xref: /btstack/src/ble/sm.c (revision f99c988a5bd418a953e55f84d9163a0d145c3106)
13deb3ec6SMatthias Ringwald /*
23deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
33deb3ec6SMatthias Ringwald  *
43deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
53deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
63deb3ec6SMatthias Ringwald  * are met:
73deb3ec6SMatthias Ringwald  *
83deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
93deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
103deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
113deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
123deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
133deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
143deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
153deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
163deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
173deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
183deb3ec6SMatthias Ringwald  *    monetary gain.
193deb3ec6SMatthias Ringwald  *
203deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
213deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
253deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
273deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
283deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
293deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
303deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
323deb3ec6SMatthias Ringwald  *
333deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
343deb3ec6SMatthias Ringwald  * [email protected]
353deb3ec6SMatthias Ringwald  *
363deb3ec6SMatthias Ringwald  */
37ab2c6ae4SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "sm.c"
393deb3ec6SMatthias Ringwald 
403deb3ec6SMatthias Ringwald #include <string.h>
413deb3ec6SMatthias Ringwald #include <inttypes.h>
423deb3ec6SMatthias Ringwald 
433edc84c5SMatthias Ringwald #include "ble/le_device_db.h"
4459c6af15SMatthias Ringwald #include "ble/core.h"
453edc84c5SMatthias Ringwald #include "ble/sm.h"
4661f37892SMatthias Ringwald #include "bluetooth_company_id.h"
47d7f1c72eSMatthias Ringwald #include "btstack_bool.h"
48d1a1f6a4SMatthias Ringwald #include "btstack_crypto.h"
490e2df43fSMatthias Ringwald #include "btstack_debug.h"
500e2df43fSMatthias Ringwald #include "btstack_event.h"
510e2df43fSMatthias Ringwald #include "btstack_linked_list.h"
520e2df43fSMatthias Ringwald #include "btstack_memory.h"
53899e6e02SMatthias Ringwald #include "btstack_tlv.h"
54f7a05cdaSMatthias Ringwald #include "gap.h"
550e2df43fSMatthias Ringwald #include "hci.h"
5613377825SMatthias Ringwald #include "hci_dump.h"
570e2df43fSMatthias Ringwald #include "l2cap.h"
583deb3ec6SMatthias Ringwald 
591a682202SMatthias Ringwald #if !defined(ENABLE_LE_PERIPHERAL) && !defined(ENABLE_LE_CENTRAL)
601a682202SMatthias Ringwald #error "LE Security Manager used, but neither ENABLE_LE_PERIPHERAL nor ENABLE_LE_CENTRAL defined. Please add at least one to btstack_config.h."
611a682202SMatthias Ringwald #endif
621a682202SMatthias Ringwald 
637ece0eaaSMatthias Ringwald #if defined(ENABLE_CROSS_TRANSPORT_KEY_DERIVATION) && (!defined(ENABLE_CLASSIC) || !defined(ENABLE_LE_SECURE_CONNECTIONS))
647ece0eaaSMatthias Ringwald #error "Cross Transport Key Derivation requires support for LE Secure Connections and BR/EDR (Classic)"
656857ad8fSMatthias Ringwald #endif
666857ad8fSMatthias Ringwald 
67d1a1f6a4SMatthias Ringwald // assert SM Public Key can be sent/received
68d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
69d1a1f6a4SMatthias Ringwald #if HCI_ACL_PAYLOAD_SIZE < 69
70d1a1f6a4SMatthias Ringwald #error "HCI_ACL_PAYLOAD_SIZE must be at least 69 bytes when using LE Secure Conection. Please increase HCI_ACL_PAYLOAD_SIZE or disable ENABLE_LE_SECURE_CONNECTIONS"
71d1a1f6a4SMatthias Ringwald #endif
72d1a1f6a4SMatthias Ringwald #endif
73d1a1f6a4SMatthias Ringwald 
7442134bc6SMatthias Ringwald #if defined(ENABLE_LE_PERIPHERAL) && defined(ENABLE_LE_CENTRAL)
75cd1176f5SMatthias Ringwald #define IS_RESPONDER(role) ((role) == HCI_ROLE_SLAVE)
7642134bc6SMatthias Ringwald #else
7742134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
7842134bc6SMatthias Ringwald // only central - never responder (avoid 'unused variable' warnings)
79cd1176f5SMatthias Ringwald #define IS_RESPONDER(role) (0 && ((role) == HCI_ROLE_SLAVE))
8042134bc6SMatthias Ringwald #else
8142134bc6SMatthias Ringwald // only peripheral - always responder (avoid 'unused variable' warnings)
82cd1176f5SMatthias Ringwald #define IS_RESPONDER(role) (1 || ((role) == HCI_ROLE_SLAVE))
8342134bc6SMatthias Ringwald #endif
8442134bc6SMatthias Ringwald #endif
8542134bc6SMatthias Ringwald 
867a766ebfSMatthias Ringwald #if defined(ENABLE_LE_SIGNED_WRITE) || defined(ENABLE_LE_SECURE_CONNECTIONS)
87d1a1f6a4SMatthias Ringwald #define USE_CMAC_ENGINE
887a766ebfSMatthias Ringwald #endif
897a766ebfSMatthias Ringwald 
906857ad8fSMatthias Ringwald 
91968b2eafSMatthias Ringwald #define BTSTACK_TAG32(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
92899e6e02SMatthias Ringwald 
933deb3ec6SMatthias Ringwald //
943deb3ec6SMatthias Ringwald // SM internal types and globals
953deb3ec6SMatthias Ringwald //
963deb3ec6SMatthias Ringwald 
973deb3ec6SMatthias Ringwald typedef enum {
983deb3ec6SMatthias Ringwald     DKG_W4_WORKING,
993deb3ec6SMatthias Ringwald     DKG_CALC_IRK,
1003deb3ec6SMatthias Ringwald     DKG_CALC_DHK,
1013deb3ec6SMatthias Ringwald     DKG_READY
1023deb3ec6SMatthias Ringwald } derived_key_generation_t;
1033deb3ec6SMatthias Ringwald 
1043deb3ec6SMatthias Ringwald typedef enum {
1053deb3ec6SMatthias Ringwald     RAU_IDLE,
106fbd4e238SMatthias Ringwald     RAU_GET_RANDOM,
1073deb3ec6SMatthias Ringwald     RAU_W4_RANDOM,
1083deb3ec6SMatthias Ringwald     RAU_GET_ENC,
1093deb3ec6SMatthias Ringwald     RAU_W4_ENC,
1103deb3ec6SMatthias Ringwald } random_address_update_t;
1113deb3ec6SMatthias Ringwald 
1123deb3ec6SMatthias Ringwald typedef enum {
1133deb3ec6SMatthias Ringwald     CMAC_IDLE,
1143deb3ec6SMatthias Ringwald     CMAC_CALC_SUBKEYS,
1153deb3ec6SMatthias Ringwald     CMAC_W4_SUBKEYS,
1163deb3ec6SMatthias Ringwald     CMAC_CALC_MI,
1173deb3ec6SMatthias Ringwald     CMAC_W4_MI,
1183deb3ec6SMatthias Ringwald     CMAC_CALC_MLAST,
1193deb3ec6SMatthias Ringwald     CMAC_W4_MLAST
1203deb3ec6SMatthias Ringwald } cmac_state_t;
1213deb3ec6SMatthias Ringwald 
1223deb3ec6SMatthias Ringwald typedef enum {
1233deb3ec6SMatthias Ringwald     JUST_WORKS,
12427c32905SMatthias Ringwald     PK_RESP_INPUT,       // Initiator displays PK, responder inputs PK
12527c32905SMatthias Ringwald     PK_INIT_INPUT,       // Responder displays PK, initiator inputs PK
12647fb4255SMatthias Ringwald     PK_BOTH_INPUT,       // Only input on both, both input PK
12747fb4255SMatthias Ringwald     NUMERIC_COMPARISON,  // Only numerical compparison (yes/no) on on both sides
12847fb4255SMatthias Ringwald     OOB                  // OOB available on one (SC) or both sides (legacy)
1293deb3ec6SMatthias Ringwald } stk_generation_method_t;
1303deb3ec6SMatthias Ringwald 
1313deb3ec6SMatthias Ringwald typedef enum {
1323deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_IDLE,
1333deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_PENDING,
1343deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_CONFIRM,
1353deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_PASSKEY,
1363deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_DECLINE
1373deb3ec6SMatthias Ringwald } sm_user_response_t;
1383deb3ec6SMatthias Ringwald 
1393deb3ec6SMatthias Ringwald typedef enum {
1403deb3ec6SMatthias Ringwald     SM_AES128_IDLE,
1413deb3ec6SMatthias Ringwald     SM_AES128_ACTIVE
1423deb3ec6SMatthias Ringwald } sm_aes128_state_t;
1433deb3ec6SMatthias Ringwald 
1443deb3ec6SMatthias Ringwald typedef enum {
1453deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_IDLE,
1463deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_GENERAL,
1473deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_FOR_CONNECTION,
1483deb3ec6SMatthias Ringwald } address_resolution_mode_t;
1493deb3ec6SMatthias Ringwald 
1503deb3ec6SMatthias Ringwald typedef enum {
151a66b030fSMatthias Ringwald     ADDRESS_RESOLUTION_SUCCEEDED,
1523deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_FAILED,
1533deb3ec6SMatthias Ringwald } address_resolution_event_t;
154901c000fSMatthias Ringwald 
155901c000fSMatthias Ringwald typedef enum {
15634b6528fSMatthias Ringwald     EC_KEY_GENERATION_IDLE,
1577df18c15SMatthias Ringwald     EC_KEY_GENERATION_ACTIVE,
1587df18c15SMatthias Ringwald     EC_KEY_GENERATION_DONE,
1597df18c15SMatthias Ringwald } ec_key_generation_state_t;
1607df18c15SMatthias Ringwald 
1617df18c15SMatthias Ringwald typedef enum {
1623cf37b8cSMatthias Ringwald     SM_STATE_VAR_DHKEY_NEEDED = 1 << 0,
1633cf37b8cSMatthias Ringwald     SM_STATE_VAR_DHKEY_CALCULATED = 1 << 1,
1643cf37b8cSMatthias Ringwald     SM_STATE_VAR_DHKEY_COMMAND_RECEIVED = 1 << 2,
165901c000fSMatthias Ringwald } sm_state_var_t;
166901c000fSMatthias Ringwald 
167c59d0c92SMatthias Ringwald typedef enum {
168c59d0c92SMatthias Ringwald     SM_SC_OOB_IDLE,
169d1a1f6a4SMatthias Ringwald     SM_SC_OOB_W4_RANDOM,
170c59d0c92SMatthias Ringwald     SM_SC_OOB_W2_CALC_CONFIRM,
171c59d0c92SMatthias Ringwald     SM_SC_OOB_W4_CONFIRM,
172c59d0c92SMatthias Ringwald } sm_sc_oob_state_t;
173c59d0c92SMatthias Ringwald 
1746420f61eSMatthias Ringwald typedef uint8_t sm_key24_t[3];
1756420f61eSMatthias Ringwald typedef uint8_t sm_key56_t[7];
1766420f61eSMatthias Ringwald typedef uint8_t sm_key256_t[32];
1776420f61eSMatthias Ringwald 
1783deb3ec6SMatthias Ringwald //
1793deb3ec6SMatthias Ringwald // GLOBAL DATA
1803deb3ec6SMatthias Ringwald //
1813deb3ec6SMatthias Ringwald 
1822d2d4d3cSMatthias Ringwald static bool sm_initialized;
1832d2d4d3cSMatthias Ringwald 
184841468bbSMatthias Ringwald static bool test_use_fixed_local_csrk;
185841468bbSMatthias Ringwald static bool test_use_fixed_local_irk;
1863deb3ec6SMatthias Ringwald 
187192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
188192365feSMatthias Ringwald static uint8_t test_pairing_failure;
189192365feSMatthias Ringwald #endif
190192365feSMatthias Ringwald 
1913deb3ec6SMatthias Ringwald // configuration
1923deb3ec6SMatthias Ringwald static uint8_t sm_accepted_stk_generation_methods;
1933deb3ec6SMatthias Ringwald static uint8_t sm_max_encryption_key_size;
1943deb3ec6SMatthias Ringwald static uint8_t sm_min_encryption_key_size;
1953deb3ec6SMatthias Ringwald static uint8_t sm_auth_req = 0;
1963deb3ec6SMatthias Ringwald static uint8_t sm_io_capabilities = IO_CAPABILITY_NO_INPUT_NO_OUTPUT;
1974b8c611fSMatthias Ringwald static uint32_t sm_fixed_passkey_in_display_role;
1981979f09cSMatthias Ringwald static bool sm_reconstruct_ltk_without_le_device_db_entry;
1993deb3ec6SMatthias Ringwald 
200b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
201728f6757SMatthias Ringwald static bool sm_slave_request_security;
202b6f39a74SMatthias Ringwald #endif
203b6f39a74SMatthias Ringwald 
204c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
205c123d999SMatthias Ringwald static bool sm_sc_only_mode;
206c59d0c92SMatthias Ringwald static uint8_t sm_sc_oob_random[16];
207c59d0c92SMatthias Ringwald static void (*sm_sc_oob_callback)(const uint8_t * confirm_value, const uint8_t * random_value);
208c59d0c92SMatthias Ringwald static sm_sc_oob_state_t sm_sc_oob_state;
209db88441fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS_DEBUG_KEY
210db88441fSMatthias Ringwald static bool sm_sc_debug_keys_enabled;
211db88441fSMatthias Ringwald #endif
212c59d0c92SMatthias Ringwald #endif
213c59d0c92SMatthias Ringwald 
214899e6e02SMatthias Ringwald 
2151979f09cSMatthias Ringwald static bool                  sm_persistent_keys_random_active;
216899e6e02SMatthias Ringwald static const btstack_tlv_t * sm_tlv_impl;
217899e6e02SMatthias Ringwald static void *                sm_tlv_context;
218899e6e02SMatthias Ringwald 
2193deb3ec6SMatthias Ringwald // Security Manager Master Keys, please use sm_set_er(er) and sm_set_ir(ir) with your own 128 bit random values
2203deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_er;
2213deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_ir;
2223deb3ec6SMatthias Ringwald 
2233deb3ec6SMatthias Ringwald // derived from sm_persistent_ir
2243deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_dhk;
2253deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_irk;
2263deb3ec6SMatthias Ringwald static derived_key_generation_t dkg_state;
2273deb3ec6SMatthias Ringwald 
2283deb3ec6SMatthias Ringwald // derived from sm_persistent_er
2293deb3ec6SMatthias Ringwald // ..
2303deb3ec6SMatthias Ringwald 
2313deb3ec6SMatthias Ringwald // random address update
2323deb3ec6SMatthias Ringwald static random_address_update_t rau_state;
2333deb3ec6SMatthias Ringwald static bd_addr_t sm_random_address;
2343deb3ec6SMatthias Ringwald 
235d1a1f6a4SMatthias Ringwald #ifdef USE_CMAC_ENGINE
236514d35fcSMatthias Ringwald // CMAC Calculation: General
237d1a1f6a4SMatthias Ringwald static btstack_crypto_aes128_cmac_t sm_cmac_request;
238d1a1f6a4SMatthias Ringwald static void (*sm_cmac_done_callback)(uint8_t hash[8]);
239d1a1f6a4SMatthias Ringwald static uint8_t sm_cmac_active;
240d1a1f6a4SMatthias Ringwald static uint8_t sm_cmac_hash[16];
2417a766ebfSMatthias Ringwald #endif
242514d35fcSMatthias Ringwald 
243514d35fcSMatthias Ringwald // CMAC for ATT Signed Writes
2447a766ebfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
245d1a1f6a4SMatthias Ringwald static uint16_t        sm_cmac_signed_write_message_len;
246d1a1f6a4SMatthias Ringwald static uint8_t         sm_cmac_signed_write_header[3];
247d1a1f6a4SMatthias Ringwald static const uint8_t * sm_cmac_signed_write_message;
248d1a1f6a4SMatthias Ringwald static uint8_t         sm_cmac_signed_write_sign_counter[4];
2497a766ebfSMatthias Ringwald #endif
250514d35fcSMatthias Ringwald 
251514d35fcSMatthias Ringwald // CMAC for Secure Connection functions
252514d35fcSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
253aec94140SMatthias Ringwald static sm_connection_t * sm_cmac_connection;
254514d35fcSMatthias Ringwald static uint8_t           sm_cmac_sc_buffer[80];
255514d35fcSMatthias Ringwald #endif
2563deb3ec6SMatthias Ringwald 
2573deb3ec6SMatthias Ringwald // resolvable private address lookup / CSRK calculation
2583deb3ec6SMatthias Ringwald static int       sm_address_resolution_test;
2593deb3ec6SMatthias Ringwald static uint8_t   sm_address_resolution_addr_type;
2603deb3ec6SMatthias Ringwald static bd_addr_t sm_address_resolution_address;
2613deb3ec6SMatthias Ringwald static void *    sm_address_resolution_context;
2623deb3ec6SMatthias Ringwald static address_resolution_mode_t sm_address_resolution_mode;
2638f2a52f4SMatthias Ringwald static btstack_linked_list_t sm_address_resolution_general_queue;
2643deb3ec6SMatthias Ringwald 
265d1a1f6a4SMatthias Ringwald // aes128 crypto engine.
2663deb3ec6SMatthias Ringwald static sm_aes128_state_t  sm_aes128_state;
2673deb3ec6SMatthias Ringwald 
268d1a1f6a4SMatthias Ringwald // crypto
269d1a1f6a4SMatthias Ringwald static btstack_crypto_random_t   sm_crypto_random_request;
270d1a1f6a4SMatthias Ringwald static btstack_crypto_aes128_t   sm_crypto_aes128_request;
271d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
272d1a1f6a4SMatthias Ringwald static btstack_crypto_ecc_p256_t sm_crypto_ecc_p256_request;
2737df1ef2fSMatthias Ringwald #endif
2747df1ef2fSMatthias Ringwald 
275d1a1f6a4SMatthias Ringwald // temp storage for random data
276d1a1f6a4SMatthias Ringwald static uint8_t sm_random_data[8];
277d1a1f6a4SMatthias Ringwald static uint8_t sm_aes128_key[16];
278d1a1f6a4SMatthias Ringwald static uint8_t sm_aes128_plaintext[16];
279d1a1f6a4SMatthias Ringwald static uint8_t sm_aes128_ciphertext[16];
2803deb3ec6SMatthias Ringwald 
281a036ae12SMatthias Ringwald // to receive events
282e03e489aSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
283c5b6ce22SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
284a036ae12SMatthias Ringwald static btstack_packet_callback_registration_t l2cap_event_callback_registration;
285c5b6ce22SMatthias Ringwald #endif
286e03e489aSMatthias Ringwald 
28789a78d34SMatthias Ringwald /* to dispatch sm event */
28889a78d34SMatthias Ringwald static btstack_linked_list_t sm_event_handlers;
28989a78d34SMatthias Ringwald 
290ece00d2dSMatthias Ringwald /* to schedule calls to sm_run */
291ece00d2dSMatthias Ringwald static btstack_timer_source_t sm_run_timer;
292ece00d2dSMatthias Ringwald 
29309e4d397SMatthias Ringwald // LE Secure Connections
29409e4d397SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
29509e4d397SMatthias Ringwald static ec_key_generation_state_t ec_key_generation_state;
296fc5bff5fSMatthias Ringwald static uint8_t ec_q[64];
29709e4d397SMatthias Ringwald #endif
298df86eb96SMatthias Ringwald 
2993deb3ec6SMatthias Ringwald //
3003deb3ec6SMatthias Ringwald // Volume 3, Part H, Chapter 24
3013deb3ec6SMatthias Ringwald // "Security shall be initiated by the Security Manager in the device in the master role.
3023deb3ec6SMatthias Ringwald // The device in the slave role shall be the responding device."
3033deb3ec6SMatthias Ringwald // -> master := initiator, slave := responder
3043deb3ec6SMatthias Ringwald //
3053deb3ec6SMatthias Ringwald 
3063deb3ec6SMatthias Ringwald // data needed for security setup
3073deb3ec6SMatthias Ringwald typedef struct sm_setup_context {
3083deb3ec6SMatthias Ringwald 
309ec820d77SMatthias Ringwald     btstack_timer_source_t sm_timeout;
3103deb3ec6SMatthias Ringwald 
3113deb3ec6SMatthias Ringwald     // user response, (Phase 1 and/or 2)
3123deb3ec6SMatthias Ringwald     uint8_t   sm_user_response;
313dd4a08fbSMatthias Ringwald     uint8_t   sm_keypress_notification; // bitmap: passkey started, digit entered, digit erased, passkey cleared, passkey complete, 3 bit count
3143deb3ec6SMatthias Ringwald 
3153deb3ec6SMatthias Ringwald     // defines which keys will be send after connection is encrypted - calculated during Phase 1, used Phase 3
316715a43d1SMatthias Ringwald     uint8_t   sm_key_distribution_send_set;
317715a43d1SMatthias Ringwald     uint8_t   sm_key_distribution_sent_set;
3189a90d41aSMatthias Ringwald     uint8_t   sm_key_distribution_expected_set;
319715a43d1SMatthias Ringwald     uint8_t   sm_key_distribution_received_set;
3203deb3ec6SMatthias Ringwald 
3213deb3ec6SMatthias Ringwald     // Phase 2 (Pairing over SMP)
3223deb3ec6SMatthias Ringwald     stk_generation_method_t sm_stk_generation_method;
3233deb3ec6SMatthias Ringwald     sm_key_t  sm_tk;
324a680ba6bSMatthias Ringwald     uint8_t   sm_have_oob_data;
3256777d8fdSMatthias Ringwald     bool      sm_use_secure_connections;
3263deb3ec6SMatthias Ringwald 
3273deb3ec6SMatthias Ringwald     sm_key_t  sm_c1_t3_value;   // c1 calculation
3283deb3ec6SMatthias Ringwald     sm_pairing_packet_t sm_m_preq; // pairing request - needed only for c1
3293deb3ec6SMatthias Ringwald     sm_pairing_packet_t sm_s_pres; // pairing response - needed only for c1
3303deb3ec6SMatthias Ringwald     sm_key_t  sm_local_random;
3313deb3ec6SMatthias Ringwald     sm_key_t  sm_local_confirm;
3323deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_random;
3333deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_confirm;
3343deb3ec6SMatthias Ringwald     uint8_t   sm_m_addr_type;   // address and type can be removed
3353deb3ec6SMatthias Ringwald     uint8_t   sm_s_addr_type;   //  ''
3363deb3ec6SMatthias Ringwald     bd_addr_t sm_m_address;     //  ''
3373deb3ec6SMatthias Ringwald     bd_addr_t sm_s_address;     //  ''
3383deb3ec6SMatthias Ringwald     sm_key_t  sm_ltk;
3393deb3ec6SMatthias Ringwald 
34068437d83SMatthias Ringwald     uint8_t   sm_state_vars;
341e53be891SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
342fc5bff5fSMatthias Ringwald     uint8_t   sm_peer_q[64];    // also stores random for EC key generation during init
343446a8c36SMatthias Ringwald     sm_key_t  sm_peer_nonce;    // might be combined with sm_peer_random
344446a8c36SMatthias Ringwald     sm_key_t  sm_local_nonce;   // might be combined with sm_local_random
345d08147dfSMatthias Ringwald     uint8_t   sm_dhkey[32];
346e53be891SMatthias Ringwald     sm_key_t  sm_peer_dhkey_check;
347e53be891SMatthias Ringwald     sm_key_t  sm_local_dhkey_check;
348446a8c36SMatthias Ringwald     sm_key_t  sm_ra;
349446a8c36SMatthias Ringwald     sm_key_t  sm_rb;
3502bacf595SMatthias Ringwald     sm_key_t  sm_t;             // used for f5 and h6
351a9f29768SMatthias Ringwald     sm_key_t  sm_mackey;
3527df18c15SMatthias Ringwald     uint8_t   sm_passkey_bit;   // also stores number of generated random bytes for EC key generation
353e53be891SMatthias Ringwald #endif
35427c32905SMatthias Ringwald 
3553deb3ec6SMatthias Ringwald     // Phase 3
3563deb3ec6SMatthias Ringwald 
3573deb3ec6SMatthias Ringwald     // key distribution, we generate
3583deb3ec6SMatthias Ringwald     uint16_t  sm_local_y;
3593deb3ec6SMatthias Ringwald     uint16_t  sm_local_div;
3603deb3ec6SMatthias Ringwald     uint16_t  sm_local_ediv;
3613deb3ec6SMatthias Ringwald     uint8_t   sm_local_rand[8];
3623deb3ec6SMatthias Ringwald     sm_key_t  sm_local_ltk;
3633deb3ec6SMatthias Ringwald     sm_key_t  sm_local_csrk;
3643deb3ec6SMatthias Ringwald     sm_key_t  sm_local_irk;
3653deb3ec6SMatthias Ringwald     // sm_local_address/addr_type not needed
3663deb3ec6SMatthias Ringwald 
3673deb3ec6SMatthias Ringwald     // key distribution, received from peer
3683deb3ec6SMatthias Ringwald     uint16_t  sm_peer_y;
3693deb3ec6SMatthias Ringwald     uint16_t  sm_peer_div;
3703deb3ec6SMatthias Ringwald     uint16_t  sm_peer_ediv;
3713deb3ec6SMatthias Ringwald     uint8_t   sm_peer_rand[8];
3723deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_ltk;
3733deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_irk;
3743deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_csrk;
3753deb3ec6SMatthias Ringwald     uint8_t   sm_peer_addr_type;
3763deb3ec6SMatthias Ringwald     bd_addr_t sm_peer_address;
377715a43d1SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
378715a43d1SMatthias Ringwald     int       sm_le_device_index;
379715a43d1SMatthias Ringwald #endif
380e0a03c85SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
381e0a03c85SMatthias Ringwald     link_key_t sm_link_key;
382e0a03c85SMatthias Ringwald     link_key_type_t sm_link_key_type;
383e0a03c85SMatthias Ringwald #endif
3843deb3ec6SMatthias Ringwald } sm_setup_context_t;
3853deb3ec6SMatthias Ringwald 
3863deb3ec6SMatthias Ringwald //
3873deb3ec6SMatthias Ringwald static sm_setup_context_t the_setup;
3883deb3ec6SMatthias Ringwald static sm_setup_context_t * setup = &the_setup;
3893deb3ec6SMatthias Ringwald 
3903deb3ec6SMatthias Ringwald // active connection - the one for which the_setup is used for
3917149bde5SMatthias Ringwald static uint16_t sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
3923deb3ec6SMatthias Ringwald 
3936b65794dSMilanka Ringwald // @return 1 if oob data is available
3943deb3ec6SMatthias Ringwald // stores oob data in provided 16 byte buffer if not null
3953deb3ec6SMatthias Ringwald static int (*sm_get_oob_data)(uint8_t addres_type, bd_addr_t addr, uint8_t * oob_data) = NULL;
3964acf7b7bSMatthias Ringwald static int (*sm_get_sc_oob_data)(uint8_t addres_type, bd_addr_t addr, uint8_t * oob_sc_peer_confirm, uint8_t * oob_sc_peer_random);
397b96d60a6SMatthias Ringwald static bool (*sm_get_ltk_callback)(hci_con_handle_t con_handle, uint8_t addres_type, bd_addr_t addr, uint8_t * ltk);
3983deb3ec6SMatthias Ringwald 
3993deb3ec6SMatthias Ringwald static void sm_run(void);
4007887cd92SMatthias Ringwald static void sm_state_reset(void);
401711e6c80SMatthias Ringwald static void sm_done_for_handle(hci_con_handle_t con_handle);
402711e6c80SMatthias Ringwald static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle);
403916ea5b2SMatthias Ringwald static void sm_cache_ltk(sm_connection_t * connection, const sm_key_t ltk);
40477e2e5edSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
40577e2e5edSMatthias Ringwald static sm_connection_t * sm_get_connection_for_bd_addr_and_type(bd_addr_t address, bd_addr_type_t addr_type);
40677e2e5edSMatthias Ringwald #endif
4073deb3ec6SMatthias Ringwald static inline int sm_calc_actual_encryption_key_size(int other);
4083deb3ec6SMatthias Ringwald static int sm_validate_stk_generation_method(void);
409d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_address_resolution(void *arg);
410d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_dhk(void *arg);
411d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_irk(void *arg);
412d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_a(void *arg);
413d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_b(void *arg);
414d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_c(void *arg);
415d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_csrk(void *arg);
416d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_d(void * arg);
417d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_ltk(void *arg);
418d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_y(void *arg);
4192a526f21SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
420d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_ltk(void *arg);
421d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_y(void *arg);
4222a526f21SMatthias Ringwald #endif
423d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_stk(void *arg);
424d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_rau(void *arg);
425d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_tk(void * arg);
426d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_rau(void * arg);
427d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4286d80b495SMatthias Ringwald static void sm_cmac_message_start(const sm_key_t key, uint16_t message_len, const uint8_t * message, void (*done_callback)(uint8_t * hash));
42934b6528fSMatthias Ringwald static void sm_ec_generate_new_key(void);
4306ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_w2_cmac_for_confirmation(void * arg);
4316ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_send_pairing_random(void * arg);
4326777d8fdSMatthias Ringwald static bool sm_passkey_entry(stk_generation_method_t method);
433d1a1f6a4SMatthias Ringwald #endif
4340ccf6c9cSMatthias Ringwald static void sm_pairing_complete(sm_connection_t * sm_conn, uint8_t status, uint8_t reason);
4353deb3ec6SMatthias Ringwald 
log_info_hex16(const char * name,uint16_t value)4363deb3ec6SMatthias Ringwald static void log_info_hex16(const char * name, uint16_t value){
437cc95824cSDirk Helbig     UNUSED(name);
438cc95824cSDirk Helbig     UNUSED(value);
4393deb3ec6SMatthias Ringwald     log_info("%-6s 0x%04x", name, value);
4403deb3ec6SMatthias Ringwald }
4413deb3ec6SMatthias Ringwald 
4421fbd72c5SMatthias Ringwald // static inline uint8_t sm_pairing_packet_get_code(sm_pairing_packet_t packet){
4431fbd72c5SMatthias Ringwald //     return packet[0];
4441fbd72c5SMatthias Ringwald // }
sm_pairing_packet_get_io_capability(sm_pairing_packet_t packet)4451fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_io_capability(sm_pairing_packet_t packet){
4461fbd72c5SMatthias Ringwald     return packet[1];
4471fbd72c5SMatthias Ringwald }
sm_pairing_packet_get_oob_data_flag(sm_pairing_packet_t packet)4481fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_oob_data_flag(sm_pairing_packet_t packet){
4491fbd72c5SMatthias Ringwald     return packet[2];
4501fbd72c5SMatthias Ringwald }
sm_pairing_packet_get_auth_req(sm_pairing_packet_t packet)4511fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_auth_req(sm_pairing_packet_t packet){
4521fbd72c5SMatthias Ringwald     return packet[3];
4531fbd72c5SMatthias Ringwald }
sm_pairing_packet_get_max_encryption_key_size(sm_pairing_packet_t packet)4541fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_max_encryption_key_size(sm_pairing_packet_t packet){
4551fbd72c5SMatthias Ringwald     return packet[4];
4561fbd72c5SMatthias Ringwald }
sm_pairing_packet_get_initiator_key_distribution(sm_pairing_packet_t packet)4571fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_initiator_key_distribution(sm_pairing_packet_t packet){
4581fbd72c5SMatthias Ringwald     return packet[5];
4591fbd72c5SMatthias Ringwald }
sm_pairing_packet_get_responder_key_distribution(sm_pairing_packet_t packet)4601fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_responder_key_distribution(sm_pairing_packet_t packet){
4611fbd72c5SMatthias Ringwald     return packet[6];
4621fbd72c5SMatthias Ringwald }
4631fbd72c5SMatthias Ringwald 
sm_pairing_packet_set_code(sm_pairing_packet_t packet,uint8_t code)4641fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_code(sm_pairing_packet_t packet, uint8_t code){
4651fbd72c5SMatthias Ringwald     packet[0] = code;
4661fbd72c5SMatthias Ringwald }
sm_pairing_packet_set_io_capability(sm_pairing_packet_t packet,uint8_t io_capability)4671fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_io_capability(sm_pairing_packet_t packet, uint8_t io_capability){
4681fbd72c5SMatthias Ringwald     packet[1] = io_capability;
4691fbd72c5SMatthias Ringwald }
sm_pairing_packet_set_oob_data_flag(sm_pairing_packet_t packet,uint8_t oob_data_flag)4701fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_oob_data_flag(sm_pairing_packet_t packet, uint8_t oob_data_flag){
4711fbd72c5SMatthias Ringwald     packet[2] = oob_data_flag;
4721fbd72c5SMatthias Ringwald }
sm_pairing_packet_set_auth_req(sm_pairing_packet_t packet,uint8_t auth_req)4731fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_auth_req(sm_pairing_packet_t packet, uint8_t auth_req){
4741fbd72c5SMatthias Ringwald     packet[3] = auth_req;
4751fbd72c5SMatthias Ringwald }
sm_pairing_packet_set_max_encryption_key_size(sm_pairing_packet_t packet,uint8_t max_encryption_key_size)4761fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_max_encryption_key_size(sm_pairing_packet_t packet, uint8_t max_encryption_key_size){
4771fbd72c5SMatthias Ringwald     packet[4] = max_encryption_key_size;
4781fbd72c5SMatthias Ringwald }
sm_pairing_packet_set_initiator_key_distribution(sm_pairing_packet_t packet,uint8_t initiator_key_distribution)4791fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_initiator_key_distribution(sm_pairing_packet_t packet, uint8_t initiator_key_distribution){
4801fbd72c5SMatthias Ringwald     packet[5] = initiator_key_distribution;
4811fbd72c5SMatthias Ringwald }
sm_pairing_packet_set_responder_key_distribution(sm_pairing_packet_t packet,uint8_t responder_key_distribution)4821fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_responder_key_distribution(sm_pairing_packet_t packet, uint8_t responder_key_distribution){
4831fbd72c5SMatthias Ringwald     packet[6] = responder_key_distribution;
4841fbd72c5SMatthias Ringwald }
4851fbd72c5SMatthias Ringwald 
sm_is_null_random(uint8_t random[8])4861979f09cSMatthias Ringwald static bool sm_is_null_random(uint8_t random[8]){
48724c4191dSMatthias Ringwald     return btstack_is_null(random, 8);
4883764b551SMatthias Ringwald }
4893764b551SMatthias Ringwald 
sm_is_null_key(uint8_t * key)4901979f09cSMatthias Ringwald static bool sm_is_null_key(uint8_t * key){
49124c4191dSMatthias Ringwald     return btstack_is_null(key, 16);
4923764b551SMatthias Ringwald }
4933764b551SMatthias Ringwald 
4941c34405fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_is_ff(const uint8_t * buffer,uint16_t size)4951c34405fSMatthias Ringwald static bool sm_is_ff(const uint8_t * buffer, uint16_t size){
4961c34405fSMatthias Ringwald     uint16_t i;
4971c34405fSMatthias Ringwald     for (i=0; i < size ; i++){
4981c34405fSMatthias Ringwald         if (buffer[i] != 0xff) {
4991c34405fSMatthias Ringwald             return false;
5001c34405fSMatthias Ringwald         }
5011c34405fSMatthias Ringwald     }
5021c34405fSMatthias Ringwald     return true;
5031c34405fSMatthias Ringwald }
5041c34405fSMatthias Ringwald #endif
5051c34405fSMatthias Ringwald 
50670b44dd4SMatthias Ringwald // sm_trigger_run allows to schedule callback from main run loop // reduces stack depth
sm_run_timer_handler(btstack_timer_source_t * ts)50770b44dd4SMatthias Ringwald static void sm_run_timer_handler(btstack_timer_source_t * ts){
50870b44dd4SMatthias Ringwald 	UNUSED(ts);
50970b44dd4SMatthias Ringwald 	sm_run();
51070b44dd4SMatthias Ringwald }
sm_trigger_run(void)51170b44dd4SMatthias Ringwald static void sm_trigger_run(void){
5122d2d4d3cSMatthias Ringwald     if (!sm_initialized) return;
51384c0c5c7SMatthias Ringwald 	(void)btstack_run_loop_remove_timer(&sm_run_timer);
51470b44dd4SMatthias Ringwald 	btstack_run_loop_set_timer(&sm_run_timer, 0);
51570b44dd4SMatthias Ringwald 	btstack_run_loop_add_timer(&sm_run_timer);
51670b44dd4SMatthias Ringwald }
51770b44dd4SMatthias Ringwald 
5183deb3ec6SMatthias Ringwald // Key utils
sm_reset_tk(void)5193deb3ec6SMatthias Ringwald static void sm_reset_tk(void){
5203deb3ec6SMatthias Ringwald     int i;
5213deb3ec6SMatthias Ringwald     for (i=0;i<16;i++){
5223deb3ec6SMatthias Ringwald         setup->sm_tk[i] = 0;
5233deb3ec6SMatthias Ringwald     }
5243deb3ec6SMatthias Ringwald }
5253deb3ec6SMatthias Ringwald 
5263deb3ec6SMatthias Ringwald // "For example, if a 128-bit encryption key is 0x123456789ABCDEF0123456789ABCDEF0
5273deb3ec6SMatthias Ringwald // and it is reduced to 7 octets (56 bits), then the resulting key is 0x0000000000000000003456789ABCDEF0.""
sm_truncate_key(sm_key_t key,int max_encryption_size)5283deb3ec6SMatthias Ringwald static void sm_truncate_key(sm_key_t key, int max_encryption_size){
5293deb3ec6SMatthias Ringwald     int i;
5303deb3ec6SMatthias Ringwald     for (i = max_encryption_size ; i < 16 ; i++){
5313deb3ec6SMatthias Ringwald         key[15-i] = 0;
5323deb3ec6SMatthias Ringwald     }
5333deb3ec6SMatthias Ringwald }
5343deb3ec6SMatthias Ringwald 
535899e6e02SMatthias Ringwald // ER / IR checks
sm_er_ir_set_default(void)53621045273SMatthias Ringwald static void sm_er_ir_set_default(void){
537899e6e02SMatthias Ringwald     int i;
538899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
539899e6e02SMatthias Ringwald         sm_persistent_er[i] = 0x30 + i;
540899e6e02SMatthias Ringwald         sm_persistent_ir[i] = 0x90 + i;
541899e6e02SMatthias Ringwald     }
542899e6e02SMatthias Ringwald }
543899e6e02SMatthias Ringwald 
sm_er_is_default(void)5441d80f1e6SMatthias Ringwald static bool sm_er_is_default(void){
545899e6e02SMatthias Ringwald     int i;
546899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
5471d80f1e6SMatthias Ringwald         if (sm_persistent_er[i] != (0x30+i)) return true;
548899e6e02SMatthias Ringwald     }
5491d80f1e6SMatthias Ringwald     return false;
550899e6e02SMatthias Ringwald }
551899e6e02SMatthias Ringwald 
sm_ir_is_default(void)5521d80f1e6SMatthias Ringwald static bool sm_ir_is_default(void){
553899e6e02SMatthias Ringwald     int i;
554899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
5551d80f1e6SMatthias Ringwald         if (sm_persistent_ir[i] != (0x90+i)) return true;
556899e6e02SMatthias Ringwald     }
5571d80f1e6SMatthias Ringwald     return false;
558899e6e02SMatthias Ringwald }
559899e6e02SMatthias Ringwald 
sm_dispatch_event(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)56073102768SMatthias Ringwald static void sm_dispatch_event(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
56173102768SMatthias Ringwald     UNUSED(channel);
56273102768SMatthias Ringwald 
56373102768SMatthias Ringwald     // log event
5649da9850bSMatthias Ringwald     hci_dump_btstack_event(packet, size);
56573102768SMatthias Ringwald     // dispatch to all event handlers
56673102768SMatthias Ringwald     btstack_linked_list_iterator_t it;
56773102768SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &sm_event_handlers);
56873102768SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
56973102768SMatthias Ringwald         btstack_packet_callback_registration_t * entry = (btstack_packet_callback_registration_t*) btstack_linked_list_iterator_next(&it);
57073102768SMatthias Ringwald         entry->callback(packet_type, 0, packet, size);
57173102768SMatthias Ringwald     }
57273102768SMatthias Ringwald }
57373102768SMatthias Ringwald 
sm_setup_event_base(uint8_t * event,int event_size,uint8_t type,hci_con_handle_t con_handle,uint8_t addr_type,bd_addr_t address)57473102768SMatthias Ringwald static void sm_setup_event_base(uint8_t * event, int event_size, uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address){
57573102768SMatthias Ringwald     event[0] = type;
57673102768SMatthias Ringwald     event[1] = event_size - 2;
57773102768SMatthias Ringwald     little_endian_store_16(event, 2, con_handle);
57873102768SMatthias Ringwald     event[4] = addr_type;
57973102768SMatthias Ringwald     reverse_bd_addr(address, &event[5]);
58073102768SMatthias Ringwald }
58173102768SMatthias Ringwald 
sm_notify_client_base(uint8_t type,hci_con_handle_t con_handle,uint8_t addr_type,bd_addr_t address)58273102768SMatthias Ringwald static void sm_notify_client_base(uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address){
58373102768SMatthias Ringwald     uint8_t event[11];
58473102768SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
58573102768SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
58673102768SMatthias Ringwald }
58773102768SMatthias Ringwald 
sm_notify_client_index(uint8_t type,hci_con_handle_t con_handle,uint8_t addr_type,bd_addr_t address,uint16_t index)58873102768SMatthias Ringwald static void sm_notify_client_index(uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address, uint16_t index){
58973102768SMatthias Ringwald     // fetch addr and addr type from db, only called for valid entries
59073102768SMatthias Ringwald     bd_addr_t identity_address;
59173102768SMatthias Ringwald     int identity_address_type;
59273102768SMatthias Ringwald     le_device_db_info(index, &identity_address_type, identity_address, NULL);
59373102768SMatthias Ringwald 
59473102768SMatthias Ringwald     uint8_t event[20];
59573102768SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
59673102768SMatthias Ringwald     event[11] = identity_address_type;
59773102768SMatthias Ringwald     reverse_bd_addr(identity_address, &event[12]);
59873102768SMatthias Ringwald     little_endian_store_16(event, 18, index);
59973102768SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
60073102768SMatthias Ringwald }
60173102768SMatthias Ringwald 
sm_notify_client_status(uint8_t type,hci_con_handle_t con_handle,uint8_t addr_type,bd_addr_t address,uint8_t status)60273102768SMatthias Ringwald static void sm_notify_client_status(uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address, uint8_t status){
60373102768SMatthias Ringwald     uint8_t event[12];
60473102768SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
60573102768SMatthias Ringwald     event[11] = status;
60673102768SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
60773102768SMatthias Ringwald }
60873102768SMatthias Ringwald 
60973102768SMatthias Ringwald 
sm_reencryption_started(sm_connection_t * sm_conn)61073102768SMatthias Ringwald static void sm_reencryption_started(sm_connection_t * sm_conn){
61173102768SMatthias Ringwald 
6123ab61f77SMatthias Ringwald     if (sm_conn->sm_reencryption_active) return;
6133ab61f77SMatthias Ringwald 
6147b001f4eSMatthias Ringwald     sm_conn->sm_reencryption_active = true;
61573102768SMatthias Ringwald 
61673102768SMatthias Ringwald     int       identity_addr_type;
61773102768SMatthias Ringwald     bd_addr_t identity_addr;
6183c0e26deSMatthias Ringwald     if (sm_conn->sm_le_db_index >= 0){
6193c0e26deSMatthias Ringwald         // fetch addr and addr type from db, only called for valid entries
62073102768SMatthias Ringwald         le_device_db_info(sm_conn->sm_le_db_index, &identity_addr_type, identity_addr, NULL);
6213c0e26deSMatthias Ringwald     } else {
6223c0e26deSMatthias Ringwald         // for legacy pairing with LTK re-construction, use current peer addr
6233c0e26deSMatthias Ringwald         identity_addr_type = sm_conn->sm_peer_addr_type;
624d5529700SMatthias Ringwald         // cppcheck-suppress uninitvar ; identity_addr is reported as uninitialized although it's the destination of the memcpy
6253c0e26deSMatthias Ringwald         memcpy(identity_addr, sm_conn->sm_peer_address, 6);
6263c0e26deSMatthias Ringwald     }
62773102768SMatthias Ringwald 
62873102768SMatthias Ringwald     sm_notify_client_base(SM_EVENT_REENCRYPTION_STARTED, sm_conn->sm_handle, identity_addr_type, identity_addr);
62973102768SMatthias Ringwald }
63073102768SMatthias Ringwald 
sm_reencryption_complete(sm_connection_t * sm_conn,uint8_t status)63173102768SMatthias Ringwald static void sm_reencryption_complete(sm_connection_t * sm_conn, uint8_t status){
63273102768SMatthias Ringwald 
63360be5b21SMatthias Ringwald     if (!sm_conn->sm_reencryption_active) return;
63460be5b21SMatthias Ringwald 
6357b001f4eSMatthias Ringwald     sm_conn->sm_reencryption_active = false;
63673102768SMatthias Ringwald 
63773102768SMatthias Ringwald     int       identity_addr_type;
63873102768SMatthias Ringwald     bd_addr_t identity_addr;
6393c0e26deSMatthias Ringwald     if (sm_conn->sm_le_db_index >= 0){
6403c0e26deSMatthias Ringwald         // fetch addr and addr type from db, only called for valid entries
64173102768SMatthias Ringwald         le_device_db_info(sm_conn->sm_le_db_index, &identity_addr_type, identity_addr, NULL);
6423c0e26deSMatthias Ringwald     } else {
6433c0e26deSMatthias Ringwald         // for legacy pairing with LTK re-construction, use current peer addr
6443c0e26deSMatthias Ringwald         identity_addr_type = sm_conn->sm_peer_addr_type;
645d5529700SMatthias Ringwald         // cppcheck-suppress uninitvar ; identity_addr is reported as uninitialized although it's the destination of the memcpy
6463c0e26deSMatthias Ringwald         memcpy(identity_addr, sm_conn->sm_peer_address, 6);
6473c0e26deSMatthias Ringwald     }
64873102768SMatthias Ringwald 
64973102768SMatthias Ringwald     sm_notify_client_status(SM_EVENT_REENCRYPTION_COMPLETE, sm_conn->sm_handle, identity_addr_type, identity_addr, status);
65073102768SMatthias Ringwald }
65173102768SMatthias Ringwald 
sm_pairing_started(sm_connection_t * sm_conn)652d3c12277SMatthias Ringwald static void sm_pairing_started(sm_connection_t * sm_conn){
653d3c12277SMatthias Ringwald 
654d3c12277SMatthias Ringwald     if (sm_conn->sm_pairing_active) return;
655d3c12277SMatthias Ringwald 
656d3c12277SMatthias Ringwald     sm_conn->sm_pairing_active = true;
657d3c12277SMatthias Ringwald 
658d3c12277SMatthias Ringwald     uint8_t event[11];
659d3c12277SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), SM_EVENT_PAIRING_STARTED, sm_conn->sm_handle, setup->sm_peer_addr_type, setup->sm_peer_address);
660d3c12277SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
661d3c12277SMatthias Ringwald }
662d3c12277SMatthias Ringwald 
sm_pairing_complete(sm_connection_t * sm_conn,uint8_t status,uint8_t reason)6630ccf6c9cSMatthias Ringwald static void sm_pairing_complete(sm_connection_t * sm_conn, uint8_t status, uint8_t reason){
664f61072f5SMatthias Ringwald 
665d77906ffSMatthias Ringwald     if (!sm_conn->sm_pairing_active) return;
666d77906ffSMatthias Ringwald 
66769f82ad8SMatthias Ringwald     sm_conn->sm_pairing_active = false;
66869f82ad8SMatthias Ringwald 
6690ccf6c9cSMatthias Ringwald     uint8_t event[13];
6700ccf6c9cSMatthias Ringwald     sm_setup_event_base(event, sizeof(event), SM_EVENT_PAIRING_COMPLETE, sm_conn->sm_handle, setup->sm_peer_addr_type, setup->sm_peer_address);
6710ccf6c9cSMatthias Ringwald     event[11] = status;
6720ccf6c9cSMatthias Ringwald     event[12] = reason;
6730ccf6c9cSMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
6740ccf6c9cSMatthias Ringwald }
6750ccf6c9cSMatthias Ringwald 
6763deb3ec6SMatthias Ringwald // SMP Timeout implementation
6773deb3ec6SMatthias Ringwald 
6783deb3ec6SMatthias Ringwald // Upon transmission of the Pairing Request command or reception of the Pairing Request command,
6793deb3ec6SMatthias Ringwald // the Security Manager Timer shall be reset and started.
6803deb3ec6SMatthias Ringwald //
6813deb3ec6SMatthias Ringwald // The Security Manager Timer shall be reset when an L2CAP SMP command is queued for transmission.
6823deb3ec6SMatthias Ringwald //
6833deb3ec6SMatthias Ringwald // If the Security Manager Timer reaches 30 seconds, the procedure shall be considered to have failed,
6843deb3ec6SMatthias Ringwald // and the local higher layer shall be notified. No further SMP commands shall be sent over the L2CAP
6853deb3ec6SMatthias Ringwald // Security Manager Channel. A new SM procedure shall only be performed when a new physical link has been
6863deb3ec6SMatthias Ringwald // established.
6873deb3ec6SMatthias Ringwald 
sm_timeout_handler(btstack_timer_source_t * timer)688ec820d77SMatthias Ringwald static void sm_timeout_handler(btstack_timer_source_t * timer){
6893deb3ec6SMatthias Ringwald     log_info("SM timeout");
690c5b64319SMatthias Ringwald     sm_connection_t * sm_conn = (sm_connection_t*) btstack_run_loop_get_timer_context(timer);
6913deb3ec6SMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_TIMEOUT;
69268a18fb9SMatthias Ringwald     sm_reencryption_complete(sm_conn, ERROR_CODE_CONNECTION_TIMEOUT);
6930ccf6c9cSMatthias Ringwald     sm_pairing_complete(sm_conn, ERROR_CODE_CONNECTION_TIMEOUT, 0);
6943deb3ec6SMatthias Ringwald     sm_done_for_handle(sm_conn->sm_handle);
6953deb3ec6SMatthias Ringwald 
6963deb3ec6SMatthias Ringwald     // trigger handling of next ready connection
6973deb3ec6SMatthias Ringwald     sm_run();
6983deb3ec6SMatthias Ringwald }
sm_timeout_start(sm_connection_t * sm_conn)6993deb3ec6SMatthias Ringwald static void sm_timeout_start(sm_connection_t * sm_conn){
700528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&setup->sm_timeout);
70191a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&setup->sm_timeout, sm_conn);
702528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer_handler(&setup->sm_timeout, sm_timeout_handler);
703528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&setup->sm_timeout, 30000); // 30 seconds sm timeout
704528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&setup->sm_timeout);
7053deb3ec6SMatthias Ringwald }
sm_timeout_stop(void)7063deb3ec6SMatthias Ringwald static void sm_timeout_stop(void){
707528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&setup->sm_timeout);
7083deb3ec6SMatthias Ringwald }
sm_timeout_reset(sm_connection_t * sm_conn)7093deb3ec6SMatthias Ringwald static void sm_timeout_reset(sm_connection_t * sm_conn){
7103deb3ec6SMatthias Ringwald     sm_timeout_stop();
7113deb3ec6SMatthias Ringwald     sm_timeout_start(sm_conn);
7123deb3ec6SMatthias Ringwald }
7133deb3ec6SMatthias Ringwald 
7143deb3ec6SMatthias Ringwald // end of sm timeout
7153deb3ec6SMatthias Ringwald 
7163deb3ec6SMatthias Ringwald // GAP Random Address updates
7173deb3ec6SMatthias Ringwald static gap_random_address_type_t gap_random_adress_type;
718ec820d77SMatthias Ringwald static btstack_timer_source_t gap_random_address_update_timer;
7193deb3ec6SMatthias Ringwald static uint32_t gap_random_adress_update_period;
7203deb3ec6SMatthias Ringwald 
gap_random_address_trigger(void)7213deb3ec6SMatthias Ringwald static void gap_random_address_trigger(void){
722899e6e02SMatthias Ringwald     log_info("gap_random_address_trigger, state %u", rau_state);
723d1a1f6a4SMatthias Ringwald     if (rau_state != RAU_IDLE) return;
724fbd4e238SMatthias Ringwald     rau_state = RAU_GET_RANDOM;
72570b44dd4SMatthias Ringwald     sm_trigger_run();
7263deb3ec6SMatthias Ringwald }
7273deb3ec6SMatthias Ringwald 
gap_random_address_update_handler(btstack_timer_source_t * timer)728ec820d77SMatthias Ringwald static void gap_random_address_update_handler(btstack_timer_source_t * timer){
7299ec2630cSMatthias Ringwald     UNUSED(timer);
7309ec2630cSMatthias Ringwald 
7313deb3ec6SMatthias Ringwald     log_info("GAP Random Address Update due");
732528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&gap_random_address_update_timer, gap_random_adress_update_period);
733528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&gap_random_address_update_timer);
7343deb3ec6SMatthias Ringwald     gap_random_address_trigger();
7353deb3ec6SMatthias Ringwald }
7363deb3ec6SMatthias Ringwald 
gap_random_address_update_start(void)7373deb3ec6SMatthias Ringwald static void gap_random_address_update_start(void){
738528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer_handler(&gap_random_address_update_timer, gap_random_address_update_handler);
739528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&gap_random_address_update_timer, gap_random_adress_update_period);
740528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&gap_random_address_update_timer);
7413deb3ec6SMatthias Ringwald }
7423deb3ec6SMatthias Ringwald 
gap_random_address_update_stop(void)7433deb3ec6SMatthias Ringwald static void gap_random_address_update_stop(void){
744528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&gap_random_address_update_timer);
7453deb3ec6SMatthias Ringwald }
7463deb3ec6SMatthias Ringwald 
7473deb3ec6SMatthias Ringwald // ah(k,r) helper
7483deb3ec6SMatthias Ringwald // r = padding || r
7493deb3ec6SMatthias Ringwald // r - 24 bit value
sm_ah_r_prime(uint8_t r[3],uint8_t * r_prime)7504a6806f3SMatthias Ringwald static void sm_ah_r_prime(uint8_t r[3], uint8_t * r_prime){
7513deb3ec6SMatthias Ringwald     // r'= padding || r
7523deb3ec6SMatthias Ringwald     memset(r_prime, 0, 16);
7536535961aSMatthias Ringwald     (void)memcpy(&r_prime[13], r, 3);
7543deb3ec6SMatthias Ringwald }
7553deb3ec6SMatthias Ringwald 
7563deb3ec6SMatthias Ringwald // d1 helper
7573deb3ec6SMatthias Ringwald // d' = padding || r || d
7583deb3ec6SMatthias Ringwald // d,r - 16 bit values
sm_d1_d_prime(uint16_t d,uint16_t r,uint8_t * d1_prime)7594a6806f3SMatthias Ringwald static void sm_d1_d_prime(uint16_t d, uint16_t r, uint8_t * d1_prime){
7603deb3ec6SMatthias Ringwald     // d'= padding || r || d
7613deb3ec6SMatthias Ringwald     memset(d1_prime, 0, 16);
762f8fbdce0SMatthias Ringwald     big_endian_store_16(d1_prime, 12, r);
763f8fbdce0SMatthias Ringwald     big_endian_store_16(d1_prime, 14, d);
7643deb3ec6SMatthias Ringwald }
7653deb3ec6SMatthias Ringwald 
7663deb3ec6SMatthias Ringwald // calculate arguments for first AES128 operation in C1 function
sm_c1_t1(sm_key_t r,uint8_t preq[7],uint8_t pres[7],uint8_t iat,uint8_t rat,uint8_t * t1)7674a6806f3SMatthias Ringwald static void sm_c1_t1(sm_key_t r, uint8_t preq[7], uint8_t pres[7], uint8_t iat, uint8_t rat, uint8_t * t1){
7683deb3ec6SMatthias Ringwald 
7693deb3ec6SMatthias Ringwald     // p1 = pres || preq || rat’ || iat’
7703deb3ec6SMatthias Ringwald     // "The octet of iat’ becomes the least significant octet of p1 and the most signifi-
7713deb3ec6SMatthias Ringwald     // cant octet of pres becomes the most significant octet of p1.
7723deb3ec6SMatthias Ringwald     // For example, if the 8-bit iat’ is 0x01, the 8-bit rat’ is 0x00, the 56-bit preq
7733deb3ec6SMatthias Ringwald     // is 0x07071000000101 and the 56 bit pres is 0x05000800000302 then
7743deb3ec6SMatthias Ringwald     // p1 is 0x05000800000302070710000001010001."
7753deb3ec6SMatthias Ringwald 
7763deb3ec6SMatthias Ringwald     sm_key_t p1;
7779c80e4ccSMatthias Ringwald     reverse_56(pres, &p1[0]);
7789c80e4ccSMatthias Ringwald     reverse_56(preq, &p1[7]);
7793deb3ec6SMatthias Ringwald     p1[14] = rat;
7803deb3ec6SMatthias Ringwald     p1[15] = iat;
7818314c363SMatthias Ringwald     log_info_key("p1", p1);
7828314c363SMatthias Ringwald     log_info_key("r", r);
7833deb3ec6SMatthias Ringwald 
7843deb3ec6SMatthias Ringwald     // t1 = r xor p1
7853deb3ec6SMatthias Ringwald     int i;
7863deb3ec6SMatthias Ringwald     for (i=0;i<16;i++){
7873deb3ec6SMatthias Ringwald         t1[i] = r[i] ^ p1[i];
7883deb3ec6SMatthias Ringwald     }
7898314c363SMatthias Ringwald     log_info_key("t1", t1);
7903deb3ec6SMatthias Ringwald }
7913deb3ec6SMatthias Ringwald 
7923deb3ec6SMatthias Ringwald // calculate arguments for second AES128 operation in C1 function
sm_c1_t3(sm_key_t t2,bd_addr_t ia,bd_addr_t ra,uint8_t * t3)7934a6806f3SMatthias Ringwald static void sm_c1_t3(sm_key_t t2, bd_addr_t ia, bd_addr_t ra, uint8_t * t3){
7943deb3ec6SMatthias Ringwald      // p2 = padding || ia || ra
7953deb3ec6SMatthias Ringwald     // "The least significant octet of ra becomes the least significant octet of p2 and
7963deb3ec6SMatthias Ringwald     // the most significant octet of padding becomes the most significant octet of p2.
7973deb3ec6SMatthias Ringwald     // For example, if 48-bit ia is 0xA1A2A3A4A5A6 and the 48-bit ra is
7983deb3ec6SMatthias Ringwald     // 0xB1B2B3B4B5B6 then p2 is 0x00000000A1A2A3A4A5A6B1B2B3B4B5B6.
7993deb3ec6SMatthias Ringwald 
8003deb3ec6SMatthias Ringwald     sm_key_t p2;
801d5529700SMatthias Ringwald     // cppcheck-suppress uninitvar ; p2 is reported as uninitialized
8023deb3ec6SMatthias Ringwald     memset(p2, 0, 16);
8036535961aSMatthias Ringwald     (void)memcpy(&p2[4], ia, 6);
8046535961aSMatthias Ringwald     (void)memcpy(&p2[10], ra, 6);
8058314c363SMatthias Ringwald     log_info_key("p2", p2);
8063deb3ec6SMatthias Ringwald 
8073deb3ec6SMatthias Ringwald     // c1 = e(k, t2_xor_p2)
8083deb3ec6SMatthias Ringwald     int i;
8093deb3ec6SMatthias Ringwald     for (i=0;i<16;i++){
8103deb3ec6SMatthias Ringwald         t3[i] = t2[i] ^ p2[i];
8113deb3ec6SMatthias Ringwald     }
8128314c363SMatthias Ringwald     log_info_key("t3", t3);
8133deb3ec6SMatthias Ringwald }
8143deb3ec6SMatthias Ringwald 
sm_s1_r_prime(sm_key_t r1,sm_key_t r2,uint8_t * r_prime)8154a6806f3SMatthias Ringwald static void sm_s1_r_prime(sm_key_t r1, sm_key_t r2, uint8_t * r_prime){
8168314c363SMatthias Ringwald     log_info_key("r1", r1);
8178314c363SMatthias Ringwald     log_info_key("r2", r2);
8186535961aSMatthias Ringwald     (void)memcpy(&r_prime[8], &r2[8], 8);
8196535961aSMatthias Ringwald     (void)memcpy(&r_prime[0], &r1[8], 8);
8203deb3ec6SMatthias Ringwald }
8213deb3ec6SMatthias Ringwald 
822fbe050beSMatthias Ringwald 
8233deb3ec6SMatthias Ringwald // decide on stk generation based on
8243deb3ec6SMatthias Ringwald // - pairing request
8253deb3ec6SMatthias Ringwald // - io capabilities
8263deb3ec6SMatthias Ringwald // - OOB data availability
sm_setup_tk(void)8273deb3ec6SMatthias Ringwald static void sm_setup_tk(void){
8283deb3ec6SMatthias Ringwald 
8298334d3d8SMatthias Ringwald     // horizontal: initiator capabilities
8308334d3d8SMatthias Ringwald     // vertial:    responder capabilities
8318334d3d8SMatthias Ringwald     static const stk_generation_method_t stk_generation_method [5] [5] = {
8328334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,       PK_INIT_INPUT,   JUST_WORKS,    PK_INIT_INPUT },
8338334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,       PK_INIT_INPUT,   JUST_WORKS,    PK_INIT_INPUT },
8348334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   PK_RESP_INPUT,    PK_BOTH_INPUT,   JUST_WORKS,    PK_RESP_INPUT },
8358334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,       JUST_WORKS,      JUST_WORKS,    JUST_WORKS    },
8368334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   PK_RESP_INPUT,    PK_INIT_INPUT,   JUST_WORKS,    PK_RESP_INPUT },
8378334d3d8SMatthias Ringwald     };
8388334d3d8SMatthias Ringwald 
8398334d3d8SMatthias Ringwald     // uses numeric comparison if one side has DisplayYesNo and KeyboardDisplay combinations
8408334d3d8SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
8418334d3d8SMatthias Ringwald     static const stk_generation_method_t stk_generation_method_with_secure_connection[5][5] = {
8428334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,         PK_INIT_INPUT,   JUST_WORKS,    PK_INIT_INPUT      },
8438334d3d8SMatthias Ringwald             { JUST_WORKS,      NUMERIC_COMPARISON, PK_INIT_INPUT,   JUST_WORKS,    NUMERIC_COMPARISON },
8448334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   PK_RESP_INPUT,      PK_BOTH_INPUT,   JUST_WORKS,    PK_RESP_INPUT      },
8458334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,         JUST_WORKS,      JUST_WORKS,    JUST_WORKS         },
8468334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   NUMERIC_COMPARISON, PK_INIT_INPUT,   JUST_WORKS,    NUMERIC_COMPARISON },
8478334d3d8SMatthias Ringwald     };
8488334d3d8SMatthias Ringwald #endif
8498334d3d8SMatthias Ringwald 
8503deb3ec6SMatthias Ringwald     // default: just works
8513deb3ec6SMatthias Ringwald     setup->sm_stk_generation_method = JUST_WORKS;
8523deb3ec6SMatthias Ringwald 
85327c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
85427c32905SMatthias Ringwald     setup->sm_use_secure_connections = ( sm_pairing_packet_get_auth_req(setup->sm_m_preq)
85527c32905SMatthias Ringwald                                        & sm_pairing_packet_get_auth_req(setup->sm_s_pres)
8564ea43905SMatthias Ringwald                                        & SM_AUTHREQ_SECURE_CONNECTION ) != 0u;
85727c32905SMatthias Ringwald #else
8586777d8fdSMatthias Ringwald     setup->sm_use_secure_connections = false;
85927c32905SMatthias Ringwald #endif
86098d95509SMatthias Ringwald     log_info("Secure pairing: %u", setup->sm_use_secure_connections);
86127c32905SMatthias Ringwald 
86265a9a04eSMatthias Ringwald 
86365a9a04eSMatthias Ringwald     // decide if OOB will be used based on SC vs. Legacy and oob flags
8641979f09cSMatthias Ringwald     bool use_oob;
86565a9a04eSMatthias Ringwald     if (setup->sm_use_secure_connections){
86665a9a04eSMatthias Ringwald         // In LE Secure Connections pairing, the out of band method is used if at least
86765a9a04eSMatthias Ringwald         // one device has the peer device's out of band authentication data available.
8681979f09cSMatthias Ringwald         use_oob = (sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq) | sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres)) != 0;
86965a9a04eSMatthias Ringwald     } else {
87065a9a04eSMatthias Ringwald         // In LE legacy pairing, the out of band method is used if both the devices have
87165a9a04eSMatthias Ringwald         // the other device's out of band authentication data available.
8721979f09cSMatthias Ringwald         use_oob = (sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq) & sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres)) != 0;
87365a9a04eSMatthias Ringwald     }
87465a9a04eSMatthias Ringwald     if (use_oob){
87565a9a04eSMatthias Ringwald         log_info("SM: have OOB data");
87665a9a04eSMatthias Ringwald         log_info_key("OOB", setup->sm_tk);
87765a9a04eSMatthias Ringwald         setup->sm_stk_generation_method = OOB;
87865a9a04eSMatthias Ringwald         return;
87965a9a04eSMatthias Ringwald     }
88065a9a04eSMatthias Ringwald 
88127c32905SMatthias Ringwald     // If both devices have not set the MITM option in the Authentication Requirements
88227c32905SMatthias Ringwald     // Flags, then the IO capabilities shall be ignored and the Just Works association
88327c32905SMatthias Ringwald     // model shall be used.
8844ea43905SMatthias Ringwald     if (((sm_pairing_packet_get_auth_req(setup->sm_m_preq) & SM_AUTHREQ_MITM_PROTECTION) == 0u)
8854ea43905SMatthias Ringwald         &&  ((sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_MITM_PROTECTION) == 0u)){
88627c32905SMatthias Ringwald         log_info("SM: MITM not required by both -> JUST WORKS");
88727c32905SMatthias Ringwald         return;
88827c32905SMatthias Ringwald     }
88927c32905SMatthias Ringwald 
8903deb3ec6SMatthias Ringwald     // Reset TK as it has been setup in sm_init_setup
8913deb3ec6SMatthias Ringwald     sm_reset_tk();
8923deb3ec6SMatthias Ringwald 
8933deb3ec6SMatthias Ringwald     // Also use just works if unknown io capabilites
8948da2e96dSMatthias Ringwald     if ((sm_pairing_packet_get_io_capability(setup->sm_m_preq) > IO_CAPABILITY_KEYBOARD_DISPLAY) || (sm_pairing_packet_get_io_capability(setup->sm_s_pres) > IO_CAPABILITY_KEYBOARD_DISPLAY)){
8953deb3ec6SMatthias Ringwald         return;
8963deb3ec6SMatthias Ringwald     }
8973deb3ec6SMatthias Ringwald 
8983deb3ec6SMatthias Ringwald     // Otherwise the IO capabilities of the devices shall be used to determine the
8993deb3ec6SMatthias Ringwald     // pairing method as defined in Table 2.4.
90027c32905SMatthias Ringwald     // see http://stackoverflow.com/a/1052837/393697 for how to specify pointer to 2-dimensional array
90127c32905SMatthias Ringwald     const stk_generation_method_t (*generation_method)[5] = stk_generation_method;
90227c32905SMatthias Ringwald 
90327c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
904c6b7cbd9SMatthias Ringwald     // table not define by default
90527c32905SMatthias Ringwald     if (setup->sm_use_secure_connections){
90627c32905SMatthias Ringwald         generation_method = stk_generation_method_with_secure_connection;
90727c32905SMatthias Ringwald     }
90827c32905SMatthias Ringwald #endif
90927c32905SMatthias Ringwald     setup->sm_stk_generation_method = generation_method[sm_pairing_packet_get_io_capability(setup->sm_s_pres)][sm_pairing_packet_get_io_capability(setup->sm_m_preq)];
91027c32905SMatthias Ringwald 
9113deb3ec6SMatthias Ringwald     log_info("sm_setup_tk: master io cap: %u, slave io cap: %u -> method %u",
9121ad129beSMatthias Ringwald         sm_pairing_packet_get_io_capability(setup->sm_m_preq), sm_pairing_packet_get_io_capability(setup->sm_s_pres), setup->sm_stk_generation_method);
9133deb3ec6SMatthias Ringwald }
9143deb3ec6SMatthias Ringwald 
sm_key_distribution_flags_for_set(uint8_t key_set)9153deb3ec6SMatthias Ringwald static int sm_key_distribution_flags_for_set(uint8_t key_set){
9163deb3ec6SMatthias Ringwald     int flags = 0;
917f688bdb8SMatthias Ringwald     if ((key_set & SM_KEYDIST_ENC_KEY) != 0u){
9183deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
9193deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
9203deb3ec6SMatthias Ringwald     }
921f688bdb8SMatthias Ringwald     if ((key_set & SM_KEYDIST_ID_KEY) != 0u){
9223deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
9233deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
9243deb3ec6SMatthias Ringwald     }
925f688bdb8SMatthias Ringwald     if ((key_set & SM_KEYDIST_SIGN) != 0u){
9263deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
9273deb3ec6SMatthias Ringwald     }
9283deb3ec6SMatthias Ringwald     return flags;
9293deb3ec6SMatthias Ringwald }
9303deb3ec6SMatthias Ringwald 
sm_setup_key_distribution(uint8_t keys_to_send,uint8_t keys_to_receive)9319a90d41aSMatthias Ringwald static void sm_setup_key_distribution(uint8_t keys_to_send, uint8_t keys_to_receive){
9323deb3ec6SMatthias Ringwald     setup->sm_key_distribution_received_set = 0;
9339a90d41aSMatthias Ringwald     setup->sm_key_distribution_expected_set = sm_key_distribution_flags_for_set(keys_to_receive);
9349a90d41aSMatthias Ringwald     setup->sm_key_distribution_send_set = sm_key_distribution_flags_for_set(keys_to_send);
935715a43d1SMatthias Ringwald     setup->sm_key_distribution_sent_set = 0;
9369790be5fSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
937715a43d1SMatthias Ringwald     setup->sm_le_device_index = -1;
9389790be5fSMatthias Ringwald #endif
9393deb3ec6SMatthias Ringwald }
9403deb3ec6SMatthias Ringwald 
9413deb3ec6SMatthias Ringwald // CSRK Key Lookup
9423deb3ec6SMatthias Ringwald 
9433deb3ec6SMatthias Ringwald 
sm_address_resolution_idle(void)9441d80f1e6SMatthias Ringwald static bool sm_address_resolution_idle(void){
9453deb3ec6SMatthias Ringwald     return sm_address_resolution_mode == ADDRESS_RESOLUTION_IDLE;
9463deb3ec6SMatthias Ringwald }
9473deb3ec6SMatthias Ringwald 
sm_address_resolution_start_lookup(uint8_t addr_type,hci_con_handle_t con_handle,bd_addr_t addr,address_resolution_mode_t mode,void * context)948711e6c80SMatthias Ringwald static void sm_address_resolution_start_lookup(uint8_t addr_type, hci_con_handle_t con_handle, bd_addr_t addr, address_resolution_mode_t mode, void * context){
9496535961aSMatthias Ringwald     (void)memcpy(sm_address_resolution_address, addr, 6);
9503deb3ec6SMatthias Ringwald     sm_address_resolution_addr_type = addr_type;
9513deb3ec6SMatthias Ringwald     sm_address_resolution_test = 0;
9523deb3ec6SMatthias Ringwald     sm_address_resolution_mode = mode;
9533deb3ec6SMatthias Ringwald     sm_address_resolution_context = context;
954711e6c80SMatthias Ringwald     sm_notify_client_base(SM_EVENT_IDENTITY_RESOLVING_STARTED, con_handle, addr_type, addr);
9553deb3ec6SMatthias Ringwald }
9563deb3ec6SMatthias Ringwald 
sm_address_resolution_lookup(uint8_t address_type,bd_addr_t address)9573deb3ec6SMatthias Ringwald int sm_address_resolution_lookup(uint8_t address_type, bd_addr_t address){
9583deb3ec6SMatthias Ringwald     // check if already in list
959665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
9603deb3ec6SMatthias Ringwald     sm_lookup_entry_t * entry;
961665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &sm_address_resolution_general_queue);
962665d90f2SMatthias Ringwald     while(btstack_linked_list_iterator_has_next(&it)){
963665d90f2SMatthias Ringwald         entry = (sm_lookup_entry_t *) btstack_linked_list_iterator_next(&it);
9643deb3ec6SMatthias Ringwald         if (entry->address_type != address_type) continue;
965f688bdb8SMatthias Ringwald         if (memcmp(entry->address, address, 6) != 0)  continue;
9663deb3ec6SMatthias Ringwald         // already in list
9673deb3ec6SMatthias Ringwald         return BTSTACK_BUSY;
9683deb3ec6SMatthias Ringwald     }
9693deb3ec6SMatthias Ringwald     entry = btstack_memory_sm_lookup_entry_get();
9703deb3ec6SMatthias Ringwald     if (!entry) return BTSTACK_MEMORY_ALLOC_FAILED;
9713deb3ec6SMatthias Ringwald     entry->address_type = (bd_addr_type_t) address_type;
9726535961aSMatthias Ringwald     (void)memcpy(entry->address, address, 6);
973665d90f2SMatthias Ringwald     btstack_linked_list_add(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
97470b44dd4SMatthias Ringwald     sm_trigger_run();
9753deb3ec6SMatthias Ringwald     return 0;
9763deb3ec6SMatthias Ringwald }
9773deb3ec6SMatthias Ringwald 
978d1a1f6a4SMatthias Ringwald // CMAC calculation using AES Engineq
979d1a1f6a4SMatthias Ringwald #ifdef USE_CMAC_ENGINE
980514d35fcSMatthias Ringwald 
sm_cmac_done_trampoline(void * arg)981d1a1f6a4SMatthias Ringwald static void sm_cmac_done_trampoline(void * arg){
982d1a1f6a4SMatthias Ringwald     UNUSED(arg);
983d1a1f6a4SMatthias Ringwald     sm_cmac_active = 0;
984d1a1f6a4SMatthias Ringwald     (*sm_cmac_done_callback)(sm_cmac_hash);
98570b44dd4SMatthias Ringwald     sm_trigger_run();
9863deb3ec6SMatthias Ringwald }
987514d35fcSMatthias Ringwald 
sm_cmac_ready(void)9884dfd504aSMatthias Ringwald int sm_cmac_ready(void){
9894ea43905SMatthias Ringwald     return sm_cmac_active == 0u;
9903deb3ec6SMatthias Ringwald }
9916d80b495SMatthias Ringwald #endif
9923deb3ec6SMatthias Ringwald 
9936d80b495SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
994514d35fcSMatthias Ringwald // generic cmac calculation
sm_cmac_message_start(const sm_key_t key,uint16_t message_len,const uint8_t * message,void (* done_callback)(uint8_t * hash))995d1a1f6a4SMatthias Ringwald static void sm_cmac_message_start(const sm_key_t key, uint16_t message_len, const uint8_t * message, void (*done_callback)(uint8_t * hash)){
996d1a1f6a4SMatthias Ringwald     sm_cmac_active = 1;
997d1a1f6a4SMatthias Ringwald     sm_cmac_done_callback = done_callback;
998d1a1f6a4SMatthias Ringwald     btstack_crypto_aes128_cmac_message(&sm_cmac_request, key, message_len, message, sm_cmac_hash, sm_cmac_done_trampoline, NULL);
9993deb3ec6SMatthias Ringwald }
10007a766ebfSMatthias Ringwald #endif
10013deb3ec6SMatthias Ringwald 
1002514d35fcSMatthias Ringwald // cmac for ATT Message signing
10037a766ebfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
1004d1a1f6a4SMatthias Ringwald 
sm_cmac_generator_start(const sm_key_t key,uint16_t message_len,uint8_t (* get_byte_callback)(uint16_t offset),void (* done_callback)(uint8_t * hash))1005d1a1f6a4SMatthias Ringwald static void sm_cmac_generator_start(const sm_key_t key, uint16_t message_len, uint8_t (*get_byte_callback)(uint16_t offset), void (*done_callback)(uint8_t * hash)){
1006d1a1f6a4SMatthias Ringwald     sm_cmac_active = 1;
1007d1a1f6a4SMatthias Ringwald     sm_cmac_done_callback = done_callback;
1008d1a1f6a4SMatthias Ringwald     btstack_crypto_aes128_cmac_generator(&sm_cmac_request, key, message_len, get_byte_callback, sm_cmac_hash, sm_cmac_done_trampoline, NULL);
1009d1a1f6a4SMatthias Ringwald }
1010d1a1f6a4SMatthias Ringwald 
sm_cmac_signed_write_message_get_byte(uint16_t offset)10114dfd504aSMatthias Ringwald static uint8_t sm_cmac_signed_write_message_get_byte(uint16_t offset){
1012d1a1f6a4SMatthias Ringwald     if (offset >= sm_cmac_signed_write_message_len) {
1013d1a1f6a4SMatthias Ringwald         log_error("sm_cmac_signed_write_message_get_byte. out of bounds, access %u, len %u", offset, sm_cmac_signed_write_message_len);
10144dfd504aSMatthias Ringwald         return 0;
10154dfd504aSMatthias Ringwald     }
10164dfd504aSMatthias Ringwald 
1017d1a1f6a4SMatthias Ringwald     offset = sm_cmac_signed_write_message_len - 1 - offset;
10184dfd504aSMatthias Ringwald 
1019d1a1f6a4SMatthias Ringwald     // sm_cmac_signed_write_header[3] | message[] | sm_cmac_signed_write_sign_counter[4]
10204dfd504aSMatthias Ringwald     if (offset < 3){
1021d1a1f6a4SMatthias Ringwald         return sm_cmac_signed_write_header[offset];
10224dfd504aSMatthias Ringwald     }
1023d1a1f6a4SMatthias Ringwald     int actual_message_len_incl_header = sm_cmac_signed_write_message_len - 4;
10244dfd504aSMatthias Ringwald     if (offset <  actual_message_len_incl_header){
1025d1a1f6a4SMatthias Ringwald         return sm_cmac_signed_write_message[offset - 3];
10264dfd504aSMatthias Ringwald     }
1027d1a1f6a4SMatthias Ringwald     return sm_cmac_signed_write_sign_counter[offset - actual_message_len_incl_header];
10284dfd504aSMatthias Ringwald }
10294dfd504aSMatthias Ringwald 
sm_cmac_signed_write_start(const sm_key_t k,uint8_t opcode,hci_con_handle_t con_handle,uint16_t message_len,const uint8_t * message,uint32_t sign_counter,void (* done_handler)(uint8_t * hash))10304dfd504aSMatthias Ringwald void sm_cmac_signed_write_start(const sm_key_t k, uint8_t opcode, hci_con_handle_t con_handle, uint16_t message_len, const uint8_t * message, uint32_t sign_counter, void (*done_handler)(uint8_t * hash)){
1031514d35fcSMatthias Ringwald     // ATT Message Signing
1032d1a1f6a4SMatthias Ringwald     sm_cmac_signed_write_header[0] = opcode;
1033d1a1f6a4SMatthias Ringwald     little_endian_store_16(sm_cmac_signed_write_header, 1, con_handle);
1034d1a1f6a4SMatthias Ringwald     little_endian_store_32(sm_cmac_signed_write_sign_counter, 0, sign_counter);
1035514d35fcSMatthias Ringwald     uint16_t total_message_len = 3 + message_len + 4;  // incl. virtually prepended att opcode, handle and appended sign_counter in LE
1036d1a1f6a4SMatthias Ringwald     sm_cmac_signed_write_message     = message;
1037d1a1f6a4SMatthias Ringwald     sm_cmac_signed_write_message_len = total_message_len;
1038d1a1f6a4SMatthias Ringwald     sm_cmac_generator_start(k, total_message_len, &sm_cmac_signed_write_message_get_byte, done_handler);
10393deb3ec6SMatthias Ringwald }
10407a766ebfSMatthias Ringwald #endif
10413deb3ec6SMatthias Ringwald 
sm_trigger_user_response_basic(sm_connection_t * sm_conn,uint8_t event_type)1042ea9b6796SMatthias Ringwald static void sm_trigger_user_response_basic(sm_connection_t * sm_conn, uint8_t event_type){
1043ea9b6796SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_PENDING;
10445baa755bSMatthias Ringwald     uint8_t event[12];
1045f6a153d5SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), event_type, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
10465baa755bSMatthias Ringwald     event[11] = setup->sm_use_secure_connections ? 1 : 0;
1047f6a153d5SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
1048ea9b6796SMatthias Ringwald }
1049ea9b6796SMatthias Ringwald 
sm_trigger_user_response_passkey(sm_connection_t * sm_conn,uint8_t event_type)105074b4d42aSMatthias Ringwald static void sm_trigger_user_response_passkey(sm_connection_t * sm_conn, uint8_t event_type){
10515baa755bSMatthias Ringwald     uint8_t event[16];
1052f6a153d5SMatthias Ringwald     uint32_t passkey = big_endian_read_32(setup->sm_tk, 12);
105374b4d42aSMatthias Ringwald     sm_setup_event_base(event, sizeof(event), event_type, sm_conn->sm_handle,
1054f6a153d5SMatthias Ringwald                         sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
10555baa755bSMatthias Ringwald     event[11] = setup->sm_use_secure_connections ? 1 : 0;
10565baa755bSMatthias Ringwald     little_endian_store_32(event, 12, passkey);
1057f6a153d5SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
1058ea9b6796SMatthias Ringwald }
1059ea9b6796SMatthias Ringwald 
sm_trigger_user_response(sm_connection_t * sm_conn)10603deb3ec6SMatthias Ringwald static void sm_trigger_user_response(sm_connection_t * sm_conn){
1061446a8c36SMatthias Ringwald     // notify client for: JUST WORKS confirm, Numeric comparison confirm, PASSKEY display or input
10623deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_IDLE;
1063d77906ffSMatthias Ringwald     sm_conn->sm_pairing_active = true;
10643deb3ec6SMatthias Ringwald     switch (setup->sm_stk_generation_method){
10653deb3ec6SMatthias Ringwald         case PK_RESP_INPUT:
106642134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1067ea9b6796SMatthias Ringwald                 sm_trigger_user_response_basic(sm_conn, SM_EVENT_PASSKEY_INPUT_NUMBER);
10683deb3ec6SMatthias Ringwald             } else {
106974b4d42aSMatthias Ringwald                 sm_trigger_user_response_passkey(sm_conn, SM_EVENT_PASSKEY_DISPLAY_NUMBER);
10703deb3ec6SMatthias Ringwald             }
10713deb3ec6SMatthias Ringwald             break;
10723deb3ec6SMatthias Ringwald         case PK_INIT_INPUT:
107342134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
107474b4d42aSMatthias Ringwald                 sm_trigger_user_response_passkey(sm_conn, SM_EVENT_PASSKEY_DISPLAY_NUMBER);
10753deb3ec6SMatthias Ringwald             } else {
1076ea9b6796SMatthias Ringwald                 sm_trigger_user_response_basic(sm_conn, SM_EVENT_PASSKEY_INPUT_NUMBER);
10773deb3ec6SMatthias Ringwald             }
10783deb3ec6SMatthias Ringwald             break;
107947fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
1080ea9b6796SMatthias Ringwald             sm_trigger_user_response_basic(sm_conn, SM_EVENT_PASSKEY_INPUT_NUMBER);
10813deb3ec6SMatthias Ringwald             break;
108247fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
108374b4d42aSMatthias Ringwald             sm_trigger_user_response_passkey(sm_conn, SM_EVENT_NUMERIC_COMPARISON_REQUEST);
108427c32905SMatthias Ringwald             break;
10853deb3ec6SMatthias Ringwald         case JUST_WORKS:
1086ea9b6796SMatthias Ringwald             sm_trigger_user_response_basic(sm_conn, SM_EVENT_JUST_WORKS_REQUEST);
10873deb3ec6SMatthias Ringwald             break;
10883deb3ec6SMatthias Ringwald         case OOB:
10893deb3ec6SMatthias Ringwald             // client already provided OOB data, let's skip notification.
10903deb3ec6SMatthias Ringwald             break;
10917bbeb3adSMilanka Ringwald         default:
10927bbeb3adSMilanka Ringwald             btstack_assert(false);
10937bbeb3adSMilanka Ringwald             break;
10943deb3ec6SMatthias Ringwald     }
10953deb3ec6SMatthias Ringwald }
10963deb3ec6SMatthias Ringwald 
sm_key_distribution_all_received(void)109761d1a45eSMatthias Ringwald static bool sm_key_distribution_all_received(void) {
10985fa700b1SMatthias Ringwald     log_debug("sm_key_distribution_all_received: received 0x%02x, expecting 0x%02x", setup->sm_key_distribution_received_set, setup->sm_key_distribution_expected_set);
1099b2296177SMatthias Ringwald     return (setup->sm_key_distribution_expected_set & setup->sm_key_distribution_received_set) == setup->sm_key_distribution_expected_set;
11003deb3ec6SMatthias Ringwald }
11013deb3ec6SMatthias Ringwald 
sm_done_for_handle(hci_con_handle_t con_handle)1102711e6c80SMatthias Ringwald static void sm_done_for_handle(hci_con_handle_t con_handle){
11037149bde5SMatthias Ringwald     if (sm_active_connection_handle == con_handle){
11043deb3ec6SMatthias Ringwald         sm_timeout_stop();
11057149bde5SMatthias Ringwald         sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
1106711e6c80SMatthias Ringwald         log_info("sm: connection 0x%x released setup context", con_handle);
1107c085d9ffSMatthias Ringwald 
1108c085d9ffSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
1109c085d9ffSMatthias Ringwald         // generate new ec key after each pairing (that used it)
1110c085d9ffSMatthias Ringwald         if (setup->sm_use_secure_connections){
1111c085d9ffSMatthias Ringwald             sm_ec_generate_new_key();
1112c085d9ffSMatthias Ringwald         }
1113c085d9ffSMatthias Ringwald #endif
11143deb3ec6SMatthias Ringwald     }
11153deb3ec6SMatthias Ringwald }
11163deb3ec6SMatthias Ringwald 
sm_master_pairing_success(sm_connection_t * connection)11177d1c0c3aSMatthias Ringwald static void sm_master_pairing_success(sm_connection_t *connection) {// master -> all done
11181dca9d8aSMatthias Ringwald     connection->sm_engine_state = SM_INITIATOR_CONNECTED;
11190ccf6c9cSMatthias Ringwald     sm_pairing_complete(connection, ERROR_CODE_SUCCESS, 0);
11201dca9d8aSMatthias Ringwald     sm_done_for_handle(connection->sm_handle);
11211dca9d8aSMatthias Ringwald }
11221dca9d8aSMatthias Ringwald 
sm_key_distribution_flags_for_auth_req(void)11233deb3ec6SMatthias Ringwald static int sm_key_distribution_flags_for_auth_req(void){
1124bb09604fSMatthias Ringwald 
1125bb09604fSMatthias Ringwald     int flags = SM_KEYDIST_ID_KEY;
1126f688bdb8SMatthias Ringwald     if ((sm_auth_req & SM_AUTHREQ_BONDING) != 0u){
1127bb09604fSMatthias Ringwald         // encryption and signing information only if bonding requested
11283deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_ENC_KEY;
1129bb09604fSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
1130bb09604fSMatthias Ringwald         flags |= SM_KEYDIST_SIGN;
1131bb09604fSMatthias Ringwald #endif
11327ece0eaaSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
1133b2072c76SMatthias Ringwald         // LinkKey for CTKD requires SC and BR/EDR Support
1134b2072c76SMatthias Ringwald         if (hci_classic_supported() && ((sm_auth_req & SM_AUTHREQ_SECURE_CONNECTION) != 0)){
11357ece0eaaSMatthias Ringwald         	flags |= SM_KEYDIST_LINK_KEY;
11367ece0eaaSMatthias Ringwald         }
11377ece0eaaSMatthias Ringwald #endif
11383deb3ec6SMatthias Ringwald     }
11393deb3ec6SMatthias Ringwald     return flags;
11403deb3ec6SMatthias Ringwald }
11413deb3ec6SMatthias Ringwald 
sm_reset_setup(void)1142d7471931SMatthias Ringwald static void sm_reset_setup(void){
11433deb3ec6SMatthias Ringwald     // fill in sm setup
1144901c000fSMatthias Ringwald     setup->sm_state_vars = 0;
1145dd4a08fbSMatthias Ringwald     setup->sm_keypress_notification = 0;
1146d0ea782aSMatthias Ringwald     setup->sm_have_oob_data = 0;
11473deb3ec6SMatthias Ringwald     sm_reset_tk();
1148d7471931SMatthias Ringwald }
1149d7471931SMatthias Ringwald 
sm_init_setup(sm_connection_t * sm_conn)1150d7471931SMatthias Ringwald static void sm_init_setup(sm_connection_t * sm_conn){
1151d7471931SMatthias Ringwald     // fill in sm setup
11523deb3ec6SMatthias Ringwald     setup->sm_peer_addr_type = sm_conn->sm_peer_addr_type;
11536535961aSMatthias Ringwald     (void)memcpy(setup->sm_peer_address, sm_conn->sm_peer_address, 6);
11543deb3ec6SMatthias Ringwald 
1155a680ba6bSMatthias Ringwald     // query client for Legacy Pairing OOB data
11569305033eSMatthias Ringwald     if (sm_get_oob_data != NULL) {
1157a680ba6bSMatthias Ringwald         setup->sm_have_oob_data = (*sm_get_oob_data)(sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, setup->sm_tk);
11583deb3ec6SMatthias Ringwald     }
11593deb3ec6SMatthias Ringwald 
1160a680ba6bSMatthias Ringwald     // if available and SC supported, also ask for SC OOB Data
1161a680ba6bSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
11624acf7b7bSMatthias Ringwald     memset(setup->sm_ra, 0, 16);
11634acf7b7bSMatthias Ringwald     memset(setup->sm_rb, 0, 16);
1164a680ba6bSMatthias Ringwald     if (setup->sm_have_oob_data && (sm_auth_req & SM_AUTHREQ_SECURE_CONNECTION)){
11659305033eSMatthias Ringwald         if (sm_get_sc_oob_data != NULL){
11664acf7b7bSMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1167a680ba6bSMatthias Ringwald                 setup->sm_have_oob_data = (*sm_get_sc_oob_data)(
1168a680ba6bSMatthias Ringwald                     sm_conn->sm_peer_addr_type,
1169a680ba6bSMatthias Ringwald                     sm_conn->sm_peer_address,
1170a680ba6bSMatthias Ringwald                     setup->sm_peer_confirm,
11714acf7b7bSMatthias Ringwald                     setup->sm_ra);
11724acf7b7bSMatthias Ringwald             } else {
11734acf7b7bSMatthias Ringwald                 setup->sm_have_oob_data = (*sm_get_sc_oob_data)(
11744acf7b7bSMatthias Ringwald                     sm_conn->sm_peer_addr_type,
11754acf7b7bSMatthias Ringwald                     sm_conn->sm_peer_address,
11764acf7b7bSMatthias Ringwald                     setup->sm_peer_confirm,
11774acf7b7bSMatthias Ringwald                     setup->sm_rb);
11784acf7b7bSMatthias Ringwald             }
1179a680ba6bSMatthias Ringwald         } else {
1180a680ba6bSMatthias Ringwald             setup->sm_have_oob_data = 0;
1181a680ba6bSMatthias Ringwald         }
1182a680ba6bSMatthias Ringwald     }
1183a680ba6bSMatthias Ringwald #endif
1184a680ba6bSMatthias Ringwald 
11853deb3ec6SMatthias Ringwald     sm_pairing_packet_t * local_packet;
118642134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
11873deb3ec6SMatthias Ringwald         // slave
11883deb3ec6SMatthias Ringwald         local_packet = &setup->sm_s_pres;
11893deb3ec6SMatthias Ringwald         setup->sm_m_addr_type = sm_conn->sm_peer_addr_type;
1190d5314cbeSMatthias Ringwald         setup->sm_s_addr_type = sm_conn->sm_own_addr_type;
11916535961aSMatthias Ringwald         (void)memcpy(setup->sm_m_address, sm_conn->sm_peer_address, 6);
1192d5314cbeSMatthias Ringwald         (void)memcpy(setup->sm_s_address, sm_conn->sm_own_address, 6);
11933deb3ec6SMatthias Ringwald     } else {
11943deb3ec6SMatthias Ringwald         // master
11953deb3ec6SMatthias Ringwald         local_packet = &setup->sm_m_preq;
11963deb3ec6SMatthias Ringwald         setup->sm_s_addr_type = sm_conn->sm_peer_addr_type;
1197d5314cbeSMatthias Ringwald         setup->sm_m_addr_type = sm_conn->sm_own_addr_type;
11986535961aSMatthias Ringwald         (void)memcpy(setup->sm_s_address, sm_conn->sm_peer_address, 6);
1199d5314cbeSMatthias Ringwald         (void)memcpy(setup->sm_m_address, sm_conn->sm_own_address, 6);
12003deb3ec6SMatthias Ringwald 
1201d0ea782aSMatthias Ringwald         uint8_t key_distribution_flags = sm_key_distribution_flags_for_auth_req();
12021ad129beSMatthias Ringwald         sm_pairing_packet_set_initiator_key_distribution(setup->sm_m_preq, key_distribution_flags);
12031ad129beSMatthias Ringwald         sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags);
12043deb3ec6SMatthias Ringwald     }
12053deb3ec6SMatthias Ringwald 
12064361507fSMatthias Ringwald     log_info("our  address %s type %u", bd_addr_to_str(sm_conn->sm_own_address), sm_conn->sm_own_addr_type);
12074361507fSMatthias Ringwald     log_info("peer address %s type %u", bd_addr_to_str(sm_conn->sm_peer_address), sm_conn->sm_peer_addr_type);
12084361507fSMatthias Ringwald 
120957132f12SMatthias Ringwald     uint8_t auth_req = sm_auth_req & ~SM_AUTHREQ_CT2;
1210d0ea782aSMatthias Ringwald     uint8_t max_encryption_key_size = sm_max_encryption_key_size;
12112c041b42SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12122c041b42SMatthias Ringwald     // enable SC for SC only mode
12132c041b42SMatthias Ringwald     if (sm_sc_only_mode){
12142c041b42SMatthias Ringwald         auth_req |= SM_AUTHREQ_SECURE_CONNECTION;
1215d0ea782aSMatthias Ringwald         max_encryption_key_size = 16;
12162c041b42SMatthias Ringwald     }
12172c041b42SMatthias Ringwald #endif
121857132f12SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
121957132f12SMatthias Ringwald 	// set CT2 if SC + Bonding + CTKD
122057132f12SMatthias Ringwald 	const uint8_t auth_req_for_ct2 = SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING;
122157132f12SMatthias Ringwald 	if ((auth_req & auth_req_for_ct2) == auth_req_for_ct2){
122257132f12SMatthias Ringwald 		auth_req |= SM_AUTHREQ_CT2;
122357132f12SMatthias Ringwald 	}
122457132f12SMatthias Ringwald #endif
12251ad129beSMatthias Ringwald     sm_pairing_packet_set_io_capability(*local_packet, sm_io_capabilities);
1226a680ba6bSMatthias Ringwald     sm_pairing_packet_set_oob_data_flag(*local_packet, setup->sm_have_oob_data);
1227df86eb96SMatthias Ringwald     sm_pairing_packet_set_auth_req(*local_packet, auth_req);
1228d0ea782aSMatthias Ringwald     sm_pairing_packet_set_max_encryption_key_size(*local_packet, max_encryption_key_size);
12293deb3ec6SMatthias Ringwald }
12303deb3ec6SMatthias Ringwald 
sm_stk_generation_init(sm_connection_t * sm_conn)12313deb3ec6SMatthias Ringwald static int sm_stk_generation_init(sm_connection_t * sm_conn){
12323deb3ec6SMatthias Ringwald 
12333deb3ec6SMatthias Ringwald     sm_pairing_packet_t * remote_packet;
12349a90d41aSMatthias Ringwald     uint8_t               keys_to_send;
12359a90d41aSMatthias Ringwald     uint8_t               keys_to_receive;
123642134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
123752f9cf63SMatthias Ringwald         // slave / responder
12383deb3ec6SMatthias Ringwald         remote_packet   = &setup->sm_m_preq;
12399a90d41aSMatthias Ringwald         keys_to_send    = sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq);
12409a90d41aSMatthias Ringwald         keys_to_receive = sm_pairing_packet_get_initiator_key_distribution(setup->sm_m_preq);
12413deb3ec6SMatthias Ringwald     } else {
12423deb3ec6SMatthias Ringwald         // master / initiator
12433deb3ec6SMatthias Ringwald         remote_packet   = &setup->sm_s_pres;
12449a90d41aSMatthias Ringwald         keys_to_send    = sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres);
12459a90d41aSMatthias Ringwald         keys_to_receive = sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres);
12463deb3ec6SMatthias Ringwald     }
12473deb3ec6SMatthias Ringwald 
12483deb3ec6SMatthias Ringwald     // check key size
12492c041b42SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12502c041b42SMatthias Ringwald     // SC Only mandates 128 bit key size
12512c041b42SMatthias Ringwald     if (sm_sc_only_mode && (sm_pairing_packet_get_max_encryption_key_size(*remote_packet) < 16)) {
12522c041b42SMatthias Ringwald         return SM_REASON_ENCRYPTION_KEY_SIZE;
12532c041b42SMatthias Ringwald     }
12542c041b42SMatthias Ringwald #endif
12551ad129beSMatthias Ringwald     sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(sm_pairing_packet_get_max_encryption_key_size(*remote_packet));
12564ea43905SMatthias Ringwald     if (sm_conn->sm_actual_encryption_key_size == 0u) return SM_REASON_ENCRYPTION_KEY_SIZE;
12573deb3ec6SMatthias Ringwald 
1258eddc894fSMatthias Ringwald     // decide on STK generation method / SC
12593deb3ec6SMatthias Ringwald     sm_setup_tk();
12603deb3ec6SMatthias Ringwald     log_info("SMP: generation method %u", setup->sm_stk_generation_method);
12613deb3ec6SMatthias Ringwald 
12623deb3ec6SMatthias Ringwald     // check if STK generation method is acceptable by client
12633deb3ec6SMatthias Ringwald     if (!sm_validate_stk_generation_method()) return SM_REASON_AUTHENTHICATION_REQUIREMENTS;
12643deb3ec6SMatthias Ringwald 
1265eddc894fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12662c041b42SMatthias Ringwald     // Check LE SC Only mode
12673cdbe9dbSMatthias Ringwald     if (sm_sc_only_mode && (setup->sm_use_secure_connections == false)){
12683cdbe9dbSMatthias Ringwald         log_info("SC Only mode active but SC not possible");
12693cdbe9dbSMatthias Ringwald         return SM_REASON_AUTHENTHICATION_REQUIREMENTS;
12703cdbe9dbSMatthias Ringwald     }
12713cdbe9dbSMatthias Ringwald 
12729a90d41aSMatthias Ringwald     // LTK (= encryption information & master identification) only used exchanged for LE Legacy Connection
1273eddc894fSMatthias Ringwald     if (setup->sm_use_secure_connections){
12749a90d41aSMatthias Ringwald         keys_to_send &= ~SM_KEYDIST_ENC_KEY;
12759a90d41aSMatthias Ringwald         keys_to_receive  &= ~SM_KEYDIST_ENC_KEY;
1276eddc894fSMatthias Ringwald     }
1277eddc894fSMatthias Ringwald #endif
1278eddc894fSMatthias Ringwald 
127952f9cf63SMatthias Ringwald     // identical to responder
12809a90d41aSMatthias Ringwald     sm_setup_key_distribution(keys_to_send, keys_to_receive);
128152f9cf63SMatthias Ringwald 
12823deb3ec6SMatthias Ringwald     // JUST WORKS doens't provide authentication
1283c1ab6cc1SMatthias Ringwald     sm_conn->sm_connection_authenticated = (setup->sm_stk_generation_method == JUST_WORKS) ? 0 : 1;
12843deb3ec6SMatthias Ringwald 
12853deb3ec6SMatthias Ringwald     return 0;
12863deb3ec6SMatthias Ringwald }
12873deb3ec6SMatthias Ringwald 
sm_address_resolution_handle_event(address_resolution_event_t event)12883deb3ec6SMatthias Ringwald static void sm_address_resolution_handle_event(address_resolution_event_t event){
12893deb3ec6SMatthias Ringwald 
12903deb3ec6SMatthias Ringwald     // cache and reset context
12913deb3ec6SMatthias Ringwald     int matched_device_id = sm_address_resolution_test;
12923deb3ec6SMatthias Ringwald     address_resolution_mode_t mode = sm_address_resolution_mode;
12933deb3ec6SMatthias Ringwald     void * context = sm_address_resolution_context;
12943deb3ec6SMatthias Ringwald 
12953deb3ec6SMatthias Ringwald     // reset context
12963deb3ec6SMatthias Ringwald     sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
12973deb3ec6SMatthias Ringwald     sm_address_resolution_context = NULL;
12983deb3ec6SMatthias Ringwald     sm_address_resolution_test = -1;
12993deb3ec6SMatthias Ringwald 
130045d80b08SMatthias Ringwald     hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID;
13013deb3ec6SMatthias Ringwald     sm_connection_t * sm_connection;
1302d2e90122SMatthias Ringwald     sm_key_t ltk;
13031979f09cSMatthias Ringwald     bool have_ltk;
130445d80b08SMatthias Ringwald     int authenticated;
13056c44b759SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
13061979f09cSMatthias Ringwald     bool trigger_pairing;
130742134bc6SMatthias Ringwald #endif
130845d80b08SMatthias Ringwald 
13093deb3ec6SMatthias Ringwald     switch (mode){
13103deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_GENERAL:
13113deb3ec6SMatthias Ringwald             break;
13123deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_FOR_CONNECTION:
13133deb3ec6SMatthias Ringwald             sm_connection = (sm_connection_t *) context;
1314711e6c80SMatthias Ringwald             con_handle = sm_connection->sm_handle;
13156c44b759SMatthias Ringwald 
13166c44b759SMatthias Ringwald             // have ltk -> start encryption / send security request
13176c44b759SMatthias Ringwald             // Core 5, Vol 3, Part C, 10.3.2 Initiating a Service Request
13186c44b759SMatthias Ringwald             // "When a bond has been created between two devices, any reconnection should result in the local device
13196c44b759SMatthias Ringwald             //  enabling or requesting encryption with the remote device before initiating any service request."
13206c44b759SMatthias Ringwald 
13213deb3ec6SMatthias Ringwald             switch (event){
1322a66b030fSMatthias Ringwald                 case ADDRESS_RESOLUTION_SUCCEEDED:
13233deb3ec6SMatthias Ringwald                     sm_connection->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
13243deb3ec6SMatthias Ringwald                     sm_connection->sm_le_db_index = matched_device_id;
1325a66b030fSMatthias Ringwald                     log_info("ADDRESS_RESOLUTION_SUCCEEDED, index %d", sm_connection->sm_le_db_index);
13266c44b759SMatthias Ringwald 
13272d68601cSMatthias Ringwald                     le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, &authenticated, NULL, NULL);
13286c44b759SMatthias Ringwald                     have_ltk = !sm_is_null_key(ltk);
13296c44b759SMatthias Ringwald 
1330f688bdb8SMatthias Ringwald                     if (IS_RESPONDER(sm_connection->sm_role)) {
13316c44b759SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
1332212d735eSMatthias Ringwald                         // IRK required before, continue
13336c39055aSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){
13346c39055aSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
13356c39055aSMatthias Ringwald                             break;
13366c39055aSMatthias Ringwald                         }
1337434260a1SMatthias Ringwald                         // Pairing request before, continue
1338212d735eSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK){
1339212d735eSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
1340212d735eSMatthias Ringwald                             break;
1341212d735eSMatthias Ringwald                         }
1342728f6757SMatthias Ringwald                         bool trigger_security_request = sm_connection->sm_pairing_requested || sm_slave_request_security;
13435f3874afSMatthias Ringwald                         sm_connection->sm_pairing_requested = false;
13446c44b759SMatthias Ringwald #ifdef ENABLE_LE_PROACTIVE_AUTHENTICATION
13457af5dcd5SMatthias Ringwald                         // trigger security request for Proactive Authentication if LTK available
13467af5dcd5SMatthias Ringwald                         trigger_security_request = trigger_security_request || have_ltk;
13476c44b759SMatthias Ringwald #endif
13487af5dcd5SMatthias Ringwald 
13497af5dcd5SMatthias Ringwald                         log_info("peripheral: pairing request local %u, have_ltk %u => trigger_security_request %u",
13505f3874afSMatthias Ringwald                                  (int) sm_connection->sm_pairing_requested, (int) have_ltk, trigger_security_request);
13517af5dcd5SMatthias Ringwald 
13527af5dcd5SMatthias Ringwald                         if (trigger_security_request){
13537af5dcd5SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
13547af5dcd5SMatthias Ringwald                             if (have_ltk){
13557af5dcd5SMatthias Ringwald                                 sm_reencryption_started(sm_connection);
13567af5dcd5SMatthias Ringwald                             } else {
13577af5dcd5SMatthias Ringwald                                 sm_pairing_started(sm_connection);
13587af5dcd5SMatthias Ringwald                             }
13597af5dcd5SMatthias Ringwald                             sm_trigger_run();
13606c44b759SMatthias Ringwald                         }
13616c44b759SMatthias Ringwald #endif
13626c44b759SMatthias Ringwald                     } else {
13636c44b759SMatthias Ringwald 
136442134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
13656c44b759SMatthias Ringwald                         // check if pairing already requested and reset requests
13666c44b759SMatthias Ringwald                         trigger_pairing = sm_connection->sm_pairing_requested || sm_connection->sm_security_request_received;
13672d68601cSMatthias Ringwald                         bool auth_required = sm_auth_req & SM_AUTHREQ_MITM_PROTECTION;
13682d68601cSMatthias Ringwald 
13696c44b759SMatthias Ringwald                         log_info("central: pairing request local %u, remote %u => trigger_pairing %u. have_ltk %u",
13705f3874afSMatthias Ringwald                                  (int) sm_connection->sm_pairing_requested, (int) sm_connection->sm_security_request_received, (int) trigger_pairing, (int) have_ltk);
13710dcaa15fSMatthias Ringwald                         sm_connection->sm_security_request_received = false;
13725f3874afSMatthias Ringwald                         sm_connection->sm_pairing_requested = false;
137332bc5d65SMatthias Ringwald                         bool trigger_reencryption = false;
1374c245ca32SMatthias Ringwald 
1375d4af1595SMatthias Ringwald                         if (have_ltk){
13762d68601cSMatthias Ringwald                             if (trigger_pairing){
13772d68601cSMatthias Ringwald                                 // if pairing is requested, re-encryption is sufficient, if ltk is already authenticated or we don't require authentication
13782d68601cSMatthias Ringwald                                 trigger_reencryption = (authenticated != 0) || (auth_required == false);
13792d68601cSMatthias Ringwald                             } else {
13806a43f611SMatthias Ringwald #ifdef ENABLE_LE_PROACTIVE_AUTHENTICATION
1381b187cc61SMatthias Ringwald                                 trigger_reencryption = true;
138232bc5d65SMatthias Ringwald #else
138332bc5d65SMatthias Ringwald                                 log_info("central: defer enabling encryption for bonded device");
138432bc5d65SMatthias Ringwald #endif
138532bc5d65SMatthias Ringwald                             }
13862d68601cSMatthias Ringwald                         }
138732bc5d65SMatthias Ringwald 
138832bc5d65SMatthias Ringwald                         if (trigger_reencryption){
13896c44b759SMatthias Ringwald                             log_info("central: enable encryption for bonded device");
13905567aa60SMatthias Ringwald                             sm_connection->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
1391d4af1595SMatthias Ringwald                             break;
1392d4af1595SMatthias Ringwald                         }
13936c44b759SMatthias Ringwald 
13946c44b759SMatthias Ringwald                         // pairing_request -> send pairing request
13956c44b759SMatthias Ringwald                         if (trigger_pairing){
13963deb3ec6SMatthias Ringwald                             sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
1397d4af1595SMatthias Ringwald                             break;
13983deb3ec6SMatthias Ringwald                         }
139942134bc6SMatthias Ringwald #endif
1400298ab52bSMatthias Ringwald                     }
14013deb3ec6SMatthias Ringwald                     break;
14023deb3ec6SMatthias Ringwald                 case ADDRESS_RESOLUTION_FAILED:
14033deb3ec6SMatthias Ringwald                     sm_connection->sm_irk_lookup_state = IRK_LOOKUP_FAILED;
1404f688bdb8SMatthias Ringwald                     if (IS_RESPONDER(sm_connection->sm_role)) {
14057af5dcd5SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
14066c39055aSMatthias Ringwald                         // LTK request received before, IRK required -> negative LTK reply
14076c39055aSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){
14086c39055aSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
14096c39055aSMatthias Ringwald                         }
1410434260a1SMatthias Ringwald                         // Pairing request before, continue
1411434260a1SMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK){
1412434260a1SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
1413434260a1SMatthias Ringwald                             break;
1414434260a1SMatthias Ringwald                         }
14157af5dcd5SMatthias Ringwald                         // send security request if requested
1416728f6757SMatthias Ringwald                         bool trigger_security_request = sm_connection->sm_pairing_requested || sm_slave_request_security;
14175f3874afSMatthias Ringwald                         sm_connection->sm_pairing_requested = false;
14187af5dcd5SMatthias Ringwald                         if (trigger_security_request){
14197af5dcd5SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
14207af5dcd5SMatthias Ringwald                             sm_pairing_started(sm_connection);
14217af5dcd5SMatthias Ringwald                         }
14226c39055aSMatthias Ringwald                         break;
14237af5dcd5SMatthias Ringwald #endif
14246c39055aSMatthias Ringwald                     }
142542134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
14265f3874afSMatthias Ringwald                     if ((sm_connection->sm_pairing_requested == false) && (sm_connection->sm_security_request_received == false)) break;
14270dcaa15fSMatthias Ringwald                     sm_connection->sm_security_request_received = false;
14285f3874afSMatthias Ringwald                     sm_connection->sm_pairing_requested = false;
14293deb3ec6SMatthias Ringwald                     sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
143042134bc6SMatthias Ringwald #endif
14313deb3ec6SMatthias Ringwald                     break;
14327bbeb3adSMilanka Ringwald 
14337bbeb3adSMilanka Ringwald                 default:
14347bbeb3adSMilanka Ringwald                     btstack_assert(false);
14357bbeb3adSMilanka Ringwald                     break;
14363deb3ec6SMatthias Ringwald             }
14373deb3ec6SMatthias Ringwald             break;
14383deb3ec6SMatthias Ringwald         default:
14393deb3ec6SMatthias Ringwald             break;
14403deb3ec6SMatthias Ringwald     }
14413deb3ec6SMatthias Ringwald 
14423deb3ec6SMatthias Ringwald     switch (event){
1443a66b030fSMatthias Ringwald         case ADDRESS_RESOLUTION_SUCCEEDED:
1444711e6c80SMatthias Ringwald             sm_notify_client_index(SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED, con_handle, sm_address_resolution_addr_type, sm_address_resolution_address, matched_device_id);
14453deb3ec6SMatthias Ringwald             break;
14463deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_FAILED:
1447711e6c80SMatthias Ringwald             sm_notify_client_base(SM_EVENT_IDENTITY_RESOLVING_FAILED, con_handle, sm_address_resolution_addr_type, sm_address_resolution_address);
14483deb3ec6SMatthias Ringwald             break;
14497bbeb3adSMilanka Ringwald         default:
14507bbeb3adSMilanka Ringwald             btstack_assert(false);
14517bbeb3adSMilanka Ringwald             break;
14523deb3ec6SMatthias Ringwald     }
14533deb3ec6SMatthias Ringwald }
14543deb3ec6SMatthias Ringwald 
sm_store_bonding_information(sm_connection_t * sm_conn)145555f09f49SMatthias Ringwald static void sm_store_bonding_information(sm_connection_t * sm_conn){
14563deb3ec6SMatthias Ringwald     int le_db_index = -1;
14573deb3ec6SMatthias Ringwald 
14583deb3ec6SMatthias Ringwald     // lookup device based on IRK
1459f688bdb8SMatthias Ringwald     if ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
14603deb3ec6SMatthias Ringwald         int i;
1461092ec58eSMatthias Ringwald         for (i=0; i < le_device_db_max_count(); i++){
14623deb3ec6SMatthias Ringwald             sm_key_t irk;
14633deb3ec6SMatthias Ringwald             bd_addr_t address;
1464c7e2c1a5SMatthias Ringwald             int address_type = BD_ADDR_TYPE_UNKNOWN;
14653deb3ec6SMatthias Ringwald             le_device_db_info(i, &address_type, address, irk);
1466adf5eaa9SMatthias Ringwald             // skip unused entries
1467c7e2c1a5SMatthias Ringwald             if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
146811d10bdaSMatthias Ringwald             // compare Identity Address
146911d10bdaSMatthias Ringwald             if (memcmp(address, setup->sm_peer_address, 6) != 0) continue;
147011d10bdaSMatthias Ringwald             // compare Identity Resolving Key
1471c7e2c1a5SMatthias Ringwald             if (memcmp(irk, setup->sm_peer_irk, 16) != 0) continue;
1472c7e2c1a5SMatthias Ringwald 
14733deb3ec6SMatthias Ringwald             log_info("sm: device found for IRK, updating");
14743deb3ec6SMatthias Ringwald             le_db_index = i;
14753deb3ec6SMatthias Ringwald             break;
14763deb3ec6SMatthias Ringwald         }
1477c7e2c1a5SMatthias Ringwald     } else {
1478c7e2c1a5SMatthias Ringwald         // assert IRK is set to zero
1479c7e2c1a5SMatthias Ringwald         memset(setup->sm_peer_irk, 0, 16);
14803deb3ec6SMatthias Ringwald     }
14813deb3ec6SMatthias Ringwald 
14823deb3ec6SMatthias Ringwald     // if not found, lookup via public address if possible
14833deb3ec6SMatthias Ringwald     log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address));
1484c1ab6cc1SMatthias Ringwald     if ((le_db_index < 0) && (setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC)){
14853deb3ec6SMatthias Ringwald         int i;
1486092ec58eSMatthias Ringwald         for (i=0; i < le_device_db_max_count(); i++){
14873deb3ec6SMatthias Ringwald             bd_addr_t address;
1488adf5eaa9SMatthias Ringwald             int address_type = BD_ADDR_TYPE_UNKNOWN;
14893deb3ec6SMatthias Ringwald             le_device_db_info(i, &address_type, address, NULL);
1490adf5eaa9SMatthias Ringwald             // skip unused entries
1491adf5eaa9SMatthias Ringwald             if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
14923deb3ec6SMatthias Ringwald             log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address));
14935df9dc78SMatthias Ringwald             if ((address_type == BD_ADDR_TYPE_LE_PUBLIC) && (memcmp(address, setup->sm_peer_address, 6) == 0)){
14943deb3ec6SMatthias Ringwald                 log_info("sm: device found for public address, updating");
14953deb3ec6SMatthias Ringwald                 le_db_index = i;
14963deb3ec6SMatthias Ringwald                 break;
14973deb3ec6SMatthias Ringwald             }
14983deb3ec6SMatthias Ringwald         }
14993deb3ec6SMatthias Ringwald     }
15003deb3ec6SMatthias Ringwald 
15013deb3ec6SMatthias Ringwald     // if not found, add to db
150202b02cffSMatthias Ringwald     bool new_to_le_device_db = false;
15033deb3ec6SMatthias Ringwald     if (le_db_index < 0) {
15043deb3ec6SMatthias Ringwald         le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
150502b02cffSMatthias Ringwald         new_to_le_device_db = true;
15063deb3ec6SMatthias Ringwald     }
15073deb3ec6SMatthias Ringwald 
15083deb3ec6SMatthias Ringwald     if (le_db_index >= 0){
15093deb3ec6SMatthias Ringwald 
151002b02cffSMatthias Ringwald #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
151102b02cffSMatthias Ringwald         if (!new_to_le_device_db){
151202b02cffSMatthias Ringwald             hci_remove_le_device_db_entry_from_resolving_list(le_db_index);
151302b02cffSMatthias Ringwald         }
151402b02cffSMatthias Ringwald         hci_load_le_device_db_entry_into_resolving_list(le_db_index);
151502b02cffSMatthias Ringwald #else
151602b02cffSMatthias Ringwald         UNUSED(new_to_le_device_db);
151702b02cffSMatthias Ringwald #endif
151802b02cffSMatthias Ringwald 
151948163929SMatthias Ringwald         sm_notify_client_index(SM_EVENT_IDENTITY_CREATED, sm_conn->sm_handle, setup->sm_peer_addr_type, setup->sm_peer_address, le_db_index);
1520e1086030SMatthias Ringwald         sm_conn->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
15217710ebd2SMatthias Ringwald         sm_conn->sm_le_db_index = le_db_index;
152248163929SMatthias Ringwald 
1523eda85fbfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
15243deb3ec6SMatthias Ringwald         // store local CSRK
1525715a43d1SMatthias Ringwald         setup->sm_le_device_index = le_db_index;
1526715a43d1SMatthias Ringwald         if ((setup->sm_key_distribution_sent_set) & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
15273deb3ec6SMatthias Ringwald             log_info("sm: store local CSRK");
15283deb3ec6SMatthias Ringwald             le_device_db_local_csrk_set(le_db_index, setup->sm_local_csrk);
15293deb3ec6SMatthias Ringwald             le_device_db_local_counter_set(le_db_index, 0);
15303deb3ec6SMatthias Ringwald         }
15313deb3ec6SMatthias Ringwald 
15323deb3ec6SMatthias Ringwald         // store remote CSRK
15333deb3ec6SMatthias Ringwald         if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
15343deb3ec6SMatthias Ringwald             log_info("sm: store remote CSRK");
15353deb3ec6SMatthias Ringwald             le_device_db_remote_csrk_set(le_db_index, setup->sm_peer_csrk);
15363deb3ec6SMatthias Ringwald             le_device_db_remote_counter_set(le_db_index, 0);
15373deb3ec6SMatthias Ringwald         }
1538eda85fbfSMatthias Ringwald #endif
153978f44163SMatthias Ringwald         // store encryption information for secure connections: LTK generated by ECDH
154078f44163SMatthias Ringwald         if (setup->sm_use_secure_connections){
1541e6343eb6SMatthias Ringwald             log_info("sm: store SC LTK (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
154278f44163SMatthias Ringwald             uint8_t zero_rand[8];
154378f44163SMatthias Ringwald             memset(zero_rand, 0, 8);
154478f44163SMatthias Ringwald             le_device_db_encryption_set(le_db_index, 0, zero_rand, setup->sm_ltk, sm_conn->sm_actual_encryption_key_size,
15453dc3a67dSMatthias Ringwald                                         sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 1);
154678f44163SMatthias Ringwald         }
154778f44163SMatthias Ringwald 
1548e6343eb6SMatthias Ringwald         // store encryption information for legacy pairing: peer LTK, EDIV, RAND
154978f44163SMatthias Ringwald         else if ( (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION)
155078f44163SMatthias Ringwald         && (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION )){
1551e6343eb6SMatthias Ringwald             log_info("sm: set encryption information (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
15523deb3ec6SMatthias Ringwald             le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
15533dc3a67dSMatthias Ringwald                                         sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 0);
155478f44163SMatthias Ringwald 
15553deb3ec6SMatthias Ringwald         }
15563deb3ec6SMatthias Ringwald     }
155755f09f49SMatthias Ringwald }
155855f09f49SMatthias Ringwald 
sm_pairing_error(sm_connection_t * sm_conn,uint8_t reason)15598980298aSMatthias Ringwald static void sm_pairing_error(sm_connection_t * sm_conn, uint8_t reason){
15608980298aSMatthias Ringwald     sm_conn->sm_pairing_failed_reason = reason;
15618980298aSMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
15628980298aSMatthias Ringwald }
15638980298aSMatthias Ringwald 
sm_le_device_db_index_lookup(bd_addr_type_t address_type,bd_addr_t address)156422cb578bSMatthias Ringwald static int sm_le_device_db_index_lookup(bd_addr_type_t address_type, bd_addr_t address){
15651a55487aSMatthias Ringwald     int i;
15661a55487aSMatthias Ringwald     for (i=0; i < le_device_db_max_count(); i++){
156722cb578bSMatthias Ringwald         bd_addr_t db_address;
156822cb578bSMatthias Ringwald         int db_address_type = BD_ADDR_TYPE_UNKNOWN;
156922cb578bSMatthias Ringwald         le_device_db_info(i, &db_address_type, db_address, NULL);
15701a55487aSMatthias Ringwald         // skip unused entries
15711a55487aSMatthias Ringwald         if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
15723548b7cbSDirk Helbig         if ((address_type == (unsigned int)db_address_type) && (memcmp(address, db_address, 6) == 0)){
15731a55487aSMatthias Ringwald             return i;
15741a55487aSMatthias Ringwald         }
15751a55487aSMatthias Ringwald     }
15761a55487aSMatthias Ringwald     return -1;
15771a55487aSMatthias Ringwald }
15781a55487aSMatthias Ringwald 
sm_remove_le_device_db_entry(uint16_t i)15792e08b70bSMatthias Ringwald static void sm_remove_le_device_db_entry(uint16_t i) {
15802e08b70bSMatthias Ringwald     le_device_db_remove(i);
1581672dc582SMatthias Ringwald #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
1582672dc582SMatthias Ringwald     // to remove an entry from the resolving list requires its identity address, which was already deleted
1583672dc582SMatthias Ringwald     // fully reload resolving list instead
1584672dc582SMatthias Ringwald     gap_load_resolving_list_from_le_device_db();
1585672dc582SMatthias Ringwald #endif
15862e08b70bSMatthias Ringwald }
15872e08b70bSMatthias Ringwald 
sm_key_distribution_validate_received(sm_connection_t * sm_conn)15888980298aSMatthias Ringwald static uint8_t sm_key_distribution_validate_received(sm_connection_t * sm_conn){
1589cc95824cSDirk Helbig     UNUSED(sm_conn);
1590cc95824cSDirk Helbig 
15911a55487aSMatthias Ringwald     // if identity is provided, abort if we have bonding with same address but different irk
1592f688bdb8SMatthias Ringwald     if ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
159322cb578bSMatthias Ringwald         int index = sm_le_device_db_index_lookup(BD_ADDR_TYPE_LE_PUBLIC, setup->sm_peer_address);
15941a55487aSMatthias Ringwald         if (index >= 0){
15951a55487aSMatthias Ringwald             sm_key_t irk;
15961a55487aSMatthias Ringwald             le_device_db_info(index, NULL, NULL, irk);
15971a55487aSMatthias Ringwald             if (memcmp(irk, setup->sm_peer_irk, 16) != 0){
15981a55487aSMatthias Ringwald                 // IRK doesn't match, delete bonding information
15991a55487aSMatthias Ringwald                 log_info("New IRK for %s (type %u) does not match stored IRK -> delete bonding information", bd_addr_to_str(sm_conn->sm_peer_address), sm_conn->sm_peer_addr_type);
16009202d845SMatthias Ringwald                 sm_remove_le_device_db_entry(index);
16011a55487aSMatthias Ringwald             }
16021a55487aSMatthias Ringwald         }
16031a55487aSMatthias Ringwald     }
16048980298aSMatthias Ringwald     return 0;
16058980298aSMatthias Ringwald }
16068980298aSMatthias Ringwald 
sm_key_distribution_handle_all_received(sm_connection_t * sm_conn)160755f09f49SMatthias Ringwald static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
160855f09f49SMatthias Ringwald 
16098980298aSMatthias Ringwald     // abort pairing if received keys are not valid
16108980298aSMatthias Ringwald     uint8_t reason = sm_key_distribution_validate_received(sm_conn);
16118980298aSMatthias Ringwald     if (reason != 0){
16128980298aSMatthias Ringwald         sm_pairing_error(sm_conn, reason);
16138980298aSMatthias Ringwald         return;
16148980298aSMatthias Ringwald     }
16158980298aSMatthias Ringwald 
161655f09f49SMatthias Ringwald     // only store pairing information if both sides are bondable, i.e., the bonadble flag is set
161755f09f49SMatthias Ringwald     bool bonding_enabled = (sm_pairing_packet_get_auth_req(setup->sm_m_preq)
161855f09f49SMatthias Ringwald                             & sm_pairing_packet_get_auth_req(setup->sm_s_pres)
161955f09f49SMatthias Ringwald                             & SM_AUTHREQ_BONDING ) != 0u;
162055f09f49SMatthias Ringwald 
162155f09f49SMatthias Ringwald     if (bonding_enabled){
162255f09f49SMatthias Ringwald         sm_store_bonding_information(sm_conn);
162327ef8bc8SMatthias Ringwald     } else {
162427ef8bc8SMatthias Ringwald         log_info("Ignoring received keys, bonding not enabled");
162527ef8bc8SMatthias Ringwald     }
16263deb3ec6SMatthias Ringwald }
16273deb3ec6SMatthias Ringwald 
sm_pdu_received_in_wrong_state(sm_connection_t * sm_conn)1628688a08f9SMatthias Ringwald static inline void sm_pdu_received_in_wrong_state(sm_connection_t * sm_conn){
1629688a08f9SMatthias Ringwald     sm_pairing_error(sm_conn, SM_REASON_UNSPECIFIED_REASON);
1630688a08f9SMatthias Ringwald }
1631688a08f9SMatthias Ringwald 
16329af0f475SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
1633688a08f9SMatthias Ringwald 
1634dc300847SMatthias Ringwald static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn);
16351d80f1e6SMatthias Ringwald static bool sm_passkey_used(stk_generation_method_t method);
16361d80f1e6SMatthias Ringwald static bool sm_just_works_or_numeric_comparison(stk_generation_method_t method);
16372419120aSMatthias Ringwald static void sm_sc_generate_nx_for_send_random(sm_connection_t * sm_conn);
1638dc300847SMatthias Ringwald 
sm_sc_start_calculating_local_confirm(sm_connection_t * sm_conn)1639b35a3de2SMatthias Ringwald static void sm_sc_start_calculating_local_confirm(sm_connection_t * sm_conn){
1640b90c4e75SMatthias Ringwald     if (setup->sm_stk_generation_method == OOB){
16411f9d84e9SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CONFIRMATION;
1642b90c4e75SMatthias Ringwald     } else {
1643b90c4e75SMatthias Ringwald         btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_nonce, 16, &sm_handle_random_result_sc_next_w2_cmac_for_confirmation, (void *)(uintptr_t) sm_conn->sm_handle);
1644b35a3de2SMatthias Ringwald     }
1645b35a3de2SMatthias Ringwald }
1646b35a3de2SMatthias Ringwald 
sm_sc_state_after_receiving_random(sm_connection_t * sm_conn)1647688a08f9SMatthias Ringwald static void sm_sc_state_after_receiving_random(sm_connection_t * sm_conn){
164842134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1649688a08f9SMatthias Ringwald         // Responder
16504acf7b7bSMatthias Ringwald         if (setup->sm_stk_generation_method == OOB){
16512419120aSMatthias Ringwald             sm_sc_generate_nx_for_send_random(sm_conn);
16524acf7b7bSMatthias Ringwald         } else {
1653688a08f9SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
16544acf7b7bSMatthias Ringwald         }
1655688a08f9SMatthias Ringwald     } else {
1656688a08f9SMatthias Ringwald         // Initiator role
1657688a08f9SMatthias Ringwald         switch (setup->sm_stk_generation_method){
1658688a08f9SMatthias Ringwald             case JUST_WORKS:
1659dc300847SMatthias Ringwald                 sm_sc_prepare_dhkey_check(sm_conn);
1660688a08f9SMatthias Ringwald                 break;
1661688a08f9SMatthias Ringwald 
166247fb4255SMatthias Ringwald             case NUMERIC_COMPARISON:
1663bd57ffebSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_G2;
1664688a08f9SMatthias Ringwald                 break;
1665688a08f9SMatthias Ringwald             case PK_INIT_INPUT:
1666688a08f9SMatthias Ringwald             case PK_RESP_INPUT:
166747fb4255SMatthias Ringwald             case PK_BOTH_INPUT:
16684ea43905SMatthias Ringwald                 if (setup->sm_passkey_bit < 20u) {
1669b35a3de2SMatthias Ringwald                     sm_sc_start_calculating_local_confirm(sm_conn);
1670688a08f9SMatthias Ringwald                 } else {
1671dc300847SMatthias Ringwald                     sm_sc_prepare_dhkey_check(sm_conn);
1672688a08f9SMatthias Ringwald                 }
1673688a08f9SMatthias Ringwald                 break;
1674688a08f9SMatthias Ringwald             case OOB:
167565a9a04eSMatthias Ringwald                 sm_sc_prepare_dhkey_check(sm_conn);
1676688a08f9SMatthias Ringwald                 break;
16777bbeb3adSMilanka Ringwald             default:
16787bbeb3adSMilanka Ringwald                 btstack_assert(false);
16797bbeb3adSMilanka Ringwald                 break;
1680688a08f9SMatthias Ringwald         }
1681688a08f9SMatthias Ringwald     }
1682688a08f9SMatthias Ringwald }
1683688a08f9SMatthias Ringwald 
sm_sc_cmac_done(uint8_t * hash)1684aec94140SMatthias Ringwald static void sm_sc_cmac_done(uint8_t * hash){
1685688a08f9SMatthias Ringwald     log_info("sm_sc_cmac_done: ");
1686688a08f9SMatthias Ringwald     log_info_hexdump(hash, 16);
1687688a08f9SMatthias Ringwald 
1688c59d0c92SMatthias Ringwald     if (sm_sc_oob_state == SM_SC_OOB_W4_CONFIRM){
1689c59d0c92SMatthias Ringwald         sm_sc_oob_state = SM_SC_OOB_IDLE;
1690a680ba6bSMatthias Ringwald         (*sm_sc_oob_callback)(hash, sm_sc_oob_random);
1691c59d0c92SMatthias Ringwald         return;
1692c59d0c92SMatthias Ringwald     }
1693c59d0c92SMatthias Ringwald 
1694bd57ffebSMatthias Ringwald     sm_connection_t * sm_conn = sm_cmac_connection;
1695bd57ffebSMatthias Ringwald     sm_cmac_connection = NULL;
16966857ad8fSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
16972bacf595SMatthias Ringwald     link_key_type_t link_key_type;
1698b4f65634SMatthias Ringwald #endif
1699bd57ffebSMatthias Ringwald 
1700bd57ffebSMatthias Ringwald     switch (sm_conn->sm_engine_state){
1701aec94140SMatthias Ringwald         case SM_SC_W4_CMAC_FOR_CONFIRMATION:
17026535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_confirm, hash, 16);
1703bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_CONFIRMATION;
1704aec94140SMatthias Ringwald             break;
1705688a08f9SMatthias Ringwald         case SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION:
1706688a08f9SMatthias Ringwald             // check
1707688a08f9SMatthias Ringwald             if (0 != memcmp(hash, setup->sm_peer_confirm, 16)){
1708bd57ffebSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CONFIRM_VALUE_FAILED);
1709688a08f9SMatthias Ringwald                 break;
1710688a08f9SMatthias Ringwald             }
17112419120aSMatthias Ringwald             // for OOB, C is verified before generating and sending random Nonce
17122419120aSMatthias Ringwald             if (setup->sm_stk_generation_method == OOB){
17132419120aSMatthias Ringwald                 sm_sc_generate_nx_for_send_random(sm_conn);
17142419120aSMatthias Ringwald             } else {
1715bd57ffebSMatthias Ringwald                 sm_sc_state_after_receiving_random(sm_conn);
17162419120aSMatthias Ringwald             }
1717688a08f9SMatthias Ringwald             break;
1718901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_G2: {
1719901c000fSMatthias Ringwald             uint32_t vab = big_endian_read_32(hash, 12) % 1000000;
1720901c000fSMatthias Ringwald             big_endian_store_32(setup->sm_tk, 12, vab);
1721901c000fSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
1722901c000fSMatthias Ringwald             sm_trigger_user_response(sm_conn);
1723019005a0SMatthias Ringwald             break;
1724019005a0SMatthias Ringwald         }
17250346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_SALT:
17266535961aSMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
1727bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_MACKEY;
17280346c37cSMatthias Ringwald             break;
17290346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_MACKEY:
17306535961aSMatthias Ringwald             (void)memcpy(setup->sm_mackey, hash, 16);
1731bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_LTK;
17320346c37cSMatthias Ringwald             break;
17330346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_LTK:
1734b18300a6SMatthias Ringwald             // truncate sm_ltk, but keep full LTK for cross-transport key derivation in sm_local_ltk
1735b18300a6SMatthias Ringwald             // Errata Service Release to the Bluetooth Specification: ESR09
1736b18300a6SMatthias Ringwald             //   E6405 – Cross transport key derivation from a key of size less than 128 bits
1737b18300a6SMatthias Ringwald             //   Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
17386535961aSMatthias Ringwald             (void)memcpy(setup->sm_ltk, hash, 16);
17396535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_ltk, hash, 16);
1740893e9333SMatthias Ringwald             sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
1741bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK;
1742019005a0SMatthias Ringwald             break;
1743901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
17446535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_dhkey_check, hash, 16);
174542134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1746901c000fSMatthias Ringwald                 // responder
1747f688bdb8SMatthias Ringwald                 if ((setup->sm_state_vars & SM_STATE_VAR_DHKEY_COMMAND_RECEIVED) != 0u){
1748901c000fSMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
1749901c000fSMatthias Ringwald                 } else {
1750901c000fSMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
1751901c000fSMatthias Ringwald                 }
1752901c000fSMatthias Ringwald             } else {
1753901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
1754901c000fSMatthias Ringwald             }
1755901c000fSMatthias Ringwald             break;
1756901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
1757901c000fSMatthias Ringwald             if (0 != memcmp(hash, setup->sm_peer_dhkey_check, 16) ){
1758901c000fSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
1759aec94140SMatthias Ringwald                 break;
1760aec94140SMatthias Ringwald             }
176142134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1762901c000fSMatthias Ringwald                 // responder
1763901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
1764901c000fSMatthias Ringwald             } else {
1765901c000fSMatthias Ringwald                 // initiator
1766901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
1767bd57ffebSMatthias Ringwald             }
1768901c000fSMatthias Ringwald             break;
17696857ad8fSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
177057132f12SMatthias Ringwald         case SM_SC_W4_CALCULATE_ILK:
17716535961aSMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
177257132f12SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY;
17732bacf595SMatthias Ringwald             break;
177457132f12SMatthias Ringwald         case SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY:
17752bacf595SMatthias Ringwald             reverse_128(hash, setup->sm_t);
17762bacf595SMatthias Ringwald             link_key_type = sm_conn->sm_connection_authenticated ?
17772bacf595SMatthias Ringwald                 AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256 : UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
17788974e43fSMatthias Ringwald             log_info("Derived classic link key from LE using h6, type %u", (int) link_key_type);
177955160b1cSMatthias Ringwald 			gap_store_link_key_for_bd_addr(setup->sm_peer_address, setup->sm_t, link_key_type);
17808974e43fSMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
17812bacf595SMatthias Ringwald                 sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
17822bacf595SMatthias Ringwald             } else {
17832bacf595SMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
17842bacf595SMatthias Ringwald             }
17850ccf6c9cSMatthias Ringwald             sm_pairing_complete(sm_conn, ERROR_CODE_SUCCESS, 0);
17862bacf595SMatthias Ringwald             sm_done_for_handle(sm_conn->sm_handle);
17872bacf595SMatthias Ringwald             break;
1788e0a03c85SMatthias Ringwald         case SM_BR_EDR_W4_CALCULATE_ILK:
1789e0a03c85SMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
1790e0a03c85SMatthias Ringwald             sm_conn->sm_engine_state = SM_BR_EDR_W2_CALCULATE_LE_LTK;
1791e0a03c85SMatthias Ringwald             break;
1792e0a03c85SMatthias Ringwald         case SM_BR_EDR_W4_CALCULATE_LE_LTK:
1793e0a03c85SMatthias Ringwald             log_info("Derived LE LTK from BR/EDR Link Key");
1794e0a03c85SMatthias Ringwald             log_info_key("Link Key", hash);
1795e0a03c85SMatthias Ringwald             (void)memcpy(setup->sm_ltk, hash, 16);
1796e0a03c85SMatthias Ringwald             sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
1797e0a03c85SMatthias Ringwald             sm_conn->sm_connection_authenticated = setup->sm_link_key_type == AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
1798e0a03c85SMatthias Ringwald             sm_store_bonding_information(sm_conn);
1799c18be159SMatthias Ringwald             sm_done_for_handle(sm_conn->sm_handle);
1800e0a03c85SMatthias Ringwald             break;
1801bdb14b0eSMatthias Ringwald #endif
1802bd57ffebSMatthias Ringwald         default:
1803bd57ffebSMatthias Ringwald             log_error("sm_sc_cmac_done in state %u", sm_conn->sm_engine_state);
1804bd57ffebSMatthias Ringwald             break;
1805bd57ffebSMatthias Ringwald     }
180670b44dd4SMatthias Ringwald     sm_trigger_run();
1807aec94140SMatthias Ringwald }
1808aec94140SMatthias Ringwald 
f4_engine(sm_connection_t * sm_conn,const sm_key256_t u,const sm_key256_t v,const sm_key_t x,uint8_t z)1809688a08f9SMatthias Ringwald static void f4_engine(sm_connection_t * sm_conn, const sm_key256_t u, const sm_key256_t v, const sm_key_t x, uint8_t z){
1810dc300847SMatthias Ringwald     const uint16_t message_len = 65;
1811aec94140SMatthias Ringwald     sm_cmac_connection = sm_conn;
18126535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, u, 32);
18136535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, v, 32);
1814aec94140SMatthias Ringwald     sm_cmac_sc_buffer[64] = z;
1815aec94140SMatthias Ringwald     log_info("f4 key");
1816aec94140SMatthias Ringwald     log_info_hexdump(x, 16);
1817aec94140SMatthias Ringwald     log_info("f4 message");
1818dc300847SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1819d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(x, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1820aec94140SMatthias Ringwald }
1821aec94140SMatthias Ringwald 
18220346c37cSMatthias Ringwald static const uint8_t f5_key_id[] = { 0x62, 0x74, 0x6c, 0x65 };
18230346c37cSMatthias Ringwald static const uint8_t f5_length[] = { 0x01, 0x00};
18240346c37cSMatthias Ringwald 
f5_calculate_salt(sm_connection_t * sm_conn)18250346c37cSMatthias Ringwald static void f5_calculate_salt(sm_connection_t * sm_conn){
18268334d3d8SMatthias Ringwald 
18278334d3d8SMatthias Ringwald     static const sm_key_t f5_salt = { 0x6C ,0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38, 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE};
18288334d3d8SMatthias Ringwald 
182940c5d850SMatthias Ringwald     log_info("f5_calculate_salt");
18300346c37cSMatthias Ringwald     // calculate salt for f5
18310346c37cSMatthias Ringwald     const uint16_t message_len = 32;
18320346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18336535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, setup->sm_dhkey, message_len);
1834d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(f5_salt, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18350346c37cSMatthias Ringwald }
18360346c37cSMatthias Ringwald 
f5_mackkey(sm_connection_t * sm_conn,sm_key_t t,const sm_key_t n1,const sm_key_t n2,const sm_key56_t a1,const sm_key56_t a2)18370346c37cSMatthias Ringwald static inline void f5_mackkey(sm_connection_t * sm_conn, sm_key_t t, const sm_key_t n1, const sm_key_t n2, const sm_key56_t a1, const sm_key56_t a2){
18380346c37cSMatthias Ringwald     const uint16_t message_len = 53;
18390346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18400346c37cSMatthias Ringwald 
18410346c37cSMatthias Ringwald     // f5(W, N1, N2, A1, A2) = AES-CMACT (Counter = 0 || keyID || N1 || N2|| A1|| A2 || Length = 256) -- this is the MacKey
18420346c37cSMatthias Ringwald     sm_cmac_sc_buffer[0] = 0;
18436535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 01, f5_key_id, 4);
18446535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 05, n1, 16);
18456535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 21, n2, 16);
18466535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 37, a1, 7);
18476535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 44, a2, 7);
18486535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 51, f5_length, 2);
18490346c37cSMatthias Ringwald     log_info("f5 key");
18500346c37cSMatthias Ringwald     log_info_hexdump(t, 16);
18510346c37cSMatthias Ringwald     log_info("f5 message for MacKey");
18520346c37cSMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1853d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(t, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18540346c37cSMatthias Ringwald }
18550346c37cSMatthias Ringwald 
f5_calculate_mackey(sm_connection_t * sm_conn)18560346c37cSMatthias Ringwald static void f5_calculate_mackey(sm_connection_t * sm_conn){
18570346c37cSMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
18580346c37cSMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
18590346c37cSMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
18606535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
18616535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
186242134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
18630346c37cSMatthias Ringwald         // responder
18640346c37cSMatthias Ringwald         f5_mackkey(sm_conn, setup->sm_t, setup->sm_peer_nonce, setup->sm_local_nonce, bd_addr_master, bd_addr_slave);
18650346c37cSMatthias Ringwald     } else {
18660346c37cSMatthias Ringwald         // initiator
18670346c37cSMatthias Ringwald         f5_mackkey(sm_conn, setup->sm_t, setup->sm_local_nonce, setup->sm_peer_nonce, bd_addr_master, bd_addr_slave);
18680346c37cSMatthias Ringwald     }
18690346c37cSMatthias Ringwald }
18700346c37cSMatthias Ringwald 
18710346c37cSMatthias Ringwald // note: must be called right after f5_mackey, as sm_cmac_buffer[1..52] will be reused
f5_ltk(sm_connection_t * sm_conn,sm_key_t t)18720346c37cSMatthias Ringwald static inline void f5_ltk(sm_connection_t * sm_conn, sm_key_t t){
18730346c37cSMatthias Ringwald     const uint16_t message_len = 53;
18740346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18750346c37cSMatthias Ringwald     sm_cmac_sc_buffer[0] = 1;
18760346c37cSMatthias Ringwald     // 1..52 setup before
18770346c37cSMatthias Ringwald     log_info("f5 key");
18780346c37cSMatthias Ringwald     log_info_hexdump(t, 16);
18790346c37cSMatthias Ringwald     log_info("f5 message for LTK");
18800346c37cSMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1881d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(t, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18820346c37cSMatthias Ringwald }
1883f92edc8eSMatthias Ringwald 
f5_calculate_ltk(sm_connection_t * sm_conn)18840346c37cSMatthias Ringwald static void f5_calculate_ltk(sm_connection_t * sm_conn){
18850346c37cSMatthias Ringwald     f5_ltk(sm_conn, setup->sm_t);
18860346c37cSMatthias Ringwald }
18870346c37cSMatthias Ringwald 
f6_setup(const sm_key_t n1,const sm_key_t n2,const sm_key_t r,const sm_key24_t io_cap,const sm_key56_t a1,const sm_key56_t a2)188831f061fbSMatthias Ringwald static void f6_setup(const sm_key_t n1, const sm_key_t n2, const sm_key_t r, const sm_key24_t io_cap, const sm_key56_t a1, const sm_key56_t a2){
18896535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, n1, 16);
18906535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 16, n2, 16);
18916535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, r, 16);
18926535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 48, io_cap, 3);
18936535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 51, a1, 7);
18946535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 58, a2, 7);
189531f061fbSMatthias Ringwald }
189631f061fbSMatthias Ringwald 
f6_engine(sm_connection_t * sm_conn,const sm_key_t w)189731f061fbSMatthias Ringwald static void f6_engine(sm_connection_t * sm_conn, const sm_key_t w){
189831f061fbSMatthias Ringwald     const uint16_t message_len = 65;
189931f061fbSMatthias Ringwald     sm_cmac_connection = sm_conn;
1900dc300847SMatthias Ringwald     log_info("f6 key");
1901dc300847SMatthias Ringwald     log_info_hexdump(w, 16);
1902dc300847SMatthias Ringwald     log_info("f6 message");
1903dc300847SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1904d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(w, 65, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1905dc300847SMatthias Ringwald }
1906dc300847SMatthias Ringwald 
1907f92edc8eSMatthias Ringwald // g2(U, V, X, Y) = AES-CMACX(U || V || Y) mod 2^32
1908f92edc8eSMatthias Ringwald // - U is 256 bits
1909f92edc8eSMatthias Ringwald // - V is 256 bits
1910f92edc8eSMatthias Ringwald // - X is 128 bits
1911f92edc8eSMatthias Ringwald // - Y is 128 bits
g2_engine(sm_connection_t * sm_conn,const sm_key256_t u,const sm_key256_t v,const sm_key_t x,const sm_key_t y)1912bd57ffebSMatthias Ringwald static void g2_engine(sm_connection_t * sm_conn, const sm_key256_t u, const sm_key256_t v, const sm_key_t x, const sm_key_t y){
1913bd57ffebSMatthias Ringwald     const uint16_t message_len = 80;
1914bd57ffebSMatthias Ringwald     sm_cmac_connection = sm_conn;
19156535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, u, 32);
19166535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, v, 32);
19176535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 64, y, 16);
1918f92edc8eSMatthias Ringwald     log_info("g2 key");
1919f92edc8eSMatthias Ringwald     log_info_hexdump(x, 16);
1920f92edc8eSMatthias Ringwald     log_info("g2 message");
19212bacf595SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1922d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(x, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1923f92edc8eSMatthias Ringwald }
1924f92edc8eSMatthias Ringwald 
g2_calculate(sm_connection_t * sm_conn)1925b35a3de2SMatthias Ringwald static void g2_calculate(sm_connection_t * sm_conn) {
1926f92edc8eSMatthias Ringwald     // calc Va if numeric comparison
192742134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1928f92edc8eSMatthias Ringwald         // responder
1929fc5bff5fSMatthias Ringwald         g2_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, setup->sm_local_nonce);;
1930f92edc8eSMatthias Ringwald     } else {
1931f92edc8eSMatthias Ringwald         // initiator
1932fc5bff5fSMatthias Ringwald         g2_engine(sm_conn, ec_q, setup->sm_peer_q, setup->sm_local_nonce, setup->sm_peer_nonce);
1933f92edc8eSMatthias Ringwald     }
1934f92edc8eSMatthias Ringwald }
1935f92edc8eSMatthias Ringwald 
sm_sc_calculate_local_confirm(sm_connection_t * sm_conn)1936945888f5SMatthias Ringwald static void sm_sc_calculate_local_confirm(sm_connection_t * sm_conn){
19379af0f475SMatthias Ringwald     uint8_t z = 0;
193840c5d850SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method)){
19399af0f475SMatthias Ringwald         // some form of passkey
19409af0f475SMatthias Ringwald         uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
19414ea43905SMatthias Ringwald         z = 0x80u | ((pk >> setup->sm_passkey_bit) & 1u);
19429af0f475SMatthias Ringwald         setup->sm_passkey_bit++;
19439af0f475SMatthias Ringwald     }
1944fc5bff5fSMatthias Ringwald     f4_engine(sm_conn, ec_q, setup->sm_peer_q, setup->sm_local_nonce, z);
19459af0f475SMatthias Ringwald }
1946688a08f9SMatthias Ringwald 
sm_sc_calculate_remote_confirm(sm_connection_t * sm_conn)1947688a08f9SMatthias Ringwald static void sm_sc_calculate_remote_confirm(sm_connection_t * sm_conn){
1948a680ba6bSMatthias Ringwald     // OOB
1949a680ba6bSMatthias Ringwald     if (setup->sm_stk_generation_method == OOB){
19504acf7b7bSMatthias Ringwald         if (IS_RESPONDER(sm_conn->sm_role)){
19514acf7b7bSMatthias Ringwald             f4_engine(sm_conn, setup->sm_peer_q, setup->sm_peer_q, setup->sm_ra, 0);
19524acf7b7bSMatthias Ringwald         } else {
19534acf7b7bSMatthias Ringwald             f4_engine(sm_conn, setup->sm_peer_q, setup->sm_peer_q, setup->sm_rb, 0);
19544acf7b7bSMatthias Ringwald         }
1955a680ba6bSMatthias Ringwald         return;
1956a680ba6bSMatthias Ringwald     }
1957a680ba6bSMatthias Ringwald 
1958688a08f9SMatthias Ringwald     uint8_t z = 0;
195940c5d850SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method)){
1960688a08f9SMatthias Ringwald         // some form of passkey
1961688a08f9SMatthias Ringwald         uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
1962688a08f9SMatthias Ringwald         // sm_passkey_bit was increased before sending confirm value
19634ea43905SMatthias Ringwald         z = 0x80u | ((pk >> (setup->sm_passkey_bit-1u)) & 1u);
1964688a08f9SMatthias Ringwald     }
1965fc5bff5fSMatthias Ringwald     f4_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, z);
1966688a08f9SMatthias Ringwald }
1967688a08f9SMatthias Ringwald 
sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn)19680346c37cSMatthias Ringwald static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn){
1969f688bdb8SMatthias Ringwald     log_info("sm_sc_prepare_dhkey_check, DHKEY calculated %u", (setup->sm_state_vars & SM_STATE_VAR_DHKEY_CALCULATED) != 0 ? 1 : 0);
19703cf37b8cSMatthias Ringwald 
1971f688bdb8SMatthias Ringwald     if ((setup->sm_state_vars & SM_STATE_VAR_DHKEY_CALCULATED) != 0u){
19723cf37b8cSMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
19733cf37b8cSMatthias Ringwald     } else {
19743cf37b8cSMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W4_CALCULATE_DHKEY;
19753cf37b8cSMatthias Ringwald     }
1976d1a1f6a4SMatthias Ringwald }
19773cf37b8cSMatthias Ringwald 
sm_sc_dhkey_calculated(void * arg)1978d1a1f6a4SMatthias Ringwald static void sm_sc_dhkey_calculated(void * arg){
1979f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
1980f3582630SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
1981f3582630SMatthias Ringwald     if (sm_conn == NULL) return;
1982f3582630SMatthias Ringwald 
19831c34405fSMatthias Ringwald     // check for invalid public key detected by Controller
19841c34405fSMatthias Ringwald     if (sm_is_ff(setup->sm_dhkey, 32)){
19851c34405fSMatthias Ringwald         log_info("sm: peer public key invalid");
19861c34405fSMatthias Ringwald         sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
19871c34405fSMatthias Ringwald         return;
19881c34405fSMatthias Ringwald     }
19891c34405fSMatthias Ringwald 
1990d1a1f6a4SMatthias Ringwald     log_info("dhkey");
1991d1a1f6a4SMatthias Ringwald     log_info_hexdump(&setup->sm_dhkey[0], 32);
1992d1a1f6a4SMatthias Ringwald     setup->sm_state_vars |= SM_STATE_VAR_DHKEY_CALCULATED;
1993d1a1f6a4SMatthias Ringwald     // trigger next step
1994d1a1f6a4SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_CALCULATE_DHKEY){
1995d1a1f6a4SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
1996d1a1f6a4SMatthias Ringwald     }
199770b44dd4SMatthias Ringwald     sm_trigger_run();
1998dc300847SMatthias Ringwald }
1999dc300847SMatthias Ringwald 
sm_sc_calculate_f6_for_dhkey_check(sm_connection_t * sm_conn)2000dc300847SMatthias Ringwald static void sm_sc_calculate_f6_for_dhkey_check(sm_connection_t * sm_conn){
2001dc300847SMatthias Ringwald     // calculate DHKCheck
2002dc300847SMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
2003dc300847SMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
2004dc300847SMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
20056535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
20066535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
2007dc300847SMatthias Ringwald     uint8_t iocap_a[3];
2008dc300847SMatthias Ringwald     iocap_a[0] = sm_pairing_packet_get_auth_req(setup->sm_m_preq);
2009dc300847SMatthias Ringwald     iocap_a[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq);
2010dc300847SMatthias Ringwald     iocap_a[2] = sm_pairing_packet_get_io_capability(setup->sm_m_preq);
2011dc300847SMatthias Ringwald     uint8_t iocap_b[3];
2012dc300847SMatthias Ringwald     iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
2013dc300847SMatthias Ringwald     iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
2014dc300847SMatthias Ringwald     iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
201542134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
2016dc300847SMatthias Ringwald         // responder
201731f061fbSMatthias Ringwald         f6_setup(setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
201831f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2019dc300847SMatthias Ringwald     } else {
2020dc300847SMatthias Ringwald         // initiator
202131f061fbSMatthias Ringwald         f6_setup( setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
202231f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2023dc300847SMatthias Ringwald     }
2024dc300847SMatthias Ringwald }
2025dc300847SMatthias Ringwald 
sm_sc_calculate_f6_to_verify_dhkey_check(sm_connection_t * sm_conn)2026019005a0SMatthias Ringwald static void sm_sc_calculate_f6_to_verify_dhkey_check(sm_connection_t * sm_conn){
2027019005a0SMatthias Ringwald     // validate E = f6()
2028019005a0SMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
2029019005a0SMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
2030019005a0SMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
20316535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
20326535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
2033019005a0SMatthias Ringwald 
2034019005a0SMatthias Ringwald     uint8_t iocap_a[3];
2035019005a0SMatthias Ringwald     iocap_a[0] = sm_pairing_packet_get_auth_req(setup->sm_m_preq);
2036019005a0SMatthias Ringwald     iocap_a[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq);
2037019005a0SMatthias Ringwald     iocap_a[2] = sm_pairing_packet_get_io_capability(setup->sm_m_preq);
2038019005a0SMatthias Ringwald     uint8_t iocap_b[3];
2039019005a0SMatthias Ringwald     iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
2040019005a0SMatthias Ringwald     iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
2041019005a0SMatthias Ringwald     iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
204242134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
2043019005a0SMatthias Ringwald         // responder
204431f061fbSMatthias Ringwald         f6_setup(setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
204531f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2046019005a0SMatthias Ringwald     } else {
2047019005a0SMatthias Ringwald         // initiator
204831f061fbSMatthias Ringwald         f6_setup(setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
204931f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2050019005a0SMatthias Ringwald     }
2051019005a0SMatthias Ringwald }
20522bacf595SMatthias Ringwald 
sm_sc_generate_nx_for_send_random(sm_connection_t * sm_conn)20532419120aSMatthias Ringwald static void sm_sc_generate_nx_for_send_random(sm_connection_t * sm_conn){
20542419120aSMatthias Ringwald     // generate Nx
20552419120aSMatthias Ringwald     log_info("Generate N%c", IS_RESPONDER(sm_conn->sm_role) ? 'b' : 'a');
20562419120aSMatthias Ringwald     btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_nonce, 16, &sm_handle_random_result_sc_next_send_pairing_random, (void*)(uintptr_t) sm_conn->sm_handle);
20572419120aSMatthias Ringwald }
20582419120aSMatthias Ringwald 
205955c62cf5SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
20602bacf595SMatthias Ringwald 
20612bacf595SMatthias Ringwald //
20622bacf595SMatthias Ringwald // Link Key Conversion Function h6
20632bacf595SMatthias Ringwald //
206457132f12SMatthias Ringwald // h6(W, keyID) = AES-CMAC_W(keyID)
20652bacf595SMatthias Ringwald // - W is 128 bits
20662bacf595SMatthias Ringwald // - keyID is 32 bits
h6_engine(sm_connection_t * sm_conn,const sm_key_t w,const uint32_t key_id)20672bacf595SMatthias Ringwald static void h6_engine(sm_connection_t * sm_conn, const sm_key_t w, const uint32_t key_id){
20682bacf595SMatthias Ringwald     const uint16_t message_len = 4;
20692bacf595SMatthias Ringwald     sm_cmac_connection = sm_conn;
20702bacf595SMatthias Ringwald     big_endian_store_32(sm_cmac_sc_buffer, 0, key_id);
20712bacf595SMatthias Ringwald     log_info("h6 key");
20722bacf595SMatthias Ringwald     log_info_hexdump(w, 16);
20732bacf595SMatthias Ringwald     log_info("h6 message");
20742bacf595SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
2075d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(w, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
20762bacf595SMatthias Ringwald }
207757132f12SMatthias Ringwald //
207857132f12SMatthias Ringwald // Link Key Conversion Function h7
207957132f12SMatthias Ringwald //
208057132f12SMatthias Ringwald // h7(SALT, W) = AES-CMAC_SALT(W)
208157132f12SMatthias Ringwald // - SALT is 128 bits
208257132f12SMatthias Ringwald // - W    is 128 bits
h7_engine(sm_connection_t * sm_conn,const sm_key_t salt,const sm_key_t w)208357132f12SMatthias Ringwald static void h7_engine(sm_connection_t * sm_conn, const sm_key_t salt, const sm_key_t w) {
208457132f12SMatthias Ringwald 	const uint16_t message_len = 16;
208557132f12SMatthias Ringwald 	sm_cmac_connection = sm_conn;
208657132f12SMatthias Ringwald 	log_info("h7 key");
208757132f12SMatthias Ringwald 	log_info_hexdump(salt, 16);
208857132f12SMatthias Ringwald 	log_info("h7 message");
208957132f12SMatthias Ringwald 	log_info_hexdump(w, 16);
209057132f12SMatthias Ringwald 	sm_cmac_message_start(salt, message_len, w, &sm_sc_cmac_done);
209157132f12SMatthias Ringwald }
20922bacf595SMatthias Ringwald 
2093b18300a6SMatthias Ringwald // For SC, setup->sm_local_ltk holds full LTK (sm_ltk is already truncated)
2094b18300a6SMatthias Ringwald // Errata Service Release to the Bluetooth Specification: ESR09
2095b18300a6SMatthias Ringwald //   E6405 – Cross transport key derivation from a key of size less than 128 bits
2096b18300a6SMatthias Ringwald //   "Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
209757132f12SMatthias Ringwald 
h6_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn)2098c82679c3SMatthias Ringwald static void h6_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn){
2099b18300a6SMatthias Ringwald     h6_engine(sm_conn, setup->sm_local_ltk, 0x746D7031);    // "tmp1"
21002bacf595SMatthias Ringwald }
21012bacf595SMatthias Ringwald 
h6_calculate_ilk_from_br_edr(sm_connection_t * sm_conn)2102e0a03c85SMatthias Ringwald static void h6_calculate_ilk_from_br_edr(sm_connection_t * sm_conn){
2103e0a03c85SMatthias Ringwald     h6_engine(sm_conn, setup->sm_link_key, 0x746D7032);    // "tmp2"
2104e0a03c85SMatthias Ringwald }
2105e0a03c85SMatthias Ringwald 
h6_calculate_br_edr_link_key(sm_connection_t * sm_conn)21062bacf595SMatthias Ringwald static void h6_calculate_br_edr_link_key(sm_connection_t * sm_conn){
21072bacf595SMatthias Ringwald     h6_engine(sm_conn, setup->sm_t, 0x6c656272);    // "lebr"
21082bacf595SMatthias Ringwald }
21092bacf595SMatthias Ringwald 
h6_calculate_le_ltk(sm_connection_t * sm_conn)2110e0a03c85SMatthias Ringwald static void h6_calculate_le_ltk(sm_connection_t * sm_conn){
2111e0a03c85SMatthias Ringwald     h6_engine(sm_conn, setup->sm_t, 0x62726C65);    // "brle"
2112e0a03c85SMatthias Ringwald }
2113e0a03c85SMatthias Ringwald 
h7_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn)2114c82679c3SMatthias Ringwald static void h7_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn){
211557132f12SMatthias Ringwald 	const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x31};  // "tmp1"
211657132f12SMatthias Ringwald 	h7_engine(sm_conn, salt, setup->sm_local_ltk);
211757132f12SMatthias Ringwald }
2118e0a03c85SMatthias Ringwald 
h7_calculate_ilk_from_br_edr(sm_connection_t * sm_conn)2119e0a03c85SMatthias Ringwald static void h7_calculate_ilk_from_br_edr(sm_connection_t * sm_conn){
2120e0a03c85SMatthias Ringwald     const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x32};  // "tmp2"
2121e0a03c85SMatthias Ringwald     h7_engine(sm_conn, salt, setup->sm_link_key);
2122e0a03c85SMatthias Ringwald }
2123e0a03c85SMatthias Ringwald 
sm_ctkd_fetch_br_edr_link_key(sm_connection_t * sm_conn)2124c18be159SMatthias Ringwald static void sm_ctkd_fetch_br_edr_link_key(sm_connection_t * sm_conn){
2125e0a03c85SMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(sm_conn->sm_handle);
2126e0a03c85SMatthias Ringwald     btstack_assert(hci_connection != NULL);
2127e0a03c85SMatthias Ringwald     reverse_128(hci_connection->link_key, setup->sm_link_key);
2128e0a03c85SMatthias Ringwald     setup->sm_link_key_type =  hci_connection->link_key_type;
2129e0a03c85SMatthias Ringwald }
2130e0a03c85SMatthias Ringwald 
sm_ctkd_start_from_br_edr(sm_connection_t * sm_conn)213113aed524SMatthias Ringwald static void sm_ctkd_start_from_br_edr(sm_connection_t * sm_conn){
213213aed524SMatthias Ringwald     // only derive LTK if EncKey is set by both
213313aed524SMatthias Ringwald     bool derive_ltk = (sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres) &
213413aed524SMatthias Ringwald                               sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres) & SM_KEYDIST_ENC_KEY) != 0;
213513aed524SMatthias Ringwald     if (derive_ltk){
2136c18be159SMatthias Ringwald         bool use_h7 = (sm_pairing_packet_get_auth_req(setup->sm_m_preq) & sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_CT2) != 0;
213713aed524SMatthias Ringwald         sm_conn->sm_engine_state = use_h7 ? SM_BR_EDR_W2_CALCULATE_ILK_USING_H7 : SM_BR_EDR_W2_CALCULATE_ILK_USING_H6;
213813aed524SMatthias Ringwald     } else {
213913aed524SMatthias Ringwald         sm_done_for_handle(sm_conn->sm_handle);
214013aed524SMatthias Ringwald     }
2141c18be159SMatthias Ringwald }
2142c18be159SMatthias Ringwald 
21439af0f475SMatthias Ringwald #endif
21449af0f475SMatthias Ringwald 
214555c62cf5SMatthias Ringwald #endif
214655c62cf5SMatthias Ringwald 
2147613da3deSMatthias Ringwald // key management legacy connections:
2148613da3deSMatthias Ringwald // - potentially two different LTKs based on direction. each device stores LTK provided by peer
2149613da3deSMatthias Ringwald // - master stores LTK, EDIV, RAND. responder optionally stored master LTK (only if it needs to reconnect)
2150613da3deSMatthias Ringwald // - initiators reconnects: initiator uses stored LTK, EDIV, RAND generated by responder
2151613da3deSMatthias Ringwald // - responder  reconnects: responder uses LTK receveived from master
2152613da3deSMatthias Ringwald 
2153613da3deSMatthias Ringwald // key management secure connections:
2154613da3deSMatthias Ringwald // - both devices store same LTK from ECDH key exchange.
2155613da3deSMatthias Ringwald 
215642134bc6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) || defined(ENABLE_LE_CENTRAL)
sm_load_security_info(sm_connection_t * sm_connection)21575829ebe2SMatthias Ringwald static void sm_load_security_info(sm_connection_t * sm_connection){
21585829ebe2SMatthias Ringwald     int encryption_key_size;
21595829ebe2SMatthias Ringwald     int authenticated;
21605829ebe2SMatthias Ringwald     int authorized;
21613dc3a67dSMatthias Ringwald     int secure_connection;
21625829ebe2SMatthias Ringwald 
21635829ebe2SMatthias Ringwald     // fetch data from device db - incl. authenticated/authorized/key size. Note all sm_connection_X require encryption enabled
21645829ebe2SMatthias Ringwald     le_device_db_encryption_get(sm_connection->sm_le_db_index, &setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
21653dc3a67dSMatthias Ringwald                                 &encryption_key_size, &authenticated, &authorized, &secure_connection);
21663dc3a67dSMatthias Ringwald     log_info("db index %u, key size %u, authenticated %u, authorized %u, secure connetion %u", sm_connection->sm_le_db_index, encryption_key_size, authenticated, authorized, secure_connection);
21675829ebe2SMatthias Ringwald     sm_connection->sm_actual_encryption_key_size = encryption_key_size;
21685829ebe2SMatthias Ringwald     sm_connection->sm_connection_authenticated = authenticated;
21695829ebe2SMatthias Ringwald     sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
2170d7dbf891SMatthias Ringwald     sm_connection->sm_connection_sc = secure_connection != 0;
21715829ebe2SMatthias Ringwald }
217242134bc6SMatthias Ringwald #endif
2173bd57ffebSMatthias Ringwald 
217442134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_connection)217559066796SMatthias Ringwald static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_connection){
21766535961aSMatthias Ringwald     (void)memcpy(setup->sm_local_rand, sm_connection->sm_local_rand, 8);
217759066796SMatthias Ringwald     setup->sm_local_ediv = sm_connection->sm_local_ediv;
217859066796SMatthias Ringwald     // re-establish used key encryption size
217959066796SMatthias Ringwald     // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
21804ea43905SMatthias Ringwald     sm_connection->sm_actual_encryption_key_size = (setup->sm_local_rand[7u] & 0x0fu) + 1u;
218159066796SMatthias Ringwald     // no db for authenticated flag hack: flag is stored in bit 4 of LSB
21824ea43905SMatthias Ringwald     sm_connection->sm_connection_authenticated = (setup->sm_local_rand[7u] & 0x10u) >> 4u;
21833dc3a67dSMatthias Ringwald     // Legacy paring -> not SC
2184d7dbf891SMatthias Ringwald     sm_connection->sm_connection_sc = false;
218559066796SMatthias Ringwald     log_info("sm: received ltk request with key size %u, authenticated %u",
218659066796SMatthias Ringwald             sm_connection->sm_actual_encryption_key_size, sm_connection->sm_connection_authenticated);
218759066796SMatthias Ringwald }
218842134bc6SMatthias Ringwald #endif
218959066796SMatthias Ringwald 
21903deb3ec6SMatthias Ringwald // distributed key generation
sm_run_dpkg(void)2191d7f1c72eSMatthias Ringwald static bool sm_run_dpkg(void){
21923deb3ec6SMatthias Ringwald     switch (dkg_state){
21933deb3ec6SMatthias Ringwald         case DKG_CALC_IRK:
21943deb3ec6SMatthias Ringwald             // already busy?
21953deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2196d1a1f6a4SMatthias Ringwald                 log_info("DKG_CALC_IRK started");
21973deb3ec6SMatthias Ringwald                 // IRK = d1(IR, 1, 0)
2198d1a1f6a4SMatthias Ringwald                 sm_d1_d_prime(1, 0, sm_aes128_plaintext);  // plaintext = d1 prime
2199d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2200d1a1f6a4SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_ir, sm_aes128_plaintext, sm_persistent_irk, sm_handle_encryption_result_dkg_irk, NULL);
2201d7f1c72eSMatthias Ringwald                 return true;
22023deb3ec6SMatthias Ringwald             }
22033deb3ec6SMatthias Ringwald             break;
22043deb3ec6SMatthias Ringwald         case DKG_CALC_DHK:
22053deb3ec6SMatthias Ringwald             // already busy?
22063deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2207d1a1f6a4SMatthias Ringwald                 log_info("DKG_CALC_DHK started");
22083deb3ec6SMatthias Ringwald                 // DHK = d1(IR, 3, 0)
2209d1a1f6a4SMatthias Ringwald                 sm_d1_d_prime(3, 0, sm_aes128_plaintext);  // plaintext = d1 prime
2210d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2211d1a1f6a4SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_ir, sm_aes128_plaintext, sm_persistent_dhk, sm_handle_encryption_result_dkg_dhk, NULL);
2212d7f1c72eSMatthias Ringwald                 return true;
22133deb3ec6SMatthias Ringwald             }
22143deb3ec6SMatthias Ringwald             break;
22153deb3ec6SMatthias Ringwald         default:
22163deb3ec6SMatthias Ringwald             break;
22173deb3ec6SMatthias Ringwald     }
2218d7f1c72eSMatthias Ringwald     return false;
2219d7f1c72eSMatthias Ringwald }
22203deb3ec6SMatthias Ringwald 
22213deb3ec6SMatthias Ringwald // random address updates
sm_run_rau(void)2222d7f1c72eSMatthias Ringwald static bool sm_run_rau(void){
22233deb3ec6SMatthias Ringwald     switch (rau_state){
2224fbd4e238SMatthias Ringwald         case RAU_GET_RANDOM:
2225fbd4e238SMatthias Ringwald             rau_state = RAU_W4_RANDOM;
22265b4dd597SMatthias Ringwald             btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_address, 6, &sm_handle_random_result_rau, NULL);
2227d7f1c72eSMatthias Ringwald             return true;
22283deb3ec6SMatthias Ringwald         case RAU_GET_ENC:
22293deb3ec6SMatthias Ringwald             // already busy?
22303deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2231d1a1f6a4SMatthias Ringwald                 sm_ah_r_prime(sm_random_address, sm_aes128_plaintext);
2232d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2233d1a1f6a4SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_irk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_rau, NULL);
2234d7f1c72eSMatthias Ringwald                 return true;
22353deb3ec6SMatthias Ringwald             }
22363deb3ec6SMatthias Ringwald             break;
22373deb3ec6SMatthias Ringwald         default:
22383deb3ec6SMatthias Ringwald             break;
22393deb3ec6SMatthias Ringwald     }
2240d7f1c72eSMatthias Ringwald     return false;
2241d7f1c72eSMatthias Ringwald }
22423deb3ec6SMatthias Ringwald 
224351258968SMatthias Ringwald // device lookup with IRK
sm_run_irk_lookup(void)224451258968SMatthias Ringwald static bool sm_run_irk_lookup(void){
2245d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
2246d7f1c72eSMatthias Ringwald 
224751258968SMatthias Ringwald     // -- if IRK lookup ready, find connection that require csrk lookup
22483deb3ec6SMatthias Ringwald     if (sm_address_resolution_idle()){
22493deb3ec6SMatthias Ringwald         hci_connections_get_iterator(&it);
2250665d90f2SMatthias Ringwald         while(btstack_linked_list_iterator_has_next(&it)){
2251665d90f2SMatthias Ringwald             hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
22523deb3ec6SMatthias Ringwald             sm_connection_t  * sm_connection  = &hci_connection->sm_connection;
22533deb3ec6SMatthias Ringwald             if (sm_connection->sm_irk_lookup_state == IRK_LOOKUP_W4_READY){
22543deb3ec6SMatthias Ringwald                 // and start lookup
22553deb3ec6SMatthias Ringwald                 sm_address_resolution_start_lookup(sm_connection->sm_peer_addr_type, sm_connection->sm_handle, sm_connection->sm_peer_address, ADDRESS_RESOLUTION_FOR_CONNECTION, sm_connection);
22563deb3ec6SMatthias Ringwald                 sm_connection->sm_irk_lookup_state = IRK_LOOKUP_STARTED;
22573deb3ec6SMatthias Ringwald                 break;
22583deb3ec6SMatthias Ringwald             }
22593deb3ec6SMatthias Ringwald         }
22603deb3ec6SMatthias Ringwald     }
22613deb3ec6SMatthias Ringwald 
22623deb3ec6SMatthias Ringwald     // -- if csrk lookup ready, resolved addresses for received addresses
22633deb3ec6SMatthias Ringwald     if (sm_address_resolution_idle()) {
2264665d90f2SMatthias Ringwald         if (!btstack_linked_list_empty(&sm_address_resolution_general_queue)){
22653deb3ec6SMatthias Ringwald             sm_lookup_entry_t * entry = (sm_lookup_entry_t *) sm_address_resolution_general_queue;
2266665d90f2SMatthias Ringwald             btstack_linked_list_remove(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
22673deb3ec6SMatthias Ringwald             sm_address_resolution_start_lookup(entry->address_type, 0, entry->address, ADDRESS_RESOLUTION_GENERAL, NULL);
22683deb3ec6SMatthias Ringwald             btstack_memory_sm_lookup_entry_free(entry);
22693deb3ec6SMatthias Ringwald         }
22703deb3ec6SMatthias Ringwald     }
22713deb3ec6SMatthias Ringwald 
2272ca685291SMatthias Ringwald     // -- Continue with device lookup by public or resolvable private address
22733deb3ec6SMatthias Ringwald     if (!sm_address_resolution_idle()){
227472d2978cSMatthias Ringwald         bool started_aes128 = false;
2275092ec58eSMatthias Ringwald         while (sm_address_resolution_test < le_device_db_max_count()){
2276adf5eaa9SMatthias Ringwald             int addr_type = BD_ADDR_TYPE_UNKNOWN;
22773deb3ec6SMatthias Ringwald             bd_addr_t addr;
22783deb3ec6SMatthias Ringwald             sm_key_t irk;
22793deb3ec6SMatthias Ringwald             le_device_db_info(sm_address_resolution_test, &addr_type, addr, irk);
22803deb3ec6SMatthias Ringwald 
2281adf5eaa9SMatthias Ringwald             // skip unused entries
2282adf5eaa9SMatthias Ringwald             if (addr_type == BD_ADDR_TYPE_UNKNOWN){
2283adf5eaa9SMatthias Ringwald                 sm_address_resolution_test++;
2284adf5eaa9SMatthias Ringwald                 continue;
2285adf5eaa9SMatthias Ringwald             }
2286adf5eaa9SMatthias Ringwald 
2287c2b94d32SMatthias Ringwald             log_info("LE Device Lookup: device %u of %u - type %u, %s", sm_address_resolution_test,
2288c2b94d32SMatthias Ringwald                      le_device_db_max_count(), addr_type, bd_addr_to_str(addr));
2289ca685291SMatthias Ringwald 
2290c2b94d32SMatthias Ringwald             // map resolved identity addresses to regular addresses
2291515f33beSMatthias Ringwald             int regular_addr_type = sm_address_resolution_addr_type & 1;
2292515f33beSMatthias Ringwald             if ((regular_addr_type == addr_type) && (memcmp(addr, sm_address_resolution_address, 6) == 0)){
2293ca685291SMatthias Ringwald                 log_info("LE Device Lookup: found by { addr_type, address} ");
2294a66b030fSMatthias Ringwald                 sm_address_resolution_handle_event(ADDRESS_RESOLUTION_SUCCEEDED);
22953deb3ec6SMatthias Ringwald                 break;
22963deb3ec6SMatthias Ringwald             }
22973deb3ec6SMatthias Ringwald 
2298c2b94d32SMatthias Ringwald             // if connection type is not random (i.e. public or resolved identity), it must be a different entry
2299c2b94d32SMatthias Ringwald             if (sm_address_resolution_addr_type != BD_ADDR_TYPE_LE_RANDOM){
23003deb3ec6SMatthias Ringwald                 sm_address_resolution_test++;
23013deb3ec6SMatthias Ringwald                 continue;
23023deb3ec6SMatthias Ringwald             }
23033deb3ec6SMatthias Ringwald 
23048cc81b50SMatthias Ringwald             // skip AH if no IRK
23058cc81b50SMatthias Ringwald             if (sm_is_null_key(irk)){
23068cc81b50SMatthias Ringwald                 sm_address_resolution_test++;
23078cc81b50SMatthias Ringwald                 continue;
23088cc81b50SMatthias Ringwald             }
23098cc81b50SMatthias Ringwald 
23103deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_ACTIVE) break;
23113deb3ec6SMatthias Ringwald 
23123deb3ec6SMatthias Ringwald             log_info("LE Device Lookup: calculate AH");
23138314c363SMatthias Ringwald             log_info_key("IRK", irk);
23143deb3ec6SMatthias Ringwald 
23156535961aSMatthias Ringwald             (void)memcpy(sm_aes128_key, irk, 16);
2316d1a1f6a4SMatthias Ringwald             sm_ah_r_prime(sm_address_resolution_address, sm_aes128_plaintext);
2317d1a1f6a4SMatthias Ringwald             sm_aes128_state = SM_AES128_ACTIVE;
2318d1a1f6a4SMatthias Ringwald             btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_aes128_key, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_address_resolution, NULL);
231972d2978cSMatthias Ringwald             started_aes128 = true;
232072d2978cSMatthias Ringwald             break;
232172d2978cSMatthias Ringwald         }
232272d2978cSMatthias Ringwald 
232372d2978cSMatthias Ringwald         if (started_aes128){
2324d7f1c72eSMatthias Ringwald             return true;
23253deb3ec6SMatthias Ringwald         }
23263deb3ec6SMatthias Ringwald 
2327092ec58eSMatthias Ringwald         if (sm_address_resolution_test >= le_device_db_max_count()){
23283deb3ec6SMatthias Ringwald             log_info("LE Device Lookup: not found");
23293deb3ec6SMatthias Ringwald             sm_address_resolution_handle_event(ADDRESS_RESOLUTION_FAILED);
23303deb3ec6SMatthias Ringwald         }
23313deb3ec6SMatthias Ringwald     }
2332d7f1c72eSMatthias Ringwald     return false;
2333d7f1c72eSMatthias Ringwald }
23343deb3ec6SMatthias Ringwald 
2335d7f1c72eSMatthias Ringwald // SC OOB
sm_run_oob(void)2336d7f1c72eSMatthias Ringwald static bool sm_run_oob(void){
2337c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2338c59d0c92SMatthias Ringwald     switch (sm_sc_oob_state){
2339c59d0c92SMatthias Ringwald         case SM_SC_OOB_W2_CALC_CONFIRM:
2340c59d0c92SMatthias Ringwald             if (!sm_cmac_ready()) break;
2341c59d0c92SMatthias Ringwald             sm_sc_oob_state = SM_SC_OOB_W4_CONFIRM;
2342c59d0c92SMatthias Ringwald             f4_engine(NULL, ec_q, ec_q, sm_sc_oob_random, 0);
2343d7f1c72eSMatthias Ringwald             return true;
2344c59d0c92SMatthias Ringwald         default:
2345c59d0c92SMatthias Ringwald             break;
2346c59d0c92SMatthias Ringwald     }
2347c59d0c92SMatthias Ringwald #endif
2348d7f1c72eSMatthias Ringwald     return false;
2349d7f1c72eSMatthias Ringwald }
2350275aafe8SMatthias Ringwald 
sm_send_connectionless(sm_connection_t * sm_connection,const uint8_t * buffer,uint16_t size)2351687a03c8SMatthias Ringwald static void sm_send_connectionless(sm_connection_t * sm_connection, const uint8_t * buffer, uint16_t size){
2352687a03c8SMatthias Ringwald     l2cap_send_connectionless(sm_connection->sm_handle, sm_connection->sm_cid, (uint8_t*) buffer, size);
2353687a03c8SMatthias Ringwald }
2354687a03c8SMatthias Ringwald 
235541d32297SMatthias Ringwald // handle basic actions that don't requires the full context
sm_run_basic(void)2356d7f1c72eSMatthias Ringwald static bool sm_run_basic(void){
2357d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
235841d32297SMatthias Ringwald     hci_connections_get_iterator(&it);
2359e9af1bf6SMatthias Ringwald     while(btstack_linked_list_iterator_has_next(&it)){
236041d32297SMatthias Ringwald         hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
236141d32297SMatthias Ringwald         sm_connection_t  * sm_connection = &hci_connection->sm_connection;
236241d32297SMatthias Ringwald         switch(sm_connection->sm_engine_state){
2363f4935286SMatthias Ringwald 
2364f4935286SMatthias Ringwald             // general
2365f4935286SMatthias Ringwald             case SM_GENERAL_SEND_PAIRING_FAILED: {
2366f4935286SMatthias Ringwald                 uint8_t buffer[2];
2367f4935286SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_FAILED;
2368f4935286SMatthias Ringwald                 buffer[1] = sm_connection->sm_pairing_failed_reason;
2369f4935286SMatthias Ringwald                 sm_connection->sm_engine_state = sm_connection->sm_role ? SM_RESPONDER_IDLE : SM_INITIATOR_CONNECTED;
2370687a03c8SMatthias Ringwald                 sm_send_connectionless(sm_connection, (uint8_t*) buffer, sizeof(buffer));
2371f4935286SMatthias Ringwald                 sm_pairing_complete(sm_connection, ERROR_CODE_AUTHENTICATION_FAILURE, sm_connection->sm_pairing_failed_reason);
2372f4935286SMatthias Ringwald                 sm_done_for_handle(sm_connection->sm_handle);
2373f4935286SMatthias Ringwald                 break;
2374f4935286SMatthias Ringwald             }
2375f4935286SMatthias Ringwald 
237641d32297SMatthias Ringwald             // responder side
237741d32297SMatthias Ringwald             case SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY:
237841d32297SMatthias Ringwald                 sm_connection->sm_engine_state = SM_RESPONDER_IDLE;
237941d32297SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle);
2380d7f1c72eSMatthias Ringwald                 return true;
23814b8b5afeSMatthias Ringwald 
23824b8b5afeSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
23834b8b5afeSMatthias Ringwald             case SM_SC_RECEIVED_LTK_REQUEST:
23844b8b5afeSMatthias Ringwald                 switch (sm_connection->sm_irk_lookup_state){
23854b8b5afeSMatthias Ringwald                     case IRK_LOOKUP_FAILED:
2386e9af1bf6SMatthias Ringwald                         log_info("LTK Request: IRK Lookup Failed)");
23874b8b5afeSMatthias Ringwald                         sm_connection->sm_engine_state = SM_RESPONDER_IDLE;
23884b8b5afeSMatthias Ringwald                         hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle);
2389d7f1c72eSMatthias Ringwald                         return true;
23904b8b5afeSMatthias Ringwald                     default:
23914b8b5afeSMatthias Ringwald                         break;
23924b8b5afeSMatthias Ringwald                 }
23934b8b5afeSMatthias Ringwald                 break;
23944b8b5afeSMatthias Ringwald #endif
239541d32297SMatthias Ringwald             default:
239641d32297SMatthias Ringwald                 break;
239741d32297SMatthias Ringwald         }
239841d32297SMatthias Ringwald     }
2399d7f1c72eSMatthias Ringwald     return false;
2400d7f1c72eSMatthias Ringwald }
24013deb3ec6SMatthias Ringwald 
sm_run_activate_connection(void)2402d7f1c72eSMatthias Ringwald static void sm_run_activate_connection(void){
24033deb3ec6SMatthias Ringwald     // Find connections that requires setup context and make active if no other is locked
2404d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
24053deb3ec6SMatthias Ringwald     hci_connections_get_iterator(&it);
24067149bde5SMatthias Ringwald     while((sm_active_connection_handle == HCI_CON_HANDLE_INVALID) && btstack_linked_list_iterator_has_next(&it)){
2407665d90f2SMatthias Ringwald         hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
24083deb3ec6SMatthias Ringwald         sm_connection_t  * sm_connection = &hci_connection->sm_connection;
24093deb3ec6SMatthias Ringwald         // - if no connection locked and we're ready/waiting for setup context, fetch it and start
24101979f09cSMatthias Ringwald         bool done = true;
241134b6528fSMatthias Ringwald 
241234b6528fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
241334b6528fSMatthias Ringwald         // assert ec key is ready
2414505f1c30SMatthias Ringwald         if (   (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED)
2415178e8c1bSMatthias Ringwald             || (sm_connection->sm_engine_state == SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST)
2416178e8c1bSMatthias Ringwald 			|| (sm_connection->sm_engine_state == SM_RESPONDER_SEND_SECURITY_REQUEST)){
241734b6528fSMatthias Ringwald             if (ec_key_generation_state == EC_KEY_GENERATION_IDLE){
241834b6528fSMatthias Ringwald                 sm_ec_generate_new_key();
241934b6528fSMatthias Ringwald             }
242034b6528fSMatthias Ringwald             if (ec_key_generation_state != EC_KEY_GENERATION_DONE){
242134b6528fSMatthias Ringwald                 continue;
242234b6528fSMatthias Ringwald             }
242334b6528fSMatthias Ringwald         }
242434b6528fSMatthias Ringwald #endif
242534b6528fSMatthias Ringwald 
24263deb3ec6SMatthias Ringwald         switch (sm_connection->sm_engine_state) {
242742134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
24283deb3ec6SMatthias Ringwald             case SM_RESPONDER_SEND_SECURITY_REQUEST:
24293deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
243042134bc6SMatthias Ringwald             case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
2431549ad5d2SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
243206cd539fSMatthias Ringwald             case SM_SC_RECEIVED_LTK_REQUEST:
243387014f74SMatthias Ringwald #endif
243487014f74SMatthias Ringwald #endif
243534c39fbdSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
24365567aa60SMatthias Ringwald             case SM_INITIATOR_PH4_HAS_LTK:
243734c39fbdSMatthias Ringwald 			case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
2438549ad5d2SMatthias Ringwald #endif
2439c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
2440c18be159SMatthias Ringwald             case SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED:
2441c18be159SMatthias Ringwald             case SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST:
2442c18be159SMatthias Ringwald #endif
244387014f74SMatthias Ringwald 				// just lock context
244487014f74SMatthias Ringwald 				break;
24453deb3ec6SMatthias Ringwald             default:
24461979f09cSMatthias Ringwald                 done = false;
24473deb3ec6SMatthias Ringwald                 break;
24483deb3ec6SMatthias Ringwald         }
24493deb3ec6SMatthias Ringwald         if (done){
24507149bde5SMatthias Ringwald             sm_active_connection_handle = sm_connection->sm_handle;
24517149bde5SMatthias Ringwald             log_info("sm: connection 0x%04x locked setup context as %s, state %u", sm_active_connection_handle, sm_connection->sm_role ? "responder" : "initiator", sm_connection->sm_engine_state);
24523deb3ec6SMatthias Ringwald         }
24533deb3ec6SMatthias Ringwald     }
2454d7f1c72eSMatthias Ringwald }
2455d7f1c72eSMatthias Ringwald 
sm_run_send_keypress_notification(sm_connection_t * connection)2456403280b9SMatthias Ringwald static void sm_run_send_keypress_notification(sm_connection_t * connection){
2457403280b9SMatthias Ringwald     int i;
2458403280b9SMatthias Ringwald     uint8_t flags       = setup->sm_keypress_notification & 0x1fu;
2459403280b9SMatthias Ringwald     uint8_t num_actions = setup->sm_keypress_notification >> 5;
2460403280b9SMatthias Ringwald     uint8_t action = 0;
2461403280b9SMatthias Ringwald     for (i=SM_KEYPRESS_PASSKEY_ENTRY_STARTED;i<=SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED;i++){
24621d80f1e6SMatthias Ringwald         if ((flags & (1u<<i)) != 0u){
2463403280b9SMatthias Ringwald             bool clear_flag = true;
2464403280b9SMatthias Ringwald             switch (i){
2465403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_ENTRY_STARTED:
2466403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_CLEARED:
2467403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED:
2468403280b9SMatthias Ringwald                 default:
2469403280b9SMatthias Ringwald                     break;
2470403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_DIGIT_ENTERED:
2471403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_DIGIT_ERASED:
2472403280b9SMatthias Ringwald                     num_actions--;
2473403280b9SMatthias Ringwald                     clear_flag = num_actions == 0u;
2474403280b9SMatthias Ringwald                     break;
2475403280b9SMatthias Ringwald             }
2476403280b9SMatthias Ringwald             if (clear_flag){
2477403280b9SMatthias Ringwald                 flags &= ~(1<<i);
2478403280b9SMatthias Ringwald             }
2479403280b9SMatthias Ringwald             action = i;
2480403280b9SMatthias Ringwald             break;
2481403280b9SMatthias Ringwald         }
2482403280b9SMatthias Ringwald     }
2483403280b9SMatthias Ringwald     setup->sm_keypress_notification = (num_actions << 5) | flags;
2484403280b9SMatthias Ringwald 
2485403280b9SMatthias Ringwald     // send keypress notification
2486403280b9SMatthias Ringwald     uint8_t buffer[2];
2487403280b9SMatthias Ringwald     buffer[0] = SM_CODE_KEYPRESS_NOTIFICATION;
2488403280b9SMatthias Ringwald     buffer[1] = action;
2489687a03c8SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2490403280b9SMatthias Ringwald 
2491403280b9SMatthias Ringwald     // try
2492384eabd3SMatthias Ringwald     l2cap_request_can_send_fix_channel_now_event(sm_active_connection_handle, connection->sm_cid);
2493403280b9SMatthias Ringwald }
2494403280b9SMatthias Ringwald 
sm_run_distribute_keys(sm_connection_t * connection)2495403280b9SMatthias Ringwald static void sm_run_distribute_keys(sm_connection_t * connection){
24961d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION) != 0u){
2497403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
2498403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
2499403280b9SMatthias Ringwald         uint8_t buffer[17];
2500403280b9SMatthias Ringwald         buffer[0] = SM_CODE_ENCRYPTION_INFORMATION;
2501403280b9SMatthias Ringwald         reverse_128(setup->sm_ltk, &buffer[1]);
2502687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2503403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2504403280b9SMatthias Ringwald         return;
2505403280b9SMatthias Ringwald     }
25061d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_MASTER_IDENTIFICATION) != 0u){
2507403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
2508403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
2509403280b9SMatthias Ringwald         uint8_t buffer[11];
2510403280b9SMatthias Ringwald         buffer[0] = SM_CODE_MASTER_IDENTIFICATION;
2511403280b9SMatthias Ringwald         little_endian_store_16(buffer, 1, setup->sm_local_ediv);
2512403280b9SMatthias Ringwald         reverse_64(setup->sm_local_rand, &buffer[3]);
2513687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2514403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2515403280b9SMatthias Ringwald         return;
2516403280b9SMatthias Ringwald     }
25171d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
2518403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
2519403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
2520403280b9SMatthias Ringwald         uint8_t buffer[17];
2521403280b9SMatthias Ringwald         buffer[0] = SM_CODE_IDENTITY_INFORMATION;
2522403280b9SMatthias Ringwald         reverse_128(sm_persistent_irk, &buffer[1]);
2523687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2524403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2525403280b9SMatthias Ringwald         return;
2526403280b9SMatthias Ringwald     }
25271d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION) != 0u){
2528403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
2529403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
2530403280b9SMatthias Ringwald         bd_addr_t local_address;
2531403280b9SMatthias Ringwald         uint8_t buffer[8];
2532403280b9SMatthias Ringwald         buffer[0] = SM_CODE_IDENTITY_ADDRESS_INFORMATION;
2533403280b9SMatthias Ringwald         switch (gap_random_address_get_mode()){
2534403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_TYPE_OFF:
2535403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_TYPE_STATIC:
2536403280b9SMatthias Ringwald                 // public or static random
2537403280b9SMatthias Ringwald                 gap_le_get_own_address(&buffer[1], local_address);
2538403280b9SMatthias Ringwald                 break;
2539403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_NON_RESOLVABLE:
2540403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_RESOLVABLE:
2541403280b9SMatthias Ringwald                 // fallback to public
2542403280b9SMatthias Ringwald                 gap_local_bd_addr(local_address);
2543403280b9SMatthias Ringwald                 buffer[1] = 0;
2544403280b9SMatthias Ringwald                 break;
2545403280b9SMatthias Ringwald             default:
2546403280b9SMatthias Ringwald                 btstack_assert(false);
2547403280b9SMatthias Ringwald                 break;
2548403280b9SMatthias Ringwald         }
2549403280b9SMatthias Ringwald         reverse_bd_addr(local_address, &buffer[2]);
2550687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2551403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2552403280b9SMatthias Ringwald         return;
2553403280b9SMatthias Ringwald     }
25541d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION) != 0u){
2555403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
2556403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
2557403280b9SMatthias Ringwald 
2558403280b9SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
2559403280b9SMatthias Ringwald         // hack to reproduce test runs
2560403280b9SMatthias Ringwald                     if (test_use_fixed_local_csrk){
2561403280b9SMatthias Ringwald                         memset(setup->sm_local_csrk, 0xcc, 16);
2562403280b9SMatthias Ringwald                     }
2563403280b9SMatthias Ringwald 
2564403280b9SMatthias Ringwald                     // store local CSRK
2565403280b9SMatthias Ringwald                     if (setup->sm_le_device_index >= 0){
2566403280b9SMatthias Ringwald                         log_info("sm: store local CSRK");
2567403280b9SMatthias Ringwald                         le_device_db_local_csrk_set(setup->sm_le_device_index, setup->sm_local_csrk);
2568403280b9SMatthias Ringwald                         le_device_db_local_counter_set(setup->sm_le_device_index, 0);
2569403280b9SMatthias Ringwald                     }
2570403280b9SMatthias Ringwald #endif
2571403280b9SMatthias Ringwald 
2572403280b9SMatthias Ringwald         uint8_t buffer[17];
2573403280b9SMatthias Ringwald         buffer[0] = SM_CODE_SIGNING_INFORMATION;
2574403280b9SMatthias Ringwald         reverse_128(setup->sm_local_csrk, &buffer[1]);
2575687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2576403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2577403280b9SMatthias Ringwald         return;
2578403280b9SMatthias Ringwald     }
2579403280b9SMatthias Ringwald     btstack_assert(false);
2580403280b9SMatthias Ringwald }
2581403280b9SMatthias Ringwald 
sm_ctkd_from_le(sm_connection_t * sm_connection)2582bbd73538SMatthias Ringwald static bool sm_ctkd_from_le(sm_connection_t *sm_connection) {
2583bbd73538SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
2584bbd73538SMatthias Ringwald     // requirements to derive link key from  LE:
2585bbd73538SMatthias Ringwald     // - use secure connections
2586bbd73538SMatthias Ringwald     if (setup->sm_use_secure_connections == 0) return false;
2587bbd73538SMatthias Ringwald     // - bonding needs to be enabled:
2588bbd73538SMatthias Ringwald     bool bonding_enabled = (sm_pairing_packet_get_auth_req(setup->sm_m_preq) & sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_BONDING ) != 0u;
2589bbd73538SMatthias Ringwald     if (!bonding_enabled) return false;
2590bbd73538SMatthias Ringwald     // - need identity address / public addr
2591bbd73538SMatthias Ringwald     bool have_identity_address_info = ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION) != 0) || (setup->sm_peer_addr_type == 0);
2592bbd73538SMatthias Ringwald     if (!have_identity_address_info) return false;
2593bbd73538SMatthias Ringwald     // - there is no stored BR/EDR link key or the derived key has at least the same level of authentication (bail if stored key has higher authentication)
2594bbd73538SMatthias Ringwald     //   this requirement is motivated by BLURtooth paper. The paper recommends to not overwrite keys at all.
2595bbd73538SMatthias Ringwald     //      If SC is authenticated, we consider it safe to overwrite a stored key.
2596bbd73538SMatthias Ringwald     //      If stored link key is not authenticated, it could already be compromised by a MITM attack. Allowing overwrite by unauthenticated derived key does not make it worse.
2597bbd73538SMatthias Ringwald     uint8_t link_key[16];
2598bbd73538SMatthias Ringwald     link_key_type_t link_key_type;
2599bbd73538SMatthias Ringwald     bool have_link_key             = gap_get_link_key_for_bd_addr(setup->sm_peer_address, link_key, &link_key_type);
26007040ba26SMatthias Ringwald     bool link_key_authenticated    = gap_authenticated_for_link_key_type(link_key_type);
2601bbd73538SMatthias Ringwald     bool derived_key_authenticated = sm_connection->sm_connection_authenticated != 0;
2602bbd73538SMatthias Ringwald     if (have_link_key && link_key_authenticated && !derived_key_authenticated) {
2603bbd73538SMatthias Ringwald         return false;
2604bbd73538SMatthias Ringwald     }
2605bbd73538SMatthias Ringwald     // get started (all of the above are true)
2606bbd73538SMatthias Ringwald     return true;
2607bbd73538SMatthias Ringwald #else
2608bbd73538SMatthias Ringwald     UNUSED(sm_connection);
2609bbd73538SMatthias Ringwald 	return false;
2610bbd73538SMatthias Ringwald #endif
2611bbd73538SMatthias Ringwald }
2612bbd73538SMatthias Ringwald 
26136a718a5eSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
sm_ctkd_from_classic(sm_connection_t * sm_connection)26146a718a5eSMatthias Ringwald static bool sm_ctkd_from_classic(sm_connection_t * sm_connection){
26156a718a5eSMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(sm_connection->sm_handle);
26166a718a5eSMatthias Ringwald     btstack_assert(hci_connection != NULL);
26176a718a5eSMatthias Ringwald     // requirements to derive ltk from BR/EDR:
26186a718a5eSMatthias Ringwald     // - BR/EDR uses secure connections
26196a718a5eSMatthias Ringwald     if (gap_secure_connection_for_link_key_type(hci_connection->link_key_type) == false) return false;
26206a718a5eSMatthias Ringwald     // - there is no stored LTK or the derived key has at least the same level of authentication (bail if LTK is authenticated but Link Key isn't)
26216a718a5eSMatthias Ringwald     bool link_key_authenticated = gap_authenticated_for_link_key_type(hci_connection->link_key_type);
26226a718a5eSMatthias Ringwald     if (link_key_authenticated) return true;
26236a718a5eSMatthias Ringwald     int index = sm_le_device_db_index_lookup(BD_ADDR_TYPE_LE_PUBLIC, hci_connection->address);
26246a718a5eSMatthias Ringwald     if (index >= 0){
26256a718a5eSMatthias Ringwald         int ltk_authenticated;
26266a718a5eSMatthias Ringwald         sm_key_t ltk;
26276a718a5eSMatthias Ringwald         le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, &ltk_authenticated, NULL, NULL);
26286a718a5eSMatthias Ringwald         bool have_ltk = !sm_is_null_key(ltk);
26296a718a5eSMatthias Ringwald         if (have_ltk && ltk_authenticated) return false;
26306a718a5eSMatthias Ringwald     }
26316a718a5eSMatthias Ringwald     return true;
26326a718a5eSMatthias Ringwald }
26336a718a5eSMatthias Ringwald #endif
26346a718a5eSMatthias Ringwald 
sm_key_distribution_complete_responder(sm_connection_t * connection)26356f7422f1SMatthias Ringwald static void sm_key_distribution_complete_responder(sm_connection_t * connection){
26366f7422f1SMatthias Ringwald     if (sm_ctkd_from_le(connection)){
26376f7422f1SMatthias Ringwald         bool use_h7 = (sm_pairing_packet_get_auth_req(setup->sm_m_preq) & sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_CT2) != 0;
26386f7422f1SMatthias Ringwald         connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
26396f7422f1SMatthias Ringwald     } else {
26406f7422f1SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_IDLE;
26416f7422f1SMatthias Ringwald         sm_pairing_complete(connection, ERROR_CODE_SUCCESS, 0);
26426f7422f1SMatthias Ringwald         sm_done_for_handle(connection->sm_handle);
26436f7422f1SMatthias Ringwald     }
26446f7422f1SMatthias Ringwald }
26456f7422f1SMatthias Ringwald 
sm_key_distribution_complete_initiator(sm_connection_t * connection)2646af7ef9d1SMatthias Ringwald static void sm_key_distribution_complete_initiator(sm_connection_t * connection){
2647af7ef9d1SMatthias Ringwald     if (sm_ctkd_from_le(connection)){
2648af7ef9d1SMatthias Ringwald         bool use_h7 = (sm_pairing_packet_get_auth_req(setup->sm_m_preq) & sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_CT2) != 0;
2649af7ef9d1SMatthias Ringwald         connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
2650af7ef9d1SMatthias Ringwald     } else {
2651af7ef9d1SMatthias Ringwald         sm_master_pairing_success(connection);
2652af7ef9d1SMatthias Ringwald     }
2653af7ef9d1SMatthias Ringwald }
2654af7ef9d1SMatthias Ringwald 
2655b919f264SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_run_state_sc_send_confirmation(sm_connection_t * connection)2656b919f264SMatthias Ringwald static void sm_run_state_sc_send_confirmation(sm_connection_t *connection) {
2657b919f264SMatthias Ringwald     uint8_t buffer[17];
2658b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_CONFIRM;
2659b919f264SMatthias Ringwald     reverse_128(setup->sm_local_confirm, &buffer[1]);
2660b919f264SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
2661b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2662b919f264SMatthias Ringwald     } else {
2663b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2664b919f264SMatthias Ringwald     }
2665b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2666b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2667b919f264SMatthias Ringwald }
2668b919f264SMatthias Ringwald 
sm_run_state_sc_send_pairing_random(sm_connection_t * connection)2669b919f264SMatthias Ringwald static void sm_run_state_sc_send_pairing_random(sm_connection_t *connection) {
2670b919f264SMatthias Ringwald     uint8_t buffer[17];
2671b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_RANDOM;
2672b919f264SMatthias Ringwald     reverse_128(setup->sm_local_nonce, &buffer[1]);
2673b919f264SMatthias Ringwald     log_info("stk method %u, bit num: %u", setup->sm_stk_generation_method, setup->sm_passkey_bit);
2674b919f264SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method) && (setup->sm_passkey_bit < 20u)){
2675b919f264SMatthias Ringwald         log_info("SM_SC_SEND_PAIRING_RANDOM A");
2676b919f264SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
2677b919f264SMatthias Ringwald             // responder
2678b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2679b919f264SMatthias Ringwald         } else {
2680b919f264SMatthias Ringwald             // initiator
2681b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2682b919f264SMatthias Ringwald         }
2683b919f264SMatthias Ringwald     } else {
2684b919f264SMatthias Ringwald         log_info("SM_SC_SEND_PAIRING_RANDOM B");
2685b919f264SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
2686b919f264SMatthias Ringwald             // responder
2687b919f264SMatthias Ringwald             if (setup->sm_stk_generation_method == NUMERIC_COMPARISON){
2688b919f264SMatthias Ringwald                 log_info("SM_SC_SEND_PAIRING_RANDOM B1");
2689b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W2_CALCULATE_G2;
2690b919f264SMatthias Ringwald             } else {
2691b919f264SMatthias Ringwald                 log_info("SM_SC_SEND_PAIRING_RANDOM B2");
2692b919f264SMatthias Ringwald                 sm_sc_prepare_dhkey_check(connection);
2693b919f264SMatthias Ringwald             }
2694b919f264SMatthias Ringwald         } else {
2695b919f264SMatthias Ringwald             // initiator
2696b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2697b919f264SMatthias Ringwald         }
2698b919f264SMatthias Ringwald     }
2699b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2700b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2701b919f264SMatthias Ringwald }
2702b919f264SMatthias Ringwald 
sm_run_state_sc_send_dhkey_check_command(sm_connection_t * connection)2703b919f264SMatthias Ringwald static void sm_run_state_sc_send_dhkey_check_command(sm_connection_t *connection) {
2704b919f264SMatthias Ringwald     uint8_t buffer[17];
2705b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_DHKEY_CHECK;
2706b919f264SMatthias Ringwald     reverse_128(setup->sm_local_dhkey_check, &buffer[1]);
2707b919f264SMatthias Ringwald 
2708b919f264SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
2709b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_LTK_REQUEST_SC;
2710b919f264SMatthias Ringwald     } else {
2711b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
2712b919f264SMatthias Ringwald     }
2713b919f264SMatthias Ringwald 
2714b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2715b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2716b919f264SMatthias Ringwald }
2717b919f264SMatthias Ringwald 
sm_run_state_sc_send_public_key_command(sm_connection_t * connection)2718b919f264SMatthias Ringwald static void sm_run_state_sc_send_public_key_command(sm_connection_t *connection) {
2719b919f264SMatthias Ringwald     bool trigger_user_response   = false;
2720b919f264SMatthias Ringwald     bool trigger_start_calculating_local_confirm = false;
2721b919f264SMatthias Ringwald     uint8_t buffer[65];
2722b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_PUBLIC_KEY;
2723b919f264SMatthias Ringwald     //
2724b919f264SMatthias Ringwald     reverse_256(&ec_q[0],  &buffer[1]);
2725b919f264SMatthias Ringwald     reverse_256(&ec_q[32], &buffer[33]);
2726b919f264SMatthias Ringwald 
2727b919f264SMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
2728b919f264SMatthias Ringwald     if (test_pairing_failure == SM_REASON_DHKEY_CHECK_FAILED){
2729b919f264SMatthias Ringwald             log_info("testing_support: invalidating public key");
2730b919f264SMatthias Ringwald             // flip single bit of public key coordinate
2731b919f264SMatthias Ringwald             buffer[1] ^= 1;
2732b919f264SMatthias Ringwald         }
2733b919f264SMatthias Ringwald #endif
2734b919f264SMatthias Ringwald 
2735b919f264SMatthias Ringwald     // stk generation method
2736b919f264SMatthias Ringwald // passkey entry: notify app to show passkey or to request passkey
2737b919f264SMatthias Ringwald     switch (setup->sm_stk_generation_method){
2738b919f264SMatthias Ringwald         case JUST_WORKS:
2739b919f264SMatthias Ringwald         case NUMERIC_COMPARISON:
2740b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2741b919f264SMatthias Ringwald                 // responder
2742b919f264SMatthias Ringwald                 trigger_start_calculating_local_confirm = true;
2743b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_LOCAL_NONCE;
2744b919f264SMatthias Ringwald             } else {
2745b919f264SMatthias Ringwald                 // initiator
2746b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2747b919f264SMatthias Ringwald             }
2748b919f264SMatthias Ringwald             break;
2749b919f264SMatthias Ringwald         case PK_INIT_INPUT:
2750b919f264SMatthias Ringwald         case PK_RESP_INPUT:
2751b919f264SMatthias Ringwald         case PK_BOTH_INPUT:
2752b919f264SMatthias Ringwald             // use random TK for display
2753b919f264SMatthias Ringwald             (void)memcpy(setup->sm_ra, setup->sm_tk, 16);
2754b919f264SMatthias Ringwald             (void)memcpy(setup->sm_rb, setup->sm_tk, 16);
2755b919f264SMatthias Ringwald             setup->sm_passkey_bit = 0;
2756b919f264SMatthias Ringwald 
2757b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2758b919f264SMatthias Ringwald                 // responder
2759b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2760b919f264SMatthias Ringwald             } else {
2761b919f264SMatthias Ringwald                 // initiator
2762b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2763b919f264SMatthias Ringwald             }
2764b919f264SMatthias Ringwald             trigger_user_response = true;
2765b919f264SMatthias Ringwald             break;
2766b919f264SMatthias Ringwald         case OOB:
2767b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2768b919f264SMatthias Ringwald                 // responder
2769b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2770b919f264SMatthias Ringwald             } else {
2771b919f264SMatthias Ringwald                 // initiator
2772b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2773b919f264SMatthias Ringwald             }
2774b919f264SMatthias Ringwald             break;
2775b919f264SMatthias Ringwald         default:
2776b919f264SMatthias Ringwald             btstack_assert(false);
2777b919f264SMatthias Ringwald             break;
2778b919f264SMatthias Ringwald     }
2779b919f264SMatthias Ringwald 
2780b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2781b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2782b919f264SMatthias Ringwald 
2783b919f264SMatthias Ringwald     // trigger user response and calc confirm after sending pdu
2784b919f264SMatthias Ringwald     if (trigger_user_response){
2785b919f264SMatthias Ringwald         sm_trigger_user_response(connection);
2786b919f264SMatthias Ringwald     }
2787b919f264SMatthias Ringwald     if (trigger_start_calculating_local_confirm){
2788b919f264SMatthias Ringwald         sm_sc_start_calculating_local_confirm(connection);
2789b919f264SMatthias Ringwald     }
2790b919f264SMatthias Ringwald }
2791b919f264SMatthias Ringwald #endif
2792b919f264SMatthias Ringwald 
sm_run_non_connection_logic(void)2793de42cac5SMatthias Ringwald static bool sm_run_non_connection_logic(void){
2794de42cac5SMatthias Ringwald     bool done;;
2795de42cac5SMatthias Ringwald 
2796de42cac5SMatthias Ringwald     done = sm_run_dpkg();
2797de42cac5SMatthias Ringwald     if (done) return true;
2798de42cac5SMatthias Ringwald 
2799de42cac5SMatthias Ringwald     done = sm_run_rau();
2800de42cac5SMatthias Ringwald     if (done) return true;
2801de42cac5SMatthias Ringwald 
280251258968SMatthias Ringwald     done = sm_run_irk_lookup();
2803de42cac5SMatthias Ringwald     if (done) return true;
2804de42cac5SMatthias Ringwald 
2805de42cac5SMatthias Ringwald     done = sm_run_oob();
2806de42cac5SMatthias Ringwald     return done;
2807de42cac5SMatthias Ringwald }
2808b919f264SMatthias Ringwald 
sm_run_ready(void)2809*f99c988aSMatthias Ringwald static bool sm_run_ready(void) {
2810*f99c988aSMatthias Ringwald     // assert that stack has already booted
2811*f99c988aSMatthias Ringwald     if (hci_get_state() != HCI_STATE_WORKING) return false;
2812d7f1c72eSMatthias Ringwald 
2813d7f1c72eSMatthias Ringwald     // assert that we can send at least commands
2814*f99c988aSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return false;
2815d7f1c72eSMatthias Ringwald 
2816d7f1c72eSMatthias Ringwald     // pause until IR/ER are ready
2817*f99c988aSMatthias Ringwald     if (sm_persistent_keys_random_active) return false;
2818*f99c988aSMatthias Ringwald 
2819*f99c988aSMatthias Ringwald     return true;
2820*f99c988aSMatthias Ringwald }
2821*f99c988aSMatthias Ringwald 
sm_run(void)2822*f99c988aSMatthias Ringwald static void sm_run(void){
2823*f99c988aSMatthias Ringwald 
2824*f99c988aSMatthias Ringwald     // ready
2825*f99c988aSMatthias Ringwald     if (sm_run_ready() == false) return;
2826d7f1c72eSMatthias Ringwald 
2827d7f1c72eSMatthias Ringwald     // non-connection related behaviour
2828de42cac5SMatthias Ringwald     bool done = sm_run_non_connection_logic();
2829d7f1c72eSMatthias Ringwald     if (done) return;
2830d7f1c72eSMatthias Ringwald 
2831d7f1c72eSMatthias Ringwald     // assert that we can send at least commands - cmd might have been sent by crypto engine
2832d7f1c72eSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return;
2833d7f1c72eSMatthias Ringwald 
2834d7f1c72eSMatthias Ringwald     // handle basic actions that don't requires the full context
2835d7f1c72eSMatthias Ringwald     done = sm_run_basic();
2836d7f1c72eSMatthias Ringwald     if (done) return;
2837d7f1c72eSMatthias Ringwald 
2838d7f1c72eSMatthias Ringwald     //
2839d7f1c72eSMatthias Ringwald     // active connection handling
2840d7f1c72eSMatthias Ringwald     // -- use loop to handle next connection if lock on setup context is released
2841d7f1c72eSMatthias Ringwald 
2842d7f1c72eSMatthias Ringwald     while (true) {
2843d7f1c72eSMatthias Ringwald 
2844d7f1c72eSMatthias Ringwald         sm_run_activate_connection();
2845d7f1c72eSMatthias Ringwald 
2846d7f1c72eSMatthias Ringwald         if (sm_active_connection_handle == HCI_CON_HANDLE_INVALID) return;
28473deb3ec6SMatthias Ringwald 
28483deb3ec6SMatthias Ringwald         //
28493deb3ec6SMatthias Ringwald         // active connection handling
28503deb3ec6SMatthias Ringwald         //
28513deb3ec6SMatthias Ringwald 
28523cf37b8cSMatthias Ringwald         sm_connection_t * connection = sm_get_connection_for_handle(sm_active_connection_handle);
28533cf37b8cSMatthias Ringwald         if (!connection) {
28543cf37b8cSMatthias Ringwald             log_info("no connection for handle 0x%04x", sm_active_connection_handle);
28553cf37b8cSMatthias Ringwald             return;
28563cf37b8cSMatthias Ringwald         }
28573cf37b8cSMatthias Ringwald 
28583deb3ec6SMatthias Ringwald         // assert that we could send a SM PDU - not needed for all of the following
2859384eabd3SMatthias Ringwald         if (!l2cap_can_send_fixed_channel_packet_now(sm_active_connection_handle, connection->sm_cid)) {
28607149bde5SMatthias Ringwald             log_info("cannot send now, requesting can send now event");
2861384eabd3SMatthias Ringwald             l2cap_request_can_send_fix_channel_now_event(sm_active_connection_handle, connection->sm_cid);
2862b170b20fSMatthias Ringwald             return;
2863b170b20fSMatthias Ringwald         }
28643deb3ec6SMatthias Ringwald 
28653d7fe1e9SMatthias Ringwald         // send keypress notifications
28661d80f1e6SMatthias Ringwald         if (setup->sm_keypress_notification != 0u){
2867403280b9SMatthias Ringwald             sm_run_send_keypress_notification(connection);
2868d7471931SMatthias Ringwald             return;
28693d7fe1e9SMatthias Ringwald         }
28703d7fe1e9SMatthias Ringwald 
2871f7ea4423SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2872234022e5SMatthias Ringwald         // assert that sm cmac engine is ready
2873234022e5SMatthias Ringwald         if (sm_cmac_ready() == false){
2874234022e5SMatthias Ringwald             break;
2875234022e5SMatthias Ringwald         }
2876f7ea4423SMatthias Ringwald #endif
2877234022e5SMatthias Ringwald 
28782e7060d6SMatthias Ringwald         // initialize to avoid 'maybe used uninitialized' error
28792e7060d6SMatthias Ringwald         int key_distribution_flags = 0;
288042134bc6SMatthias Ringwald         UNUSED(key_distribution_flags);
2881b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
2882b6afa23eSMatthias Ringwald         int err;
28839b75de03SMatthias Ringwald         bool have_ltk;
28849b75de03SMatthias Ringwald         uint8_t ltk[16];
2885b6f39a74SMatthias Ringwald #endif
28863deb3ec6SMatthias Ringwald 
28873deb3ec6SMatthias Ringwald         log_info("sm_run: state %u", connection->sm_engine_state);
28883deb3ec6SMatthias Ringwald         switch (connection->sm_engine_state){
28893deb3ec6SMatthias Ringwald 
2890f32b7a88SMatthias Ringwald             // secure connections, initiator + responding states
2891aec94140SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2892aec94140SMatthias Ringwald             case SM_SC_W2_CMAC_FOR_CONFIRMATION:
2893aec94140SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CMAC_FOR_CONFIRMATION;
2894aec94140SMatthias Ringwald                 sm_sc_calculate_local_confirm(connection);
2895aec94140SMatthias Ringwald                 break;
2896688a08f9SMatthias Ringwald             case SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION:
2897688a08f9SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION;
2898688a08f9SMatthias Ringwald                 sm_sc_calculate_remote_confirm(connection);
2899688a08f9SMatthias Ringwald                 break;
2900dc300847SMatthias Ringwald             case SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK:
2901dc300847SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK;
2902dc300847SMatthias Ringwald                 sm_sc_calculate_f6_for_dhkey_check(connection);
2903dc300847SMatthias Ringwald                 break;
2904019005a0SMatthias Ringwald             case SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
2905019005a0SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
29060346c37cSMatthias Ringwald                 sm_sc_calculate_f6_to_verify_dhkey_check(connection);
29070346c37cSMatthias Ringwald                 break;
29080346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_SALT:
29090346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_SALT;
29100346c37cSMatthias Ringwald                 f5_calculate_salt(connection);
29110346c37cSMatthias Ringwald                 break;
29120346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_MACKEY:
29130346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_MACKEY;
29140346c37cSMatthias Ringwald                 f5_calculate_mackey(connection);
29150346c37cSMatthias Ringwald                 break;
29160346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_LTK:
29170346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_LTK;
29180346c37cSMatthias Ringwald                 f5_calculate_ltk(connection);
2919019005a0SMatthias Ringwald                 break;
2920bd57ffebSMatthias Ringwald             case SM_SC_W2_CALCULATE_G2:
2921bd57ffebSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_G2;
2922b35a3de2SMatthias Ringwald                 g2_calculate(connection);
2923bd57ffebSMatthias Ringwald                 break;
2924e0a03c85SMatthias Ringwald #endif
2925e0a03c85SMatthias Ringwald 
292642134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
29273deb3ec6SMatthias Ringwald             // initiator side
2928f32b7a88SMatthias Ringwald 
29295567aa60SMatthias Ringwald             case SM_INITIATOR_PH4_HAS_LTK: {
2930f32b7a88SMatthias Ringwald 				sm_reset_setup();
2931f32b7a88SMatthias Ringwald 				sm_load_security_info(connection);
2932f32b7a88SMatthias Ringwald 
2933bcab6650SMatthias Ringwald                 // cache key before using
2934f76e733aSMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_peer_ltk);
2935bcab6650SMatthias Ringwald 
29363deb3ec6SMatthias Ringwald                 sm_key_t peer_ltk_flipped;
29379c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_peer_ltk, peer_ltk_flipped);
29385567aa60SMatthias Ringwald                 connection->sm_engine_state = SM_PH4_W4_CONNECTION_ENCRYPTED;
29393deb3ec6SMatthias Ringwald                 log_info("sm: hci_le_start_encryption ediv 0x%04x", setup->sm_peer_ediv);
2940c9b8fdd9SMatthias Ringwald                 uint32_t rand_high = big_endian_read_32(setup->sm_peer_rand, 0);
2941c9b8fdd9SMatthias Ringwald                 uint32_t rand_low  = big_endian_read_32(setup->sm_peer_rand, 4);
29423deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_start_encryption, connection->sm_handle,rand_low, rand_high, setup->sm_peer_ediv, peer_ltk_flipped);
294349c9e430SMatthias Ringwald 
294449c9e430SMatthias Ringwald                 // notify after sending
294549c9e430SMatthias Ringwald                 sm_reencryption_started(connection);
29463deb3ec6SMatthias Ringwald                 return;
29473deb3ec6SMatthias Ringwald             }
29483deb3ec6SMatthias Ringwald 
2949b26f445fSMatthias Ringwald 			case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
2950b26f445fSMatthias Ringwald 				sm_reset_setup();
2951b26f445fSMatthias Ringwald 				sm_init_setup(connection);
2952b26f445fSMatthias Ringwald 
29531ad129beSMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST);
29543deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_INITIATOR_PH1_W4_PAIRING_RESPONSE;
2955687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
29563deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
295749c9e430SMatthias Ringwald 
295849c9e430SMatthias Ringwald                 // notify after sending
295949c9e430SMatthias Ringwald                 sm_pairing_started(connection);
29603deb3ec6SMatthias Ringwald                 break;
296142134bc6SMatthias Ringwald #endif
29623deb3ec6SMatthias Ringwald 
296327c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2964b919f264SMatthias Ringwald             case SM_SC_SEND_PUBLIC_KEY_COMMAND:
2965b919f264SMatthias Ringwald                 sm_run_state_sc_send_public_key_command(connection);
296645a61d50SMatthias Ringwald                 break;
2967b919f264SMatthias Ringwald             case SM_SC_SEND_CONFIRMATION:
2968b919f264SMatthias Ringwald                 sm_run_state_sc_send_confirmation(connection);
296945a61d50SMatthias Ringwald                 break;
2970b919f264SMatthias Ringwald             case SM_SC_SEND_PAIRING_RANDOM:
2971b919f264SMatthias Ringwald                 sm_run_state_sc_send_pairing_random(connection);
297245a61d50SMatthias Ringwald                 break;
2973b919f264SMatthias Ringwald             case SM_SC_SEND_DHKEY_CHECK_COMMAND:
2974b919f264SMatthias Ringwald                 sm_run_state_sc_send_dhkey_check_command(connection);
29757bbeb3adSMilanka Ringwald                 break;
2976e53be891SMatthias Ringwald #endif
297742134bc6SMatthias Ringwald 
297842134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
2979dd12a62bSMatthias Ringwald 
298087014f74SMatthias Ringwald 			case SM_RESPONDER_SEND_SECURITY_REQUEST: {
298187014f74SMatthias Ringwald 				const uint8_t buffer[2] = {SM_CODE_SECURITY_REQUEST, sm_auth_req};
298287014f74SMatthias Ringwald 				connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
2983687a03c8SMatthias Ringwald 				sm_send_connectionless(connection,  (uint8_t *) buffer, sizeof(buffer));
2984c8d0ff33SMatthias Ringwald 				sm_timeout_start(connection);
298587014f74SMatthias Ringwald 				break;
298687014f74SMatthias Ringwald 			}
298787014f74SMatthias Ringwald 
298838196718SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
298938196718SMatthias Ringwald 			case SM_SC_RECEIVED_LTK_REQUEST:
299038196718SMatthias Ringwald 				switch (connection->sm_irk_lookup_state){
299138196718SMatthias Ringwald 					case IRK_LOOKUP_SUCCEEDED:
299238196718SMatthias Ringwald 						// assuming Secure Connection, we have a stored LTK and the EDIV/RAND are null
299338196718SMatthias Ringwald 						// start using context by loading security info
299438196718SMatthias Ringwald 						sm_reset_setup();
299538196718SMatthias Ringwald 						sm_load_security_info(connection);
299638196718SMatthias Ringwald 						if ((setup->sm_peer_ediv == 0u) && sm_is_null_random(setup->sm_peer_rand) && !sm_is_null_key(setup->sm_peer_ltk)){
299738196718SMatthias Ringwald 							(void)memcpy(setup->sm_ltk, setup->sm_peer_ltk, 16);
299838196718SMatthias Ringwald 							connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
299942646f38SMatthias Ringwald                             sm_reencryption_started(connection);
300038196718SMatthias Ringwald                             sm_trigger_run();
300138196718SMatthias Ringwald 							break;
300238196718SMatthias Ringwald 						}
300338196718SMatthias Ringwald 						log_info("LTK Request: ediv & random are empty, but no stored LTK (IRK Lookup Succeeded)");
300438196718SMatthias Ringwald 						connection->sm_engine_state = SM_RESPONDER_IDLE;
300538196718SMatthias Ringwald 						hci_send_cmd(&hci_le_long_term_key_negative_reply, connection->sm_handle);
300638196718SMatthias Ringwald 						return;
300738196718SMatthias Ringwald 					default:
300838196718SMatthias Ringwald 						// just wait until IRK lookup is completed
300938196718SMatthias Ringwald 						break;
301038196718SMatthias Ringwald 				}
301138196718SMatthias Ringwald 				break;
301238196718SMatthias Ringwald #endif /* ENABLE_LE_SECURE_CONNECTIONS */
301338196718SMatthias Ringwald 
3014b6afa23eSMatthias Ringwald 			case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
3015b6afa23eSMatthias Ringwald                 sm_reset_setup();
30169b75de03SMatthias Ringwald 
30179b75de03SMatthias Ringwald 			    // handle Pairing Request with LTK available
30189b75de03SMatthias Ringwald                 switch (connection->sm_irk_lookup_state) {
30199b75de03SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
30209b75de03SMatthias Ringwald                         le_device_db_encryption_get(connection->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
30219b75de03SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
30229b75de03SMatthias Ringwald                         if (have_ltk){
30239b75de03SMatthias Ringwald                             log_info("pairing request but LTK available");
302419a40772SMatthias Ringwald                             // emit re-encryption start/fail sequence
30259b75de03SMatthias Ringwald                             sm_reencryption_started(connection);
30269b75de03SMatthias Ringwald                             sm_reencryption_complete(connection, ERROR_CODE_PIN_OR_KEY_MISSING);
30279b75de03SMatthias Ringwald                         }
30289b75de03SMatthias Ringwald                         break;
30299b75de03SMatthias Ringwald                     default:
30309b75de03SMatthias Ringwald                         break;
30319b75de03SMatthias Ringwald                 }
30329b75de03SMatthias Ringwald 
3033b6afa23eSMatthias Ringwald 				sm_init_setup(connection);
303439543d07SMatthias Ringwald 
3035b6afa23eSMatthias Ringwald 				// recover pairing request
3036b6afa23eSMatthias Ringwald 				(void)memcpy(&setup->sm_m_preq, &connection->sm_m_preq, sizeof(sm_pairing_packet_t));
3037b6afa23eSMatthias Ringwald 				err = sm_stk_generation_init(connection);
3038b6afa23eSMatthias Ringwald 
3039b6afa23eSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
3040b6afa23eSMatthias Ringwald 				if ((0 < test_pairing_failure) && (test_pairing_failure < SM_REASON_DHKEY_CHECK_FAILED)){
3041b6afa23eSMatthias Ringwald                         log_info("testing_support: respond with pairing failure %u", test_pairing_failure);
3042b6afa23eSMatthias Ringwald                         err = test_pairing_failure;
3043b6afa23eSMatthias Ringwald                     }
3044b6afa23eSMatthias Ringwald #endif
30459305033eSMatthias Ringwald 				if (err != 0){
304649c9e430SMatthias Ringwald                     // emit pairing started/failed sequence
304749c9e430SMatthias Ringwald                     sm_pairing_started(connection);
3048f4935286SMatthias Ringwald                     sm_pairing_error(connection, err);
3049b6afa23eSMatthias Ringwald 					sm_trigger_run();
3050b6afa23eSMatthias Ringwald 					break;
3051b6afa23eSMatthias Ringwald 				}
3052b6afa23eSMatthias Ringwald 
3053b6afa23eSMatthias Ringwald 				sm_timeout_start(connection);
3054b6afa23eSMatthias Ringwald 
3055b6afa23eSMatthias Ringwald 				// generate random number first, if we need to show passkey, otherwise send response
3056b6afa23eSMatthias Ringwald 				if (setup->sm_stk_generation_method == PK_INIT_INPUT){
3057b6afa23eSMatthias Ringwald 					btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph2_tk, (void *)(uintptr_t) connection->sm_handle);
3058b6afa23eSMatthias Ringwald 					break;
3059b6afa23eSMatthias Ringwald 				}
3060b6afa23eSMatthias Ringwald 
3061b6afa23eSMatthias Ringwald 				/* fall through */
3062b6afa23eSMatthias Ringwald 
30633deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE:
30641ad129beSMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_s_pres,SM_CODE_PAIRING_RESPONSE);
3065f55bd529SMatthias Ringwald 
3066f55bd529SMatthias Ringwald                 // start with initiator key dist flags
30673deb3ec6SMatthias Ringwald                 key_distribution_flags = sm_key_distribution_flags_for_auth_req();
30681ad129beSMatthias Ringwald 
3069f55bd529SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
3070b2072c76SMatthias Ringwald                 // LTK (= encryption information & master identification) only exchanged for LE Legacy Connection
3071f55bd529SMatthias Ringwald                 if (setup->sm_use_secure_connections){
3072f55bd529SMatthias Ringwald                     key_distribution_flags &= ~SM_KEYDIST_ENC_KEY;
3073f55bd529SMatthias Ringwald                 }
3074f55bd529SMatthias Ringwald #endif
3075f55bd529SMatthias Ringwald                 // setup in response
3076f55bd529SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_s_pres, sm_pairing_packet_get_initiator_key_distribution(setup->sm_m_preq) & key_distribution_flags);
3077f55bd529SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_s_pres, sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq) & key_distribution_flags);
3078f55bd529SMatthias Ringwald 
3079f55bd529SMatthias Ringwald                 // update key distribution after ENC was dropped
30809a90d41aSMatthias Ringwald                 sm_setup_key_distribution(sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres), sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres));
3081f55bd529SMatthias Ringwald 
308227c32905SMatthias Ringwald                 if (setup->sm_use_secure_connections){
3083c6b7cbd9SMatthias Ringwald                     connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
30840b8af2a5SMatthias Ringwald                 } else {
30850b8af2a5SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_CONFIRM;
308627c32905SMatthias Ringwald                 }
30870b8af2a5SMatthias Ringwald 
3088687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
30893deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
309049c9e430SMatthias Ringwald 
309149c9e430SMatthias Ringwald                 // notify after sending
309249c9e430SMatthias Ringwald                 sm_pairing_started(connection);
309349c9e430SMatthias Ringwald 
3094446a8c36SMatthias Ringwald                 // SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
3095c1ab6cc1SMatthias Ringwald                 if (!setup->sm_use_secure_connections || (setup->sm_stk_generation_method == JUST_WORKS)){
30963deb3ec6SMatthias Ringwald                     sm_trigger_user_response(connection);
3097446a8c36SMatthias Ringwald                 }
30983deb3ec6SMatthias Ringwald                 return;
309942134bc6SMatthias Ringwald #endif
31003deb3ec6SMatthias Ringwald 
31013deb3ec6SMatthias Ringwald             case SM_PH2_SEND_PAIRING_RANDOM: {
31023deb3ec6SMatthias Ringwald                 uint8_t buffer[17];
31033deb3ec6SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_RANDOM;
31049c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_local_random, &buffer[1]);
310542134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
31063deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH2_W4_LTK_REQUEST;
31073deb3ec6SMatthias Ringwald                 } else {
31083deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_RANDOM;
31093deb3ec6SMatthias Ringwald                 }
3110687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
31113deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
31123deb3ec6SMatthias Ringwald                 break;
31133deb3ec6SMatthias Ringwald             }
31143deb3ec6SMatthias Ringwald 
3115d1a1f6a4SMatthias Ringwald             case SM_PH2_C1_GET_ENC_A:
31163deb3ec6SMatthias Ringwald                 // already busy?
31173deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
3118d1a1f6a4SMatthias Ringwald                 // calculate confirm using aes128 engine - step 1
3119d1a1f6a4SMatthias Ringwald                 sm_c1_t1(setup->sm_local_random, (uint8_t*) &setup->sm_m_preq, (uint8_t*) &setup->sm_s_pres, setup->sm_m_addr_type, setup->sm_s_addr_type, sm_aes128_plaintext);
3120d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_C1_W4_ENC_A;
3121d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3122f3582630SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, setup->sm_tk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_enc_a, (void *)(uintptr_t) connection->sm_handle);
31233deb3ec6SMatthias Ringwald                 break;
31243deb3ec6SMatthias Ringwald 
31253deb3ec6SMatthias Ringwald             case SM_PH2_C1_GET_ENC_C:
31263deb3ec6SMatthias Ringwald                 // already busy?
31273deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31283deb3ec6SMatthias Ringwald                 // calculate m_confirm using aes128 engine - step 1
3129d1a1f6a4SMatthias Ringwald                 sm_c1_t1(setup->sm_peer_random, (uint8_t*) &setup->sm_m_preq, (uint8_t*) &setup->sm_s_pres, setup->sm_m_addr_type, setup->sm_s_addr_type, sm_aes128_plaintext);
3130d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_C1_W4_ENC_C;
3131d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3132f3582630SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, setup->sm_tk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_enc_c, (void *)(uintptr_t) connection->sm_handle);
31333deb3ec6SMatthias Ringwald                 break;
3134d1a1f6a4SMatthias Ringwald 
31353deb3ec6SMatthias Ringwald             case SM_PH2_CALC_STK:
31363deb3ec6SMatthias Ringwald                 // already busy?
31373deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31383deb3ec6SMatthias Ringwald                 // calculate STK
313942134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
3140d1a1f6a4SMatthias Ringwald                     sm_s1_r_prime(setup->sm_local_random, setup->sm_peer_random, sm_aes128_plaintext);
31413deb3ec6SMatthias Ringwald                 } else {
3142d1a1f6a4SMatthias Ringwald                     sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, sm_aes128_plaintext);
31433deb3ec6SMatthias Ringwald                 }
3144d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_STK;
3145d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3146f3582630SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, setup->sm_tk, sm_aes128_plaintext, setup->sm_ltk, sm_handle_encryption_result_enc_stk, (void *)(uintptr_t) connection->sm_handle);
31473deb3ec6SMatthias Ringwald                 break;
3148d1a1f6a4SMatthias Ringwald 
31493deb3ec6SMatthias Ringwald             case SM_PH3_Y_GET_ENC:
31503deb3ec6SMatthias Ringwald                 // already busy?
31513deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31523deb3ec6SMatthias Ringwald                 // PH3B2 - calculate Y from      - enc
31539ad0dd7cSMatthias Ringwald 
31549ad0dd7cSMatthias Ringwald                 // dm helper (was sm_dm_r_prime)
31559ad0dd7cSMatthias Ringwald                 // r' = padding || r
31569ad0dd7cSMatthias Ringwald                 // r - 64 bit value
31579ad0dd7cSMatthias Ringwald                 memset(&sm_aes128_plaintext[0], 0, 8);
31586535961aSMatthias Ringwald                 (void)memcpy(&sm_aes128_plaintext[8], setup->sm_local_rand, 8);
31599ad0dd7cSMatthias Ringwald 
31603deb3ec6SMatthias Ringwald                 // Y = dm(DHK, Rand)
3161d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH3_Y_W4_ENC;
3162d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3163f3582630SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_dhk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_enc_ph3_y, (void *)(uintptr_t) connection->sm_handle);
3164d1a1f6a4SMatthias Ringwald                 break;
3165d1a1f6a4SMatthias Ringwald 
31663deb3ec6SMatthias Ringwald             case SM_PH2_C1_SEND_PAIRING_CONFIRM: {
31673deb3ec6SMatthias Ringwald                 uint8_t buffer[17];
31683deb3ec6SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_CONFIRM;
31699c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_local_confirm, &buffer[1]);
317042134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
31713deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH2_W4_PAIRING_RANDOM;
31723deb3ec6SMatthias Ringwald                 } else {
31733deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_CONFIRM;
31743deb3ec6SMatthias Ringwald                 }
3175687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
31763deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
31773deb3ec6SMatthias Ringwald                 return;
31783deb3ec6SMatthias Ringwald             }
317942134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
31803deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH2_SEND_LTK_REPLY: {
3181916ea5b2SMatthias Ringwald                 // cache key before using
3182916ea5b2SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
31833deb3ec6SMatthias Ringwald                 sm_key_t stk_flipped;
31849c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_ltk, stk_flipped);
31853deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
31863deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, stk_flipped);
31873deb3ec6SMatthias Ringwald                 return;
31883deb3ec6SMatthias Ringwald             }
3189d7471931SMatthias Ringwald             case SM_RESPONDER_PH4_SEND_LTK_REPLY: {
3190b96d60a6SMatthias Ringwald                 // allow to override LTK
3191b96d60a6SMatthias Ringwald                 if (sm_get_ltk_callback != NULL){
3192b96d60a6SMatthias Ringwald                     (void)(*sm_get_ltk_callback)(connection->sm_handle, connection->sm_peer_addr_type, connection->sm_peer_address, setup->sm_ltk);
3193b96d60a6SMatthias Ringwald                 }
3194916ea5b2SMatthias Ringwald                 // cache key before using
3195916ea5b2SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
31963deb3ec6SMatthias Ringwald                 sm_key_t ltk_flipped;
31979c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_ltk, ltk_flipped);
31985567aa60SMatthias Ringwald                 connection->sm_engine_state = SM_PH4_W4_CONNECTION_ENCRYPTED;
31993deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, ltk_flipped);
32003deb3ec6SMatthias Ringwald                 return;
32013deb3ec6SMatthias Ringwald             }
3202dd12a62bSMatthias Ringwald 
3203dd12a62bSMatthias Ringwald 			case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
32043deb3ec6SMatthias Ringwald                 // already busy?
32053deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
32063deb3ec6SMatthias Ringwald                 log_info("LTK Request: recalculating with ediv 0x%04x", setup->sm_local_ediv);
3207c61cfe5aSMatthias Ringwald 
3208dd12a62bSMatthias Ringwald 				sm_reset_setup();
3209dd12a62bSMatthias Ringwald 				sm_start_calculating_ltk_from_ediv_and_rand(connection);
3210dd12a62bSMatthias Ringwald 
321142646f38SMatthias Ringwald 				sm_reencryption_started(connection);
321242646f38SMatthias Ringwald 
3213c61cfe5aSMatthias Ringwald                 // dm helper (was sm_dm_r_prime)
3214c61cfe5aSMatthias Ringwald                 // r' = padding || r
3215c61cfe5aSMatthias Ringwald                 // r - 64 bit value
3216c61cfe5aSMatthias Ringwald                 memset(&sm_aes128_plaintext[0], 0, 8);
32176535961aSMatthias Ringwald                 (void)memcpy(&sm_aes128_plaintext[8], setup->sm_local_rand, 8);
3218c61cfe5aSMatthias Ringwald 
32193deb3ec6SMatthias Ringwald                 // Y = dm(DHK, Rand)
3220d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_RESPONDER_PH4_Y_W4_ENC;
3221d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3222f3582630SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_dhk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_enc_ph4_y, (void *)(uintptr_t) connection->sm_handle);
32233deb3ec6SMatthias Ringwald                 return;
322442134bc6SMatthias Ringwald #endif
322542134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
322642134bc6SMatthias Ringwald             case SM_INITIATOR_PH3_SEND_START_ENCRYPTION: {
3227bcab6650SMatthias Ringwald                 // cache key before using
3228bcab6650SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
3229bcab6650SMatthias Ringwald 
323042134bc6SMatthias Ringwald                 sm_key_t stk_flipped;
323142134bc6SMatthias Ringwald                 reverse_128(setup->sm_ltk, stk_flipped);
323242134bc6SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
323342134bc6SMatthias Ringwald                 hci_send_cmd(&hci_le_start_encryption, connection->sm_handle, 0, 0, 0, stk_flipped);
323442134bc6SMatthias Ringwald                 return;
323542134bc6SMatthias Ringwald             }
323642134bc6SMatthias Ringwald #endif
32373deb3ec6SMatthias Ringwald 
32383deb3ec6SMatthias Ringwald             case SM_PH3_DISTRIBUTE_KEYS:
3239e94757aeSMatthias Ringwald                 // send next key
3240403280b9SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
3241403280b9SMatthias Ringwald                     sm_run_distribute_keys(connection);
3242e94757aeSMatthias Ringwald                 }
3243e94757aeSMatthias Ringwald 
3244e94757aeSMatthias Ringwald                 // more to send?
3245e94757aeSMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
32463deb3ec6SMatthias Ringwald                     return;
32473deb3ec6SMatthias Ringwald                 }
32483deb3ec6SMatthias Ringwald 
32493deb3ec6SMatthias Ringwald                 // keys are sent
325042134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
32513deb3ec6SMatthias Ringwald                     // slave -> receive master keys if any
325261d1a45eSMatthias Ringwald                     if (sm_key_distribution_all_received()){
32533deb3ec6SMatthias Ringwald                         sm_key_distribution_handle_all_received(connection);
3254f5020412SMatthias Ringwald                         sm_key_distribution_complete_responder(connection);
3255f5020412SMatthias Ringwald                         // start CTKD right away
3256f5020412SMatthias Ringwald                         continue;
32573deb3ec6SMatthias Ringwald                     } else {
32583deb3ec6SMatthias Ringwald                         connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
32593deb3ec6SMatthias Ringwald                     }
32603deb3ec6SMatthias Ringwald                 } else {
32611dca9d8aSMatthias Ringwald                     sm_master_pairing_success(connection);
32623deb3ec6SMatthias Ringwald                 }
32633deb3ec6SMatthias Ringwald                 break;
32643deb3ec6SMatthias Ringwald 
3265c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3266c18be159SMatthias Ringwald             case SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST:
3267c18be159SMatthias Ringwald                 // fill in sm setup (lite version of sm_init_setup)
3268c18be159SMatthias Ringwald                 sm_reset_setup();
3269c18be159SMatthias Ringwald                 setup->sm_peer_addr_type = connection->sm_peer_addr_type;
3270c18be159SMatthias Ringwald                 setup->sm_m_addr_type = connection->sm_peer_addr_type;
3271c18be159SMatthias Ringwald                 setup->sm_s_addr_type = connection->sm_own_addr_type;
3272c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_peer_address, connection->sm_peer_address, 6);
3273c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_m_address, connection->sm_peer_address, 6);
3274c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_s_address, connection->sm_own_address, 6);
3275c18be159SMatthias Ringwald                 setup->sm_use_secure_connections = true;
3276c18be159SMatthias Ringwald                 sm_ctkd_fetch_br_edr_link_key(connection);
3277c18be159SMatthias Ringwald 
3278c18be159SMatthias Ringwald                 // Enc Key and IRK if requested
3279c18be159SMatthias Ringwald                 key_distribution_flags = SM_KEYDIST_ID_KEY | SM_KEYDIST_ENC_KEY;
3280c18be159SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
3281c18be159SMatthias Ringwald                 // Plus signing key if supported
3282c18be159SMatthias Ringwald                 key_distribution_flags |= SM_KEYDIST_ID_KEY;
3283c18be159SMatthias Ringwald #endif
3284c18be159SMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST);
3285c18be159SMatthias Ringwald                 sm_pairing_packet_set_io_capability(setup->sm_m_preq, 0);
3286c18be159SMatthias Ringwald                 sm_pairing_packet_set_oob_data_flag(setup->sm_m_preq, 0);
3287c18be159SMatthias Ringwald                 sm_pairing_packet_set_auth_req(setup->sm_m_preq, SM_AUTHREQ_CT2);
3288c18be159SMatthias Ringwald                 sm_pairing_packet_set_max_encryption_key_size(setup->sm_m_preq, sm_max_encryption_key_size);
3289c18be159SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_m_preq, key_distribution_flags);
3290c18be159SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags);
3291c18be159SMatthias Ringwald 
3292c18be159SMatthias Ringwald                 // set state and send pairing response
3293c18be159SMatthias Ringwald                 sm_timeout_start(connection);
3294c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_INITIATOR_W4_PAIRING_RESPONSE;
3295c18be159SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t *) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
3296c18be159SMatthias Ringwald                 break;
3297c18be159SMatthias Ringwald 
3298c18be159SMatthias Ringwald             case SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED:
3299c18be159SMatthias Ringwald                 // fill in sm setup (lite version of sm_init_setup)
3300c18be159SMatthias Ringwald                 sm_reset_setup();
3301c18be159SMatthias Ringwald                 setup->sm_peer_addr_type = connection->sm_peer_addr_type;
3302c18be159SMatthias Ringwald                 setup->sm_m_addr_type = connection->sm_peer_addr_type;
3303c18be159SMatthias Ringwald                 setup->sm_s_addr_type = connection->sm_own_addr_type;
3304c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_peer_address, connection->sm_peer_address, 6);
3305c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_m_address, connection->sm_peer_address, 6);
3306c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_s_address, connection->sm_own_address, 6);
3307c18be159SMatthias Ringwald                 setup->sm_use_secure_connections = true;
3308c18be159SMatthias Ringwald                 sm_ctkd_fetch_br_edr_link_key(connection);
3309c18be159SMatthias Ringwald                 (void) memcpy(&setup->sm_m_preq, &connection->sm_m_preq, sizeof(sm_pairing_packet_t));
3310c18be159SMatthias Ringwald 
3311c18be159SMatthias Ringwald                 // Enc Key and IRK if requested
3312c18be159SMatthias Ringwald                 key_distribution_flags = SM_KEYDIST_ID_KEY | SM_KEYDIST_ENC_KEY;
3313c18be159SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
3314c18be159SMatthias Ringwald                 // Plus signing key if supported
3315c18be159SMatthias Ringwald                 key_distribution_flags |= SM_KEYDIST_ID_KEY;
3316c18be159SMatthias Ringwald #endif
3317c18be159SMatthias Ringwald                 // drop flags not requested by initiator
3318c18be159SMatthias Ringwald                 key_distribution_flags &= sm_pairing_packet_get_initiator_key_distribution(connection->sm_m_preq);
3319c18be159SMatthias Ringwald 
3320c18be159SMatthias Ringwald                 // If Secure Connections pairing has been initiated over BR/EDR, the following fields of the SM Pairing Request PDU are reserved for future use:
3321c18be159SMatthias Ringwald                 // - the IO Capability field,
3322c18be159SMatthias Ringwald                 // - the OOB data flag field, and
3323c18be159SMatthias Ringwald                 // - all bits in the Auth Req field except the CT2 bit.
3324c18be159SMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_s_pres, SM_CODE_PAIRING_RESPONSE);
3325c18be159SMatthias Ringwald                 sm_pairing_packet_set_io_capability(setup->sm_s_pres, 0);
3326c18be159SMatthias Ringwald                 sm_pairing_packet_set_oob_data_flag(setup->sm_s_pres, 0);
3327c18be159SMatthias Ringwald                 sm_pairing_packet_set_auth_req(setup->sm_s_pres, SM_AUTHREQ_CT2);
3328c18be159SMatthias Ringwald                 sm_pairing_packet_set_max_encryption_key_size(setup->sm_s_pres, connection->sm_actual_encryption_key_size);
3329c18be159SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_s_pres, key_distribution_flags);
3330c18be159SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_s_pres, key_distribution_flags);
3331c18be159SMatthias Ringwald 
3332c18be159SMatthias Ringwald                 // configure key distribution, LTK is derived locally
3333c18be159SMatthias Ringwald                 key_distribution_flags &= ~SM_KEYDIST_ENC_KEY;
3334c18be159SMatthias Ringwald                 sm_setup_key_distribution(key_distribution_flags, key_distribution_flags);
3335c18be159SMatthias Ringwald 
3336c18be159SMatthias Ringwald                 // set state and send pairing response
3337c18be159SMatthias Ringwald                 sm_timeout_start(connection);
3338c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
3339c18be159SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t *) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
3340c18be159SMatthias Ringwald                 break;
3341c18be159SMatthias Ringwald             case SM_BR_EDR_DISTRIBUTE_KEYS:
334220964aa9SMatthias Ringwald                 // send next key
3343c18be159SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0) {
3344c18be159SMatthias Ringwald                     sm_run_distribute_keys(connection);
334520964aa9SMatthias Ringwald                 }
334620964aa9SMatthias Ringwald 
334720964aa9SMatthias Ringwald                 // more to send?
334820964aa9SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
3349c18be159SMatthias Ringwald                     return;
3350c18be159SMatthias Ringwald                 }
335120964aa9SMatthias Ringwald 
3352c18be159SMatthias Ringwald                 // keys are sent
3353c18be159SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)) {
3354c18be159SMatthias Ringwald                     // responder -> receive master keys if there are any
335561d1a45eSMatthias Ringwald                     if (!sm_key_distribution_all_received()){
3356c18be159SMatthias Ringwald                         connection->sm_engine_state = SM_BR_EDR_RECEIVE_KEYS;
3357c18be159SMatthias Ringwald                         break;
3358c18be159SMatthias Ringwald                     }
3359c18be159SMatthias Ringwald                 }
3360c18be159SMatthias Ringwald                 // otherwise start CTKD right away (responder and no keys to receive / initiator)
3361c18be159SMatthias Ringwald                 sm_ctkd_start_from_br_edr(connection);
3362c18be159SMatthias Ringwald                 continue;
3363c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_ILK_USING_H6:
3364c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
3365c18be159SMatthias Ringwald                 h6_calculate_ilk_from_le_ltk(connection);
3366c18be159SMatthias Ringwald                 break;
3367c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY:
3368c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY;
3369c18be159SMatthias Ringwald                 h6_calculate_br_edr_link_key(connection);
3370c18be159SMatthias Ringwald                 break;
3371c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_ILK_USING_H7:
3372c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
3373c18be159SMatthias Ringwald                 h7_calculate_ilk_from_le_ltk(connection);
3374c18be159SMatthias Ringwald                 break;
3375c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_ILK_USING_H6:
3376c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_ILK;
3377c18be159SMatthias Ringwald                 h6_calculate_ilk_from_br_edr(connection);
3378c18be159SMatthias Ringwald                 break;
3379c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_LE_LTK:
3380c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_LE_LTK;
3381c18be159SMatthias Ringwald                 h6_calculate_le_ltk(connection);
3382c18be159SMatthias Ringwald                 break;
3383c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_ILK_USING_H7:
3384c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_ILK;
3385c18be159SMatthias Ringwald                 h7_calculate_ilk_from_br_edr(connection);
3386c18be159SMatthias Ringwald                 break;
3387c18be159SMatthias Ringwald #endif
3388c18be159SMatthias Ringwald 
33893deb3ec6SMatthias Ringwald             default:
33903deb3ec6SMatthias Ringwald                 break;
33913deb3ec6SMatthias Ringwald         }
33923deb3ec6SMatthias Ringwald 
33933deb3ec6SMatthias Ringwald         // check again if active connection was released
33947149bde5SMatthias Ringwald         if (sm_active_connection_handle != HCI_CON_HANDLE_INVALID) break;
33953deb3ec6SMatthias Ringwald     }
33963deb3ec6SMatthias Ringwald }
33973deb3ec6SMatthias Ringwald 
3398d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
sm_handle_encryption_result_enc_a(void * arg)3399d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_a(void *arg){
3400f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
340104678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
340204678764SMatthias Ringwald 
3403f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3404f3582630SMatthias Ringwald     if (connection == NULL) return;
3405f3582630SMatthias Ringwald 
3406d1a1f6a4SMatthias Ringwald     sm_c1_t3(sm_aes128_ciphertext, setup->sm_m_address, setup->sm_s_address, setup->sm_c1_t3_value);
340704678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3408f3582630SMatthias Ringwald     btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, setup->sm_tk, setup->sm_c1_t3_value, setup->sm_local_confirm, sm_handle_encryption_result_enc_b, (void *)(uintptr_t) connection->sm_handle);
3409d1a1f6a4SMatthias Ringwald }
34103deb3ec6SMatthias Ringwald 
sm_handle_encryption_result_enc_b(void * arg)3411d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_b(void *arg){
3412f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
341304678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
341404678764SMatthias Ringwald 
3415f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3416f3582630SMatthias Ringwald     if (connection == NULL) return;
3417f3582630SMatthias Ringwald 
34188314c363SMatthias Ringwald     log_info_key("c1!", setup->sm_local_confirm);
34193deb3ec6SMatthias Ringwald     connection->sm_engine_state = SM_PH2_C1_SEND_PAIRING_CONFIRM;
342070b44dd4SMatthias Ringwald     sm_trigger_run();
3421d1a1f6a4SMatthias Ringwald }
3422d1a1f6a4SMatthias Ringwald 
3423d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
sm_handle_encryption_result_enc_c(void * arg)3424d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_c(void *arg){
3425f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
342604678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
342704678764SMatthias Ringwald 
3428f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3429f3582630SMatthias Ringwald     if (connection == NULL) return;
3430f3582630SMatthias Ringwald 
3431d1a1f6a4SMatthias Ringwald     sm_c1_t3(sm_aes128_ciphertext, setup->sm_m_address, setup->sm_s_address, setup->sm_c1_t3_value);
343204678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3433f3582630SMatthias Ringwald     btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, setup->sm_tk, setup->sm_c1_t3_value, sm_aes128_ciphertext, sm_handle_encryption_result_enc_d, (void *)(uintptr_t) connection->sm_handle);
3434d1a1f6a4SMatthias Ringwald }
3435d1a1f6a4SMatthias Ringwald 
sm_handle_encryption_result_enc_d(void * arg)3436d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_d(void * arg){
3437f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
343804678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
343904678764SMatthias Ringwald 
3440f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3441f3582630SMatthias Ringwald     if (connection == NULL) return;
3442f3582630SMatthias Ringwald 
3443d1a1f6a4SMatthias Ringwald     log_info_key("c1!", sm_aes128_ciphertext);
3444d1a1f6a4SMatthias Ringwald     if (memcmp(setup->sm_peer_confirm, sm_aes128_ciphertext, 16) != 0){
3445f4935286SMatthias Ringwald         sm_pairing_error(connection, SM_REASON_CONFIRM_VALUE_FAILED);
344670b44dd4SMatthias Ringwald         sm_trigger_run();
34473deb3ec6SMatthias Ringwald         return;
34483deb3ec6SMatthias Ringwald     }
344942134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
34503deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
345170b44dd4SMatthias Ringwald         sm_trigger_run();
34523deb3ec6SMatthias Ringwald     } else {
3453d1a1f6a4SMatthias Ringwald         sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, sm_aes128_plaintext);
3454d1a1f6a4SMatthias Ringwald         sm_aes128_state = SM_AES128_ACTIVE;
3455f3582630SMatthias Ringwald         btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, setup->sm_tk, sm_aes128_plaintext, setup->sm_ltk, sm_handle_encryption_result_enc_stk, (void *)(uintptr_t) connection->sm_handle);
34563deb3ec6SMatthias Ringwald     }
34573deb3ec6SMatthias Ringwald }
3458d1a1f6a4SMatthias Ringwald 
sm_handle_encryption_result_enc_stk(void * arg)3459d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_stk(void *arg){
346004678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
3461f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
346204678764SMatthias Ringwald 
3463f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3464f3582630SMatthias Ringwald     if (connection == NULL) return;
3465f3582630SMatthias Ringwald 
34663deb3ec6SMatthias Ringwald     sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
34678314c363SMatthias Ringwald     log_info_key("stk", setup->sm_ltk);
346842134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
34693deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
34703deb3ec6SMatthias Ringwald     } else {
34713deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
34723deb3ec6SMatthias Ringwald     }
347370b44dd4SMatthias Ringwald     sm_trigger_run();
3474d1a1f6a4SMatthias Ringwald }
3475d1a1f6a4SMatthias Ringwald 
3476d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
sm_handle_encryption_result_enc_ph3_y(void * arg)3477d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_y(void *arg){
3478f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
347904678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
348004678764SMatthias Ringwald 
3481f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3482f3582630SMatthias Ringwald     if (connection == NULL) return;
3483f3582630SMatthias Ringwald 
3484d1a1f6a4SMatthias Ringwald     setup->sm_local_y = big_endian_read_16(sm_aes128_ciphertext, 14);
34853deb3ec6SMatthias Ringwald     log_info_hex16("y", setup->sm_local_y);
34863deb3ec6SMatthias Ringwald     // PH3B3 - calculate EDIV
34873deb3ec6SMatthias Ringwald     setup->sm_local_ediv = setup->sm_local_y ^ setup->sm_local_div;
34883deb3ec6SMatthias Ringwald     log_info_hex16("ediv", setup->sm_local_ediv);
34893deb3ec6SMatthias Ringwald     // PH3B4 - calculate LTK         - enc
34903deb3ec6SMatthias Ringwald     // LTK = d1(ER, DIV, 0))
3491d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 0, sm_aes128_plaintext);
349204678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3493f3582630SMatthias Ringwald     btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_er, sm_aes128_plaintext, setup->sm_ltk, sm_handle_encryption_result_enc_ph3_ltk, (void *)(uintptr_t) connection->sm_handle);
34943deb3ec6SMatthias Ringwald }
3495d1a1f6a4SMatthias Ringwald 
34962a526f21SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
3497d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
sm_handle_encryption_result_enc_ph4_y(void * arg)3498d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_y(void *arg){
349904678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
3500f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
350104678764SMatthias Ringwald 
3502f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3503f3582630SMatthias Ringwald     if (connection == NULL) return;
3504f3582630SMatthias Ringwald 
3505d1a1f6a4SMatthias Ringwald     setup->sm_local_y = big_endian_read_16(sm_aes128_ciphertext, 14);
35063deb3ec6SMatthias Ringwald     log_info_hex16("y", setup->sm_local_y);
35073deb3ec6SMatthias Ringwald 
35083deb3ec6SMatthias Ringwald     // PH3B3 - calculate DIV
35093deb3ec6SMatthias Ringwald     setup->sm_local_div = setup->sm_local_y ^ setup->sm_local_ediv;
35103deb3ec6SMatthias Ringwald     log_info_hex16("ediv", setup->sm_local_ediv);
35113deb3ec6SMatthias Ringwald     // PH3B4 - calculate LTK         - enc
35123deb3ec6SMatthias Ringwald     // LTK = d1(ER, DIV, 0))
3513d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 0, sm_aes128_plaintext);
351404678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3515f3582630SMatthias Ringwald     btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_er, sm_aes128_plaintext, setup->sm_ltk, sm_handle_encryption_result_enc_ph4_ltk, (void *)(uintptr_t) connection->sm_handle);
35163deb3ec6SMatthias Ringwald }
35172a526f21SMatthias Ringwald #endif
3518d1a1f6a4SMatthias Ringwald 
3519d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
sm_handle_encryption_result_enc_ph3_ltk(void * arg)3520d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_ltk(void *arg){
3521f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
352204678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
352304678764SMatthias Ringwald 
3524f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3525f3582630SMatthias Ringwald     if (connection == NULL) return;
3526f3582630SMatthias Ringwald 
35278314c363SMatthias Ringwald     log_info_key("ltk", setup->sm_ltk);
35283deb3ec6SMatthias Ringwald     // calc CSRK next
3529d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 1, sm_aes128_plaintext);
353004678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3531f3582630SMatthias Ringwald     btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_er, sm_aes128_plaintext, setup->sm_local_csrk, sm_handle_encryption_result_enc_csrk, (void *)(uintptr_t) connection->sm_handle);
3532d1a1f6a4SMatthias Ringwald }
3533d1a1f6a4SMatthias Ringwald 
sm_handle_encryption_result_enc_csrk(void * arg)3534d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_csrk(void *arg){
3535f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
353604678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
353704678764SMatthias Ringwald 
3538f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3539f3582630SMatthias Ringwald     if (connection == NULL) return;
3540f3582630SMatthias Ringwald 
3541d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
35428314c363SMatthias Ringwald     log_info_key("csrk", setup->sm_local_csrk);
35431d80f1e6SMatthias Ringwald     if (setup->sm_key_distribution_send_set != 0u){
35443deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
35453deb3ec6SMatthias Ringwald     } else {
35463deb3ec6SMatthias Ringwald         // no keys to send, just continue
354742134bc6SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
354861d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
3549c5a72e35SMatthias Ringwald                 sm_key_distribution_handle_all_received(connection);
3550c5a72e35SMatthias Ringwald                 sm_key_distribution_complete_responder(connection);
3551c5a72e35SMatthias Ringwald             } else {
35523deb3ec6SMatthias Ringwald                 // slave -> receive master keys
35533deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
3554c5a72e35SMatthias Ringwald             }
35553deb3ec6SMatthias Ringwald         } else {
3556af7ef9d1SMatthias Ringwald             sm_key_distribution_complete_initiator(connection);
35573deb3ec6SMatthias Ringwald         }
35582bacf595SMatthias Ringwald     }
355970b44dd4SMatthias Ringwald     sm_trigger_run();
3560d1a1f6a4SMatthias Ringwald }
3561d1a1f6a4SMatthias Ringwald 
356242134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
sm_handle_encryption_result_enc_ph4_ltk(void * arg)3563d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_ltk(void *arg){
3564f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
356504678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
356604678764SMatthias Ringwald 
3567f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3568f3582630SMatthias Ringwald     if (connection == NULL) return;
3569f3582630SMatthias Ringwald 
35703deb3ec6SMatthias Ringwald     sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
35718314c363SMatthias Ringwald     log_info_key("ltk", setup->sm_ltk);
3572d7471931SMatthias Ringwald     connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
357370b44dd4SMatthias Ringwald     sm_trigger_run();
3574d1a1f6a4SMatthias Ringwald }
3575d1a1f6a4SMatthias Ringwald #endif
3576d1a1f6a4SMatthias Ringwald 
sm_handle_encryption_result_address_resolution(void * arg)3577d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_address_resolution(void *arg){
3578d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3579d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
358004678764SMatthias Ringwald 
3581d1a1f6a4SMatthias Ringwald     // compare calulated address against connecting device
3582d1a1f6a4SMatthias Ringwald     uint8_t * hash = &sm_aes128_ciphertext[13];
3583d1a1f6a4SMatthias Ringwald     if (memcmp(&sm_address_resolution_address[3], hash, 3) == 0){
3584d1a1f6a4SMatthias Ringwald         log_info("LE Device Lookup: matched resolvable private address");
3585a66b030fSMatthias Ringwald         sm_address_resolution_handle_event(ADDRESS_RESOLUTION_SUCCEEDED);
358670b44dd4SMatthias Ringwald         sm_trigger_run();
35873deb3ec6SMatthias Ringwald         return;
35883deb3ec6SMatthias Ringwald     }
3589d1a1f6a4SMatthias Ringwald     // no match, try next
3590d1a1f6a4SMatthias Ringwald     sm_address_resolution_test++;
359170b44dd4SMatthias Ringwald     sm_trigger_run();
35923deb3ec6SMatthias Ringwald }
35933deb3ec6SMatthias Ringwald 
sm_handle_encryption_result_dkg_irk(void * arg)3594d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_irk(void *arg){
3595d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3596d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
359704678764SMatthias Ringwald 
3598d1a1f6a4SMatthias Ringwald     log_info_key("irk", sm_persistent_irk);
3599d1a1f6a4SMatthias Ringwald     dkg_state = DKG_CALC_DHK;
360070b44dd4SMatthias Ringwald     sm_trigger_run();
36017df18c15SMatthias Ringwald }
3602d1a1f6a4SMatthias Ringwald 
sm_handle_encryption_result_dkg_dhk(void * arg)3603d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_dhk(void *arg){
3604d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3605d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
360604678764SMatthias Ringwald 
3607d1a1f6a4SMatthias Ringwald     log_info_key("dhk", sm_persistent_dhk);
3608d1a1f6a4SMatthias Ringwald     dkg_state = DKG_READY;
360970b44dd4SMatthias Ringwald     sm_trigger_run();
36107df18c15SMatthias Ringwald }
3611d1a1f6a4SMatthias Ringwald 
sm_handle_encryption_result_rau(void * arg)3612d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_rau(void *arg){
3613d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3614d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
361504678764SMatthias Ringwald 
36166535961aSMatthias Ringwald     (void)memcpy(&sm_random_address[3], &sm_aes128_ciphertext[13], 3);
3617e91ddb40SMatthias Ringwald     rau_state = RAU_IDLE;
3618e91ddb40SMatthias Ringwald     hci_le_random_address_set(sm_random_address);
3619e91ddb40SMatthias Ringwald 
362070b44dd4SMatthias Ringwald     sm_trigger_run();
362151fa0b28SMatthias Ringwald }
36227df18c15SMatthias Ringwald 
sm_handle_random_result_rau(void * arg)3623d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_rau(void * arg){
3624d1a1f6a4SMatthias Ringwald     UNUSED(arg);
36253deb3ec6SMatthias Ringwald     // non-resolvable vs. resolvable
36263deb3ec6SMatthias Ringwald     switch (gap_random_adress_type){
36273deb3ec6SMatthias Ringwald         case GAP_RANDOM_ADDRESS_RESOLVABLE:
36283deb3ec6SMatthias Ringwald             // resolvable: use random as prand and calc address hash
36293deb3ec6SMatthias Ringwald             // "The two most significant bits of prand shall be equal to ‘0’ and ‘1"
36304ea43905SMatthias Ringwald             sm_random_address[0u] &= 0x3fu;
36314ea43905SMatthias Ringwald             sm_random_address[0u] |= 0x40u;
36323deb3ec6SMatthias Ringwald             rau_state = RAU_GET_ENC;
36333deb3ec6SMatthias Ringwald             break;
36343deb3ec6SMatthias Ringwald         case GAP_RANDOM_ADDRESS_NON_RESOLVABLE:
36353deb3ec6SMatthias Ringwald         default:
36363deb3ec6SMatthias Ringwald             // "The two most significant bits of the address shall be equal to ‘0’""
36374ea43905SMatthias Ringwald             sm_random_address[0u] &= 0x3fu;
36382954e6c6SMatthias Ringwald             rau_state = RAU_IDLE;
3639e91ddb40SMatthias Ringwald             hci_le_random_address_set(sm_random_address);
36403deb3ec6SMatthias Ringwald             break;
36413deb3ec6SMatthias Ringwald     }
364270b44dd4SMatthias Ringwald     sm_trigger_run();
36433deb3ec6SMatthias Ringwald }
36443deb3ec6SMatthias Ringwald 
3645c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_handle_random_result_sc_next_send_pairing_random(void * arg)36466ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_send_pairing_random(void * arg){
3647f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3648f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3649f3582630SMatthias Ringwald     if (connection == NULL) return;
3650c59d0c92SMatthias Ringwald 
365165a9a04eSMatthias Ringwald     connection->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
365270b44dd4SMatthias Ringwald     sm_trigger_run();
365365a9a04eSMatthias Ringwald }
3654d1a1f6a4SMatthias Ringwald 
sm_handle_random_result_sc_next_w2_cmac_for_confirmation(void * arg)36556ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_w2_cmac_for_confirmation(void * arg){
36566ca80073SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
36576ca80073SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
36586ca80073SMatthias Ringwald     if (connection == NULL) return;
36596ca80073SMatthias Ringwald 
3660b35a3de2SMatthias Ringwald     connection->sm_engine_state = SM_SC_W2_CMAC_FOR_CONFIRMATION;
366170b44dd4SMatthias Ringwald     sm_trigger_run();
3662d1a1f6a4SMatthias Ringwald }
3663f1c1783eSMatthias Ringwald #endif
3664f1c1783eSMatthias Ringwald 
sm_handle_random_result_ph2_random(void * arg)3665d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_random(void * arg){
3666f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3667f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3668f3582630SMatthias Ringwald     if (connection == NULL) return;
3669f3582630SMatthias Ringwald 
3670d1a1f6a4SMatthias Ringwald     connection->sm_engine_state = SM_PH2_C1_GET_ENC_A;
367170b44dd4SMatthias Ringwald     sm_trigger_run();
3672d1a1f6a4SMatthias Ringwald }
3673d1a1f6a4SMatthias Ringwald 
sm_handle_random_result_ph2_tk(void * arg)3674d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_tk(void * arg){
3675f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3676f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3677f3582630SMatthias Ringwald     if (connection == NULL) return;
3678f3582630SMatthias Ringwald 
3679caf15bf3SMatthias Ringwald     sm_reset_tk();
3680caf15bf3SMatthias Ringwald     uint32_t tk;
36815ce1359eSMatthias Ringwald     if (sm_fixed_passkey_in_display_role == 0xffffffffU){
36823deb3ec6SMatthias Ringwald         // map random to 0-999999 without speding much cycles on a modulus operation
3683d1a1f6a4SMatthias Ringwald         tk = little_endian_read_32(sm_random_data,0);
36843deb3ec6SMatthias Ringwald         tk = tk & 0xfffff;  // 1048575
36854ea43905SMatthias Ringwald         if (tk >= 999999u){
36864ea43905SMatthias Ringwald             tk = tk - 999999u;
36873deb3ec6SMatthias Ringwald         }
3688caf15bf3SMatthias Ringwald     } else {
3689caf15bf3SMatthias Ringwald         // override with pre-defined passkey
36904b8c611fSMatthias Ringwald         tk = sm_fixed_passkey_in_display_role;
3691caf15bf3SMatthias Ringwald     }
3692f8fbdce0SMatthias Ringwald     big_endian_store_32(setup->sm_tk, 12, tk);
369342134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
36943deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
36953deb3ec6SMatthias Ringwald     } else {
3696b41539d5SMatthias Ringwald         if (setup->sm_use_secure_connections){
3697b41539d5SMatthias Ringwald             connection->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
3698b41539d5SMatthias Ringwald         } else {
36993deb3ec6SMatthias Ringwald             connection->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
37003deb3ec6SMatthias Ringwald             sm_trigger_user_response(connection);
37013deb3ec6SMatthias Ringwald             // response_idle == nothing <--> sm_trigger_user_response() did not require response
37023deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
3703f3582630SMatthias Ringwald                 btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_random, 16, &sm_handle_random_result_ph2_random, (void *)(uintptr_t) connection->sm_handle);
37043deb3ec6SMatthias Ringwald             }
37053deb3ec6SMatthias Ringwald         }
3706b41539d5SMatthias Ringwald     }
370770b44dd4SMatthias Ringwald     sm_trigger_run();
37083deb3ec6SMatthias Ringwald }
3709d1a1f6a4SMatthias Ringwald 
sm_handle_random_result_ph3_div(void * arg)3710d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph3_div(void * arg){
3711f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3712f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3713f3582630SMatthias Ringwald     if (connection == NULL) return;
3714f3582630SMatthias Ringwald 
3715d1a1f6a4SMatthias Ringwald     // use 16 bit from random value as div
3716d1a1f6a4SMatthias Ringwald     setup->sm_local_div = big_endian_read_16(sm_random_data, 0);
3717d1a1f6a4SMatthias Ringwald     log_info_hex16("div", setup->sm_local_div);
3718d1a1f6a4SMatthias Ringwald     connection->sm_engine_state = SM_PH3_Y_GET_ENC;
371970b44dd4SMatthias Ringwald     sm_trigger_run();
3720d1a1f6a4SMatthias Ringwald }
3721d1a1f6a4SMatthias Ringwald 
sm_handle_random_result_ph3_random(void * arg)3722d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph3_random(void * arg){
3723f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3724f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3725f3582630SMatthias Ringwald     if (connection == NULL) return;
3726f3582630SMatthias Ringwald 
3727d1a1f6a4SMatthias Ringwald     reverse_64(sm_random_data, setup->sm_local_rand);
37283deb3ec6SMatthias Ringwald     // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
37294ea43905SMatthias Ringwald     setup->sm_local_rand[7u] = (setup->sm_local_rand[7u] & 0xf0u) + (connection->sm_actual_encryption_key_size - 1u);
37303deb3ec6SMatthias Ringwald     // no db for authenticated flag hack: store flag in bit 4 of LSB
37314ea43905SMatthias Ringwald     setup->sm_local_rand[7u] = (setup->sm_local_rand[7u] & 0xefu) + (connection->sm_connection_authenticated << 4u);
37328b3ffec5SMatthias Ringwald     btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 2, &sm_handle_random_result_ph3_div, (void *)(uintptr_t) connection->sm_handle);
37333deb3ec6SMatthias Ringwald }
sm_validate_er_ir(void)3734899e6e02SMatthias Ringwald static void sm_validate_er_ir(void){
3735899e6e02SMatthias Ringwald     // warn about default ER/IR
37361979f09cSMatthias Ringwald     bool warning = false;
3737899e6e02SMatthias Ringwald     if (sm_ir_is_default()){
37381979f09cSMatthias Ringwald         warning = true;
3739899e6e02SMatthias Ringwald         log_error("Persistent IR not set with sm_set_ir. Use of private addresses will cause pairing issues");
3740899e6e02SMatthias Ringwald     }
3741899e6e02SMatthias Ringwald     if (sm_er_is_default()){
37421979f09cSMatthias Ringwald         warning = true;
3743899e6e02SMatthias Ringwald         log_error("Persistent ER not set with sm_set_er. Legacy Pairing LTK is not secure");
3744899e6e02SMatthias Ringwald     }
374521045273SMatthias Ringwald     if (warning) {
3746899e6e02SMatthias Ringwald         log_error("Please configure btstack_tlv to let BTstack setup ER and IR keys");
3747899e6e02SMatthias Ringwald     }
374821045273SMatthias Ringwald }
3749899e6e02SMatthias Ringwald 
sm_handle_random_result_ir(void * arg)3750899e6e02SMatthias Ringwald static void sm_handle_random_result_ir(void *arg){
37511979f09cSMatthias Ringwald     sm_persistent_keys_random_active = false;
37529305033eSMatthias Ringwald     if (arg != NULL){
3753899e6e02SMatthias Ringwald         // key generated, store in tlv
37544ea43905SMatthias Ringwald         int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16u);
3755899e6e02SMatthias Ringwald         log_info("Generated IR key. Store in TLV status: %d", status);
3756e0d13a19SMilanka Ringwald         UNUSED(status);
3757899e6e02SMatthias Ringwald     }
3758899e6e02SMatthias Ringwald     log_info_key("IR", sm_persistent_ir);
37598d9b6072SMatthias Ringwald     dkg_state = DKG_CALC_IRK;
3760841468bbSMatthias Ringwald 
3761841468bbSMatthias Ringwald     if (test_use_fixed_local_irk){
3762841468bbSMatthias Ringwald         log_info_key("IRK", sm_persistent_irk);
3763841468bbSMatthias Ringwald         dkg_state = DKG_CALC_DHK;
3764841468bbSMatthias Ringwald     }
3765841468bbSMatthias Ringwald 
376670b44dd4SMatthias Ringwald     sm_trigger_run();
3767899e6e02SMatthias Ringwald }
3768899e6e02SMatthias Ringwald 
sm_handle_random_result_er(void * arg)3769899e6e02SMatthias Ringwald static void sm_handle_random_result_er(void *arg){
37701979f09cSMatthias Ringwald     sm_persistent_keys_random_active = false;
37716643d79bSMatthias Ringwald     if (arg != NULL){
3772899e6e02SMatthias Ringwald         // key generated, store in tlv
37734ea43905SMatthias Ringwald         int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16u);
3774899e6e02SMatthias Ringwald         log_info("Generated ER key. Store in TLV status: %d", status);
3775e0d13a19SMilanka Ringwald         UNUSED(status);
3776899e6e02SMatthias Ringwald     }
3777899e6e02SMatthias Ringwald     log_info_key("ER", sm_persistent_er);
3778899e6e02SMatthias Ringwald 
3779899e6e02SMatthias Ringwald     // try load ir
37804ea43905SMatthias Ringwald     int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16u);
3781899e6e02SMatthias Ringwald     if (key_size == 16){
3782899e6e02SMatthias Ringwald         // ok, let's continue
3783899e6e02SMatthias Ringwald         log_info("IR from TLV");
3784899e6e02SMatthias Ringwald         sm_handle_random_result_ir( NULL );
3785899e6e02SMatthias Ringwald     } else {
3786899e6e02SMatthias Ringwald         // invalid, generate new random one
37871979f09cSMatthias Ringwald         sm_persistent_keys_random_active = true;
3788899e6e02SMatthias Ringwald         btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_ir, 16, &sm_handle_random_result_ir, &sm_persistent_ir);
3789899e6e02SMatthias Ringwald     }
3790899e6e02SMatthias Ringwald }
37913deb3ec6SMatthias Ringwald 
sm_connection_init(sm_connection_t * sm_conn,hci_con_handle_t con_handle,uint8_t role,uint8_t peer_addr_type,bd_addr_t peer_address)379250053c13SMatthias Ringwald static void sm_connection_init(sm_connection_t * sm_conn, hci_con_handle_t con_handle, uint8_t role, uint8_t peer_addr_type, bd_addr_t peer_address){
3793f664b5e8SMatthias Ringwald 
3794f664b5e8SMatthias Ringwald     // connection info
3795f664b5e8SMatthias Ringwald     sm_conn->sm_handle = con_handle;
3796f664b5e8SMatthias Ringwald     sm_conn->sm_role = role;
379750053c13SMatthias Ringwald     sm_conn->sm_peer_addr_type = peer_addr_type;
379850053c13SMatthias Ringwald     memcpy(sm_conn->sm_peer_address, peer_address, 6);
3799f664b5e8SMatthias Ringwald 
3800f664b5e8SMatthias Ringwald     // security properties
3801f664b5e8SMatthias Ringwald     sm_conn->sm_connection_encrypted = 0;
3802f664b5e8SMatthias Ringwald     sm_conn->sm_connection_authenticated = 0;
3803f664b5e8SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_UNKNOWN;
3804f664b5e8SMatthias Ringwald     sm_conn->sm_le_db_index = -1;
3805f664b5e8SMatthias Ringwald     sm_conn->sm_reencryption_active = false;
3806f664b5e8SMatthias Ringwald 
3807f664b5e8SMatthias Ringwald     // prepare CSRK lookup (does not involve setup)
3808f664b5e8SMatthias Ringwald     sm_conn->sm_irk_lookup_state = IRK_LOOKUP_W4_READY;
3809f664b5e8SMatthias Ringwald 
3810f664b5e8SMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_IDLE;
3811f664b5e8SMatthias Ringwald }
3812f664b5e8SMatthias Ringwald 
3813599e89daSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
sm_event_handle_classic_encryption_event(sm_connection_t * sm_conn,hci_con_handle_t con_handle)3814599e89daSMatthias Ringwald static void sm_event_handle_classic_encryption_event(sm_connection_t * sm_conn, hci_con_handle_t con_handle){
3815599e89daSMatthias Ringwald     // CTKD requires BR/EDR Secure Connection
3816599e89daSMatthias Ringwald     if (sm_conn->sm_connection_encrypted != 2) return;
3817599e89daSMatthias Ringwald     // prepare for pairing request
3818599e89daSMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
3819d44cdc4aSMatthias Ringwald         log_info("CTKD: SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST");
3820599e89daSMatthias Ringwald         sm_conn->sm_engine_state = SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST;
3821599e89daSMatthias Ringwald     } else if (sm_conn->sm_pairing_requested){
3822599e89daSMatthias Ringwald         // check if remote supports fixed channels
3823599e89daSMatthias Ringwald         bool defer = true;
3824599e89daSMatthias Ringwald         const hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
3825599e89daSMatthias Ringwald         if (hci_connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_DONE){
3826599e89daSMatthias Ringwald             // check if remote supports SMP over BR/EDR
3827599e89daSMatthias Ringwald             if ((hci_connection->l2cap_state.fixed_channels_supported & (1 << L2CAP_CID_BR_EDR_SECURITY_MANAGER)) != 0){
3828599e89daSMatthias Ringwald                 log_info("CTKD: SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST");
3829599e89daSMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST;
3830599e89daSMatthias Ringwald             } else {
3831599e89daSMatthias Ringwald                 defer = false;
3832599e89daSMatthias Ringwald             }
3833599e89daSMatthias Ringwald         } else {
3834599e89daSMatthias Ringwald             // wait for fixed channel info
3835599e89daSMatthias Ringwald             log_info("CTKD: SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK");
3836599e89daSMatthias Ringwald             sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK;
3837599e89daSMatthias Ringwald         }
3838599e89daSMatthias Ringwald         if (defer){
3839599e89daSMatthias Ringwald             hci_dedicated_bonding_defer_disconnect(con_handle, true);
3840599e89daSMatthias Ringwald         }
3841599e89daSMatthias Ringwald     }
3842599e89daSMatthias Ringwald }
3843599e89daSMatthias Ringwald #endif
3844599e89daSMatthias Ringwald 
sm_event_packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)3845d9a7306aSMatthias Ringwald static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
38463deb3ec6SMatthias Ringwald 
3847cbdfe9f7SMatthias Ringwald     UNUSED(channel);    // ok: there is no channel
3848cbdfe9f7SMatthias Ringwald     UNUSED(size);       // ok: fixed format HCI events
38499ec2630cSMatthias Ringwald 
38503deb3ec6SMatthias Ringwald     sm_connection_t * sm_conn;
3851711e6c80SMatthias Ringwald     hci_con_handle_t  con_handle;
3852fbe050beSMatthias Ringwald     uint8_t           status;
3853f664b5e8SMatthias Ringwald     bd_addr_t         addr;
3854d9f3ead5SMatthias Ringwald     bd_addr_type_t    addr_type;
3855f664b5e8SMatthias Ringwald 
38563deb3ec6SMatthias Ringwald     switch (packet_type) {
38573deb3ec6SMatthias Ringwald 
38583deb3ec6SMatthias Ringwald 		case HCI_EVENT_PACKET:
38590e2df43fSMatthias Ringwald 			switch (hci_event_packet_get_type(packet)) {
38603deb3ec6SMatthias Ringwald 
38613deb3ec6SMatthias Ringwald                 case BTSTACK_EVENT_STATE:
3862745015f6SMatthias Ringwald                     switch (btstack_event_state_get_state(packet)){
3863745015f6SMatthias Ringwald                         case HCI_STATE_WORKING:
38643deb3ec6SMatthias Ringwald                             log_info("HCI Working!");
3865899e6e02SMatthias Ringwald                             // setup IR/ER with TLV
3866899e6e02SMatthias Ringwald                             btstack_tlv_get_instance(&sm_tlv_impl, &sm_tlv_context);
38679305033eSMatthias Ringwald                             if (sm_tlv_impl != NULL){
38684ea43905SMatthias Ringwald                                 int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16u);
3869899e6e02SMatthias Ringwald                                 if (key_size == 16){
3870899e6e02SMatthias Ringwald                                     // ok, let's continue
3871899e6e02SMatthias Ringwald                                     log_info("ER from TLV");
3872899e6e02SMatthias Ringwald                                     sm_handle_random_result_er( NULL );
3873899e6e02SMatthias Ringwald                                 } else {
3874899e6e02SMatthias Ringwald                                     // invalid, generate random one
38751979f09cSMatthias Ringwald                                     sm_persistent_keys_random_active = true;
3876899e6e02SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_er, 16, &sm_handle_random_result_er, &sm_persistent_er);
3877899e6e02SMatthias Ringwald                                 }
3878899e6e02SMatthias Ringwald                             } else {
3879899e6e02SMatthias Ringwald                                 sm_validate_er_ir();
38808d9b6072SMatthias Ringwald                                 dkg_state = DKG_CALC_IRK;
3881841468bbSMatthias Ringwald 
3882841468bbSMatthias Ringwald                                 if (test_use_fixed_local_irk){
3883841468bbSMatthias Ringwald                                     log_info_key("IRK", sm_persistent_irk);
3884841468bbSMatthias Ringwald                                     dkg_state = DKG_CALC_DHK;
3885841468bbSMatthias Ringwald                                 }
3886899e6e02SMatthias Ringwald                             }
38871bf086daSMatthias Ringwald 
388815211b85SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
388915211b85SMatthias Ringwald                             // trigger ECC key generation
389015211b85SMatthias Ringwald                             if (ec_key_generation_state == EC_KEY_GENERATION_IDLE){
389115211b85SMatthias Ringwald                                 sm_ec_generate_new_key();
389215211b85SMatthias Ringwald                             }
389315211b85SMatthias Ringwald #endif
389415211b85SMatthias Ringwald 
38951bf086daSMatthias Ringwald                             // restart random address updates after power cycle
38964a688bd1SMatthias Ringwald                             if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_STATIC){
38974a688bd1SMatthias Ringwald                                 gap_random_address_set(sm_random_address);
38984a688bd1SMatthias Ringwald                             } else {
38991bf086daSMatthias Ringwald                                 gap_random_address_set_mode(gap_random_adress_type);
39004a688bd1SMatthias Ringwald                             }
3901745015f6SMatthias Ringwald                             break;
3902745015f6SMatthias Ringwald 
3903745015f6SMatthias Ringwald                         case HCI_STATE_OFF:
39047f775357SMatthias Ringwald                         case HCI_STATE_HALTING:
3905cbdd51cfSMatthias Ringwald                             log_info("SM: reset state");
3906745015f6SMatthias Ringwald                             // stop random address update
3907745015f6SMatthias Ringwald                             gap_random_address_update_stop();
3908cbdd51cfSMatthias Ringwald                             // reset state
3909cbdd51cfSMatthias Ringwald                             sm_state_reset();
3910745015f6SMatthias Ringwald                             break;
3911745015f6SMatthias Ringwald 
3912745015f6SMatthias Ringwald                         default:
3913745015f6SMatthias Ringwald                             break;
39143deb3ec6SMatthias Ringwald                     }
39153deb3ec6SMatthias Ringwald 					break;
3916c18be159SMatthias Ringwald 
39172d095694SMatthias Ringwald #ifdef ENABLE_CLASSIC
39182d095694SMatthias Ringwald 			    case HCI_EVENT_CONNECTION_COMPLETE:
39192d095694SMatthias Ringwald 			        // ignore if connection failed
39202d095694SMatthias Ringwald 			        if (hci_event_connection_complete_get_status(packet)) return;
39213deb3ec6SMatthias Ringwald 
39222d095694SMatthias Ringwald 			        con_handle = hci_event_connection_complete_get_connection_handle(packet);
39232d095694SMatthias Ringwald 			        sm_conn = sm_get_connection_for_handle(con_handle);
39242d095694SMatthias Ringwald 			        if (!sm_conn) break;
39252d095694SMatthias Ringwald 
39262d095694SMatthias Ringwald                     hci_event_connection_complete_get_bd_addr(packet, addr);
39272d095694SMatthias Ringwald 			        sm_connection_init(sm_conn,
39282d095694SMatthias Ringwald                                        con_handle,
39292d095694SMatthias Ringwald                                        (uint8_t) gap_get_role(con_handle),
3930f72f7944SMatthias Ringwald                                        BD_ADDR_TYPE_LE_PUBLIC,
39312d095694SMatthias Ringwald                                        addr);
39322d095694SMatthias Ringwald 			        // classic connection corresponds to public le address
39332d095694SMatthias Ringwald 			        sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_PUBLIC;
39342d095694SMatthias Ringwald                     gap_local_bd_addr(sm_conn->sm_own_address);
39352d095694SMatthias Ringwald                     sm_conn->sm_cid = L2CAP_CID_BR_EDR_SECURITY_MANAGER;
3936c18be159SMatthias Ringwald                     sm_conn->sm_engine_state = SM_BR_EDR_W4_ENCRYPTION_COMPLETE;
39372d095694SMatthias Ringwald 			        break;
3938d44cdc4aSMatthias Ringwald 
3939401d2b30SMatthias Ringwald #endif
3940401d2b30SMatthias Ringwald 
3941401d2b30SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3942d44cdc4aSMatthias Ringwald                 case HCI_EVENT_ROLE_CHANGE:
3943d44cdc4aSMatthias Ringwald                     hci_event_role_change_get_bd_addr(packet, addr);
3944d44cdc4aSMatthias Ringwald                     sm_conn = sm_get_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL);
3945d44cdc4aSMatthias Ringwald                     if (sm_conn == NULL) break;
3946d44cdc4aSMatthias Ringwald                     sm_conn->sm_role = hci_event_role_change_get_role(packet);
3947d44cdc4aSMatthias Ringwald                     break;
3948c18be159SMatthias Ringwald 
3949c18be159SMatthias Ringwald 			    case HCI_EVENT_SIMPLE_PAIRING_COMPLETE:
3950c18be159SMatthias Ringwald 			        if (hci_event_simple_pairing_complete_get_status(packet) != ERROR_CODE_SUCCESS) break;
3951c18be159SMatthias Ringwald                     hci_event_simple_pairing_complete_get_bd_addr(packet, addr);
3952c18be159SMatthias Ringwald                     sm_conn = sm_get_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL);
3953c18be159SMatthias Ringwald                     if (sm_conn == NULL) break;
39545f3874afSMatthias Ringwald                     sm_conn->sm_pairing_requested = true;
3955c18be159SMatthias Ringwald 			        break;
3956c18be159SMatthias Ringwald #endif
3957c18be159SMatthias Ringwald 
39589d1eff91SMatthias Ringwald 			    case HCI_EVENT_META_GAP:
39599d1eff91SMatthias Ringwald 			        switch (hci_event_gap_meta_get_subevent_code(packet)) {
39609d1eff91SMatthias Ringwald 			            case GAP_SUBEVENT_LE_CONNECTION_COMPLETE:
3961f664b5e8SMatthias Ringwald 			                // ignore if connection failed
39629d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_status(packet) != ERROR_CODE_SUCCESS) break;
39633deb3ec6SMatthias Ringwald 
39649d1eff91SMatthias Ringwald 			                con_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
3965711e6c80SMatthias Ringwald 			                sm_conn = sm_get_connection_for_handle(con_handle);
39663deb3ec6SMatthias Ringwald 			                if (!sm_conn) break;
39673deb3ec6SMatthias Ringwald 
3968d9f3ead5SMatthias Ringwald                             // Get current peer address
3969d9f3ead5SMatthias Ringwald                             addr_type = gap_subevent_le_connection_complete_get_peer_address_type(packet);
3970d9f3ead5SMatthias Ringwald                             if (hci_is_le_identity_address_type(addr_type)){
3971d9f3ead5SMatthias Ringwald                                 addr_type = BD_ADDR_TYPE_LE_RANDOM;
3972d9f3ead5SMatthias Ringwald                                 gap_subevent_le_connection_complete_get_peer_resolvable_private_address(packet, addr);
3973d9f3ead5SMatthias Ringwald                             } else {
39749d1eff91SMatthias Ringwald                                 gap_subevent_le_connection_complete_get_peer_address(packet, addr);
3975d9f3ead5SMatthias Ringwald                             }
3976f664b5e8SMatthias Ringwald 			                sm_connection_init(sm_conn,
3977f664b5e8SMatthias Ringwald                                                con_handle,
39789d1eff91SMatthias Ringwald                                                gap_subevent_le_connection_complete_get_role(packet),
3979d9f3ead5SMatthias Ringwald                                                addr_type,
3980f664b5e8SMatthias Ringwald                                                addr);
3981687a03c8SMatthias Ringwald 			                sm_conn->sm_cid = L2CAP_CID_SECURITY_MANAGER_PROTOCOL;
3982f664b5e8SMatthias Ringwald 
3983f664b5e8SMatthias Ringwald 			                // track our addr used for this connection and set state
3984b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
39859d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_role(packet) != 0){
3986ba9fc867SMatthias Ringwald 			                    // responder - use own address from advertisements
398767bf59ffSMatthias Ringwald #ifdef ENABLE_LE_EXTENDED_ADVERTISING
398867bf59ffSMatthias Ringwald                                 if (hci_le_extended_advertising_supported()){
398967bf59ffSMatthias Ringwald                                     // cache local resolvable address
399067bf59ffSMatthias Ringwald                                     // note: will be overwritten if random or private address was used in adv set by HCI_SUBEVENT_LE_ADVERTISING_SET_TERMINATED
399167bf59ffSMatthias Ringwald                                     sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_RANDOM;
399267bf59ffSMatthias Ringwald                                     gap_subevent_le_connection_complete_get_local_resolvable_private_address(packet,sm_conn->sm_own_address);
399367bf59ffSMatthias Ringwald                                 } else
399467bf59ffSMatthias Ringwald #endif
399567bf59ffSMatthias Ringwald                                 {
3996ba9fc867SMatthias Ringwald                                     gap_le_get_own_advertisements_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address);
399767bf59ffSMatthias Ringwald                                 }
3998f664b5e8SMatthias Ringwald 			                    sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
3999b892db1cSMatthias Ringwald 			                }
4000b892db1cSMatthias Ringwald #endif
4001b892db1cSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
40029d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_role(packet) == 0){
4003ba9fc867SMatthias Ringwald 			                    // initiator - use own address from create connection
4004ba9fc867SMatthias Ringwald 			                    gap_le_get_own_connection_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address);
40053deb3ec6SMatthias Ringwald 			                    sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
40063deb3ec6SMatthias Ringwald 			                }
4007b892db1cSMatthias Ringwald #endif
40083deb3ec6SMatthias Ringwald 			                break;
40099d1eff91SMatthias Ringwald 			            default:
40109d1eff91SMatthias Ringwald 			                break;
40119d1eff91SMatthias Ringwald 			        }
40129d1eff91SMatthias Ringwald 			        break;
40139d1eff91SMatthias Ringwald                 case HCI_EVENT_LE_META:
40149d1eff91SMatthias Ringwald                     switch (hci_event_le_meta_get_subevent_code(packet)) {
401567bf59ffSMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
401667bf59ffSMatthias Ringwald #ifdef ENABLE_LE_EXTENDED_ADVERTISING
401767bf59ffSMatthias Ringwald                         case HCI_SUBEVENT_LE_ADVERTISING_SET_TERMINATED:
401867bf59ffSMatthias Ringwald                             if (hci_subevent_le_advertising_set_terminated_get_status(packet) == ERROR_CODE_SUCCESS){
401967bf59ffSMatthias Ringwald                                 uint8_t advertising_handle = hci_subevent_le_advertising_set_terminated_get_advertising_handle(packet);
402067bf59ffSMatthias Ringwald                                 con_handle = hci_subevent_le_advertising_set_terminated_get_connection_handle(packet);
402167bf59ffSMatthias Ringwald                                 sm_conn = sm_get_connection_for_handle(con_handle);
4022ebd6ff34SMatthias Ringwald                                 if (!sm_conn) break;
4023ebd6ff34SMatthias Ringwald 
402467bf59ffSMatthias Ringwald                                 gap_le_get_own_advertising_set_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address, advertising_handle);
402567bf59ffSMatthias Ringwald                                 log_info("Adv set %u terminated -> use addr type %u, addr %s for con handle 0x%04x", advertising_handle, sm_conn->sm_own_addr_type,
402667bf59ffSMatthias Ringwald                                          bd_addr_to_str(sm_conn->sm_own_address), con_handle);
402767bf59ffSMatthias Ringwald                             }
402867bf59ffSMatthias Ringwald                             break;
402967bf59ffSMatthias Ringwald #endif
403067bf59ffSMatthias Ringwald #endif
40313deb3ec6SMatthias Ringwald                         case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST:
40329d1eff91SMatthias Ringwald                             con_handle = hci_subevent_le_long_term_key_request_get_connection_handle(packet);
4033711e6c80SMatthias Ringwald                             sm_conn = sm_get_connection_for_handle(con_handle);
40343deb3ec6SMatthias Ringwald                             if (!sm_conn) break;
40353deb3ec6SMatthias Ringwald 
40363deb3ec6SMatthias Ringwald                             log_info("LTK Request: state %u", sm_conn->sm_engine_state);
40373deb3ec6SMatthias Ringwald                             if (sm_conn->sm_engine_state == SM_RESPONDER_PH2_W4_LTK_REQUEST){
40383deb3ec6SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_PH2_CALC_STK;
40393deb3ec6SMatthias Ringwald                                 break;
40403deb3ec6SMatthias Ringwald                             }
4041c6b7cbd9SMatthias Ringwald                             if (sm_conn->sm_engine_state == SM_SC_W4_LTK_REQUEST_SC){
4042778b6aadSMatthias Ringwald                                 // PH2 SEND LTK as we need to exchange keys in PH3
4043778b6aadSMatthias Ringwald                                 sm_conn->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
4044e53be891SMatthias Ringwald                                 break;
4045e53be891SMatthias Ringwald                             }
40463deb3ec6SMatthias Ringwald 
40473deb3ec6SMatthias Ringwald                             // store rand and ediv
40489c80e4ccSMatthias Ringwald                             reverse_64(&packet[5], sm_conn->sm_local_rand);
40499d1eff91SMatthias Ringwald                             sm_conn->sm_local_ediv = hci_subevent_le_long_term_key_request_get_encryption_diversifier(packet);
4050549ad5d2SMatthias Ringwald 
4051549ad5d2SMatthias Ringwald                             // For Legacy Pairing (<=> EDIV != 0 || RAND != NULL), we need to recalculated our LTK as a
4052549ad5d2SMatthias Ringwald                             // potentially stored LTK is from the master
40534ea43905SMatthias Ringwald                             if ((sm_conn->sm_local_ediv != 0u) || !sm_is_null_random(sm_conn->sm_local_rand)){
40546c39055aSMatthias Ringwald                                 if (sm_reconstruct_ltk_without_le_device_db_entry){
405506cd539fSMatthias Ringwald                                     sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
4056549ad5d2SMatthias Ringwald                                     break;
4057549ad5d2SMatthias Ringwald                                 }
40586c39055aSMatthias Ringwald                                 // additionally check if remote is in LE Device DB if requested
40596c39055aSMatthias Ringwald                                 switch(sm_conn->sm_irk_lookup_state){
40606c39055aSMatthias Ringwald                                     case IRK_LOOKUP_FAILED:
40616c39055aSMatthias Ringwald                                         log_info("LTK Request: device not in device db");
40626c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
40636c39055aSMatthias Ringwald                                         break;
40646c39055aSMatthias Ringwald                                     case IRK_LOOKUP_SUCCEEDED:
40656c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
40666c39055aSMatthias Ringwald                                         break;
40676c39055aSMatthias Ringwald                                     default:
40686c39055aSMatthias Ringwald                                         // wait for irk look doen
40696c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK;
40706c39055aSMatthias Ringwald                                         break;
40716c39055aSMatthias Ringwald                                 }
40726c39055aSMatthias Ringwald                                 break;
40736c39055aSMatthias Ringwald                             }
4074549ad5d2SMatthias Ringwald 
4075549ad5d2SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
407606cd539fSMatthias Ringwald                             sm_conn->sm_engine_state = SM_SC_RECEIVED_LTK_REQUEST;
4077549ad5d2SMatthias Ringwald #else
4078549ad5d2SMatthias Ringwald                             log_info("LTK Request: ediv & random are empty, but LE Secure Connections not supported");
4079549ad5d2SMatthias Ringwald                             sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
4080549ad5d2SMatthias Ringwald #endif
40813deb3ec6SMatthias Ringwald                             break;
4082804d3e67SMatthias Ringwald 
40833deb3ec6SMatthias Ringwald                         default:
40843deb3ec6SMatthias Ringwald                             break;
40853deb3ec6SMatthias Ringwald                     }
40863deb3ec6SMatthias Ringwald                     break;
40873deb3ec6SMatthias Ringwald 
40883deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE:
40898601e696SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE_V2:
40903b7fd749SMatthias Ringwald                 	con_handle = hci_event_encryption_change_get_connection_handle(packet);
4091711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
40923deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
40933deb3ec6SMatthias Ringwald 
40943b7fd749SMatthias Ringwald                     sm_conn->sm_connection_encrypted = hci_event_encryption_change_get_encryption_enabled(packet);
40953deb3ec6SMatthias Ringwald                     log_info("Encryption state change: %u, key size %u", sm_conn->sm_connection_encrypted,
40963deb3ec6SMatthias Ringwald                         sm_conn->sm_actual_encryption_key_size);
40973deb3ec6SMatthias Ringwald                     log_info("event handler, state %u", sm_conn->sm_engine_state);
409803a9359aSMatthias Ringwald 
4099fbe050beSMatthias Ringwald                     switch (sm_conn->sm_engine_state){
4100fbe050beSMatthias Ringwald 
41015567aa60SMatthias Ringwald                         case SM_PH4_W4_CONNECTION_ENCRYPTED:
410203a9359aSMatthias Ringwald                             // encryption change event concludes re-encryption for bonded devices (even if it fails)
41031d80f1e6SMatthias Ringwald                             if (sm_conn->sm_connection_encrypted != 0u) {
4104fbe050beSMatthias Ringwald                                 status = ERROR_CODE_SUCCESS;
41051d80f1e6SMatthias Ringwald                                 if (IS_RESPONDER(sm_conn->sm_role)){
41068d4eef95SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
41078d4eef95SMatthias Ringwald                                 } else {
410803a9359aSMatthias Ringwald                                     sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
41098d4eef95SMatthias Ringwald                                 }
4110fbe050beSMatthias Ringwald                             } else {
4111e28291c1SMatthias Ringwald                                 status = hci_event_encryption_change_get_status(packet);
4112cb6d7eb0SMatthias Ringwald                                 // set state to 'RE-ENCRYPTION FAILED' to allow pairing but prevent other interactions
41133b7fd749SMatthias Ringwald                                 // also, gap_reconnect_security_setup_active will return true
4114cb6d7eb0SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_GENERAL_REENCRYPTION_FAILED;
41153b7fd749SMatthias Ringwald                             }
4116fbe050beSMatthias Ringwald 
4117fbe050beSMatthias Ringwald                             // emit re-encryption complete
411873102768SMatthias Ringwald                             sm_reencryption_complete(sm_conn, status);
4119fbe050beSMatthias Ringwald 
4120c245ca32SMatthias Ringwald                             // notify client, if pairing was requested before
4121c245ca32SMatthias Ringwald                             if (sm_conn->sm_pairing_requested){
41225f3874afSMatthias Ringwald                                 sm_conn->sm_pairing_requested = false;
41230ccf6c9cSMatthias Ringwald                                 sm_pairing_complete(sm_conn, status, 0);
412403a9359aSMatthias Ringwald                             }
412503a9359aSMatthias Ringwald 
41263deb3ec6SMatthias Ringwald                             sm_done_for_handle(sm_conn->sm_handle);
41273deb3ec6SMatthias Ringwald                             break;
4128fbe050beSMatthias Ringwald 
41293deb3ec6SMatthias Ringwald                         case SM_PH2_W4_CONNECTION_ENCRYPTED:
4130fbe050beSMatthias Ringwald                             if (!sm_conn->sm_connection_encrypted) break;
413157ff4745SMatthias Ringwald                             // handler for HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE
413257ff4745SMatthias Ringwald                             // contains the same code for this state
4133dd583d9fSMatthias Ringwald                             sm_conn->sm_connection_sc = setup->sm_use_secure_connections;
413442134bc6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
41353deb3ec6SMatthias Ringwald                                 // slave
413657ff4745SMatthias Ringwald                                 if (sm_conn->sm_connection_sc){
4137bbf8db22SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
4138bbf8db22SMatthias Ringwald                                 } else {
4139f3582630SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph3_random, (void *)(uintptr_t) sm_conn->sm_handle);
4140bbf8db22SMatthias Ringwald                                 }
41413deb3ec6SMatthias Ringwald                             } else {
41423deb3ec6SMatthias Ringwald                                 // master
414361d1a45eSMatthias Ringwald                                 if (sm_key_distribution_all_received()){
41443deb3ec6SMatthias Ringwald                                     // skip receiving keys as there are none
41453deb3ec6SMatthias Ringwald                                     sm_key_distribution_handle_all_received(sm_conn);
4146f3582630SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph3_random, (void *)(uintptr_t) sm_conn->sm_handle);
41473deb3ec6SMatthias Ringwald                                 } else {
41483deb3ec6SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
41493deb3ec6SMatthias Ringwald                                 }
41503deb3ec6SMatthias Ringwald                             }
41513deb3ec6SMatthias Ringwald                             break;
4152c18be159SMatthias Ringwald 
4153c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4154c18be159SMatthias Ringwald                         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
4155599e89daSMatthias Ringwald                             sm_event_handle_classic_encryption_event(sm_conn, con_handle);
4156c18be159SMatthias Ringwald                             break;
4157c18be159SMatthias Ringwald #endif
41583deb3ec6SMatthias Ringwald                         default:
41593deb3ec6SMatthias Ringwald                             break;
41603deb3ec6SMatthias Ringwald                     }
41613deb3ec6SMatthias Ringwald                     break;
41623deb3ec6SMatthias Ringwald 
41633deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE:
4164711e6c80SMatthias Ringwald                     con_handle = little_endian_read_16(packet, 3);
4165711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
41663deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
41673deb3ec6SMatthias Ringwald 
41683deb3ec6SMatthias Ringwald                     log_info("Encryption key refresh complete, key size %u", sm_conn->sm_actual_encryption_key_size);
41693deb3ec6SMatthias Ringwald                     log_info("event handler, state %u", sm_conn->sm_engine_state);
41703deb3ec6SMatthias Ringwald                     // continue if part of initial pairing
41713deb3ec6SMatthias Ringwald                     switch (sm_conn->sm_engine_state){
41725567aa60SMatthias Ringwald                         case SM_PH4_W4_CONNECTION_ENCRYPTED:
41731d80f1e6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
41745567aa60SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
41755567aa60SMatthias Ringwald                             } else {
41763deb3ec6SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
41775567aa60SMatthias Ringwald                             }
41783deb3ec6SMatthias Ringwald                             sm_done_for_handle(sm_conn->sm_handle);
41793deb3ec6SMatthias Ringwald                             break;
41803deb3ec6SMatthias Ringwald                         case SM_PH2_W4_CONNECTION_ENCRYPTED:
418157ff4745SMatthias Ringwald                             // handler for HCI_EVENT_ENCRYPTION_CHANGE
418257ff4745SMatthias Ringwald                             // contains the same code for this state
418357ff4745SMatthias Ringwald                             sm_conn->sm_connection_sc = setup->sm_use_secure_connections;
418442134bc6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
41853deb3ec6SMatthias Ringwald                                 // slave
418657ff4745SMatthias Ringwald                                 if (sm_conn->sm_connection_sc){
418757ff4745SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
418857ff4745SMatthias Ringwald                                 } else {
4189f3582630SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph3_random, (void *)(uintptr_t) sm_conn->sm_handle);
419057ff4745SMatthias Ringwald                                 }
41913deb3ec6SMatthias Ringwald                             } else {
41923deb3ec6SMatthias Ringwald                                 // master
419357ff4745SMatthias Ringwald                                 if (sm_key_distribution_all_received()){
419457ff4745SMatthias Ringwald                                     // skip receiving keys as there are none
419557ff4745SMatthias Ringwald                                     sm_key_distribution_handle_all_received(sm_conn);
419657ff4745SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph3_random, (void *)(uintptr_t) sm_conn->sm_handle);
419757ff4745SMatthias Ringwald                                 } else {
41983deb3ec6SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
41993deb3ec6SMatthias Ringwald                                 }
420057ff4745SMatthias Ringwald                             }
42013deb3ec6SMatthias Ringwald                             break;
420294219034SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
420394219034SMatthias Ringwald                         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
420494219034SMatthias Ringwald                             sm_event_handle_classic_encryption_event(sm_conn, con_handle);
420594219034SMatthias Ringwald                             break;
420694219034SMatthias Ringwald #endif
42073deb3ec6SMatthias Ringwald                         default:
42083deb3ec6SMatthias Ringwald                             break;
42093deb3ec6SMatthias Ringwald                     }
42103deb3ec6SMatthias Ringwald                     break;
42113deb3ec6SMatthias Ringwald 
42123deb3ec6SMatthias Ringwald 
42133deb3ec6SMatthias Ringwald                 case HCI_EVENT_DISCONNECTION_COMPLETE:
4214711e6c80SMatthias Ringwald                     con_handle = little_endian_read_16(packet, 3);
4215711e6c80SMatthias Ringwald                     sm_done_for_handle(con_handle);
4216711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
42173deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
42183deb3ec6SMatthias Ringwald 
421903f736b1SMatthias Ringwald                     // pairing failed, if it was ongoing
42207f3f442dSMatthias Ringwald                     switch (sm_conn->sm_engine_state){
42217f3f442dSMatthias Ringwald                         case SM_GENERAL_IDLE:
42227f3f442dSMatthias Ringwald                         case SM_INITIATOR_CONNECTED:
42237f3f442dSMatthias Ringwald                         case SM_RESPONDER_IDLE:
42247f3f442dSMatthias Ringwald                             break;
42257f3f442dSMatthias Ringwald                         default:
422668a18fb9SMatthias Ringwald                             sm_reencryption_complete(sm_conn, ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION);
42270ccf6c9cSMatthias Ringwald                             sm_pairing_complete(sm_conn, ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION, 0);
42287f3f442dSMatthias Ringwald                             break;
422903f736b1SMatthias Ringwald                     }
4230accbde80SMatthias Ringwald 
42313deb3ec6SMatthias Ringwald                     sm_conn->sm_engine_state = SM_GENERAL_IDLE;
42323deb3ec6SMatthias Ringwald                     sm_conn->sm_handle = 0;
42333deb3ec6SMatthias Ringwald                     break;
42343deb3ec6SMatthias Ringwald 
42353deb3ec6SMatthias Ringwald                 case HCI_EVENT_COMMAND_COMPLETE:
4236f7811256SMatthias Ringwald                     if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_BD_ADDR) {
42379091c5f5SMatthias Ringwald                         // set local addr for le device db
423833373e40SMatthias Ringwald                         reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1], addr);
42390c130b19SMatthias Ringwald                         le_device_db_set_local_bd_addr(addr);
424033373e40SMatthias Ringwald                     }
424165b44ffdSMatthias Ringwald                     break;
4242a036ae12SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4243a036ae12SMatthias Ringwald                 case L2CAP_EVENT_INFORMATION_RESPONSE:
4244a036ae12SMatthias Ringwald                     con_handle = l2cap_event_information_response_get_con_handle(packet);
4245a036ae12SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
4246a036ae12SMatthias Ringwald                     if (!sm_conn) break;
4247a036ae12SMatthias Ringwald                     if (sm_conn->sm_engine_state == SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK){
4248a036ae12SMatthias Ringwald                         // check if remote supports SMP over BR/EDR
4249a036ae12SMatthias Ringwald                         const hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
4250a036ae12SMatthias Ringwald                         if ((hci_connection->l2cap_state.fixed_channels_supported & (1 << L2CAP_CID_BR_EDR_SECURITY_MANAGER)) != 0){
4251a036ae12SMatthias Ringwald                             sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST;
4252a036ae12SMatthias Ringwald                         } else {
4253a036ae12SMatthias Ringwald                             sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
4254f82b8f4bSMatthias Ringwald                             hci_dedicated_bonding_defer_disconnect(con_handle, false);
4255a036ae12SMatthias Ringwald                         }
4256a036ae12SMatthias Ringwald                     }
4257a036ae12SMatthias Ringwald                     break;
4258a036ae12SMatthias Ringwald #endif
425965b44ffdSMatthias Ringwald                 default:
426065b44ffdSMatthias Ringwald                     break;
42613deb3ec6SMatthias Ringwald 			}
426265b44ffdSMatthias Ringwald             break;
426365b44ffdSMatthias Ringwald         default:
426465b44ffdSMatthias Ringwald             break;
42653deb3ec6SMatthias Ringwald 	}
42663deb3ec6SMatthias Ringwald 
42673deb3ec6SMatthias Ringwald     sm_run();
42683deb3ec6SMatthias Ringwald }
42693deb3ec6SMatthias Ringwald 
sm_calc_actual_encryption_key_size(int other)42703deb3ec6SMatthias Ringwald static inline int sm_calc_actual_encryption_key_size(int other){
42713deb3ec6SMatthias Ringwald     if (other < sm_min_encryption_key_size) return 0;
42723deb3ec6SMatthias Ringwald     if (other < sm_max_encryption_key_size) return other;
42733deb3ec6SMatthias Ringwald     return sm_max_encryption_key_size;
42743deb3ec6SMatthias Ringwald }
42753deb3ec6SMatthias Ringwald 
4276945888f5SMatthias Ringwald 
427731c09488SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_just_works_or_numeric_comparison(stk_generation_method_t method)42781d80f1e6SMatthias Ringwald static bool sm_just_works_or_numeric_comparison(stk_generation_method_t method){
4279945888f5SMatthias Ringwald     switch (method){
4280945888f5SMatthias Ringwald         case JUST_WORKS:
428147fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
42821d80f1e6SMatthias Ringwald             return true;
4283945888f5SMatthias Ringwald         default:
42841d80f1e6SMatthias Ringwald             return false;
4285945888f5SMatthias Ringwald     }
4286945888f5SMatthias Ringwald }
428707036a04SMatthias Ringwald // responder
4288945888f5SMatthias Ringwald 
sm_passkey_used(stk_generation_method_t method)42891d80f1e6SMatthias Ringwald static bool sm_passkey_used(stk_generation_method_t method){
4290688a08f9SMatthias Ringwald     switch (method){
4291688a08f9SMatthias Ringwald         case PK_RESP_INPUT:
42921d80f1e6SMatthias Ringwald             return true;
4293688a08f9SMatthias Ringwald         default:
4294688a08f9SMatthias Ringwald             return 0;
4295688a08f9SMatthias Ringwald     }
4296688a08f9SMatthias Ringwald }
429740c5d850SMatthias Ringwald 
sm_passkey_entry(stk_generation_method_t method)42986777d8fdSMatthias Ringwald static bool sm_passkey_entry(stk_generation_method_t method){
429940c5d850SMatthias Ringwald     switch (method){
430040c5d850SMatthias Ringwald         case PK_RESP_INPUT:
430140c5d850SMatthias Ringwald         case PK_INIT_INPUT:
430247fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
43036777d8fdSMatthias Ringwald             return true;
430440c5d850SMatthias Ringwald         default:
43056777d8fdSMatthias Ringwald             return false;
430640c5d850SMatthias Ringwald     }
430740c5d850SMatthias Ringwald }
430840c5d850SMatthias Ringwald 
430931c09488SMatthias Ringwald #endif
4310688a08f9SMatthias Ringwald 
43113deb3ec6SMatthias Ringwald /**
43123deb3ec6SMatthias Ringwald  * @return ok
43133deb3ec6SMatthias Ringwald  */
sm_validate_stk_generation_method(void)43143deb3ec6SMatthias Ringwald static int sm_validate_stk_generation_method(void){
43153deb3ec6SMatthias Ringwald     // check if STK generation method is acceptable by client
43163deb3ec6SMatthias Ringwald     switch (setup->sm_stk_generation_method){
43173deb3ec6SMatthias Ringwald         case JUST_WORKS:
43184ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_JUST_WORKS) != 0u;
43193deb3ec6SMatthias Ringwald         case PK_RESP_INPUT:
43203deb3ec6SMatthias Ringwald         case PK_INIT_INPUT:
432147fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
43224ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_PASSKEY) != 0u;
43233deb3ec6SMatthias Ringwald         case OOB:
43244ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_OOB) != 0u;
432547fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
43264ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON) != 0u;
43273deb3ec6SMatthias Ringwald         default:
43283deb3ec6SMatthias Ringwald             return 0;
43293deb3ec6SMatthias Ringwald     }
43303deb3ec6SMatthias Ringwald }
43313deb3ec6SMatthias Ringwald 
433236f0defaSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
sm_initiator_connected_handle_security_request(sm_connection_t * sm_conn,const uint8_t * packet)433336f0defaSMatthias Ringwald static void sm_initiator_connected_handle_security_request(sm_connection_t * sm_conn, const uint8_t *packet){
433436f0defaSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
433536f0defaSMatthias Ringwald     if (sm_sc_only_mode){
433636f0defaSMatthias Ringwald         uint8_t auth_req = packet[1];
433736f0defaSMatthias Ringwald         if ((auth_req & SM_AUTHREQ_SECURE_CONNECTION) == 0){
433836f0defaSMatthias Ringwald             sm_pairing_error(sm_conn, SM_REASON_AUTHENTHICATION_REQUIREMENTS);
433936f0defaSMatthias Ringwald             return;
434036f0defaSMatthias Ringwald         }
434136f0defaSMatthias Ringwald     }
434236f0defaSMatthias Ringwald #else
434336f0defaSMatthias Ringwald     UNUSED(packet);
434436f0defaSMatthias Ringwald #endif
434536f0defaSMatthias Ringwald 
434636f0defaSMatthias Ringwald     int have_ltk;
434736f0defaSMatthias Ringwald     uint8_t ltk[16];
434836f0defaSMatthias Ringwald 
434936f0defaSMatthias Ringwald     // IRK complete?
435036f0defaSMatthias Ringwald     switch (sm_conn->sm_irk_lookup_state){
435136f0defaSMatthias Ringwald         case IRK_LOOKUP_FAILED:
435236f0defaSMatthias Ringwald             // start pairing
435336f0defaSMatthias Ringwald             sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
435436f0defaSMatthias Ringwald             break;
435536f0defaSMatthias Ringwald         case IRK_LOOKUP_SUCCEEDED:
435636f0defaSMatthias Ringwald             le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
435736f0defaSMatthias Ringwald             have_ltk = !sm_is_null_key(ltk);
435836f0defaSMatthias Ringwald             log_info("central: security request - have_ltk %u, encryption %u", have_ltk, sm_conn->sm_connection_encrypted);
435936f0defaSMatthias Ringwald             if (have_ltk && (sm_conn->sm_connection_encrypted == 0)){
436036f0defaSMatthias Ringwald                 // start re-encrypt if we have LTK and the connection is not already encrypted
436136f0defaSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
436236f0defaSMatthias Ringwald             } else {
436336f0defaSMatthias Ringwald                 // start pairing
436436f0defaSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
436536f0defaSMatthias Ringwald             }
436636f0defaSMatthias Ringwald             break;
436736f0defaSMatthias Ringwald         default:
436836f0defaSMatthias Ringwald             // otherwise, store security request
43690dcaa15fSMatthias Ringwald             sm_conn->sm_security_request_received = true;
437036f0defaSMatthias Ringwald             break;
437136f0defaSMatthias Ringwald     }
437236f0defaSMatthias Ringwald }
437336f0defaSMatthias Ringwald #endif
437436f0defaSMatthias Ringwald 
sm_pdu_validate_and_get_opcode(uint8_t packet_type,const uint8_t * packet,uint16_t size)4375f9bda154SMatthias Ringwald static uint8_t sm_pdu_validate_and_get_opcode(uint8_t packet_type, const uint8_t *packet, uint16_t size){
43768334d3d8SMatthias Ringwald 
43774c1d1092SMatthias Ringwald     // size of complete sm_pdu used to validate input
43784c1d1092SMatthias Ringwald     static const uint8_t sm_pdu_size[] = {
43794c1d1092SMatthias Ringwald             0,  // 0x00 invalid opcode
43804c1d1092SMatthias Ringwald             7,  // 0x01 pairing request
43814c1d1092SMatthias Ringwald             7,  // 0x02 pairing response
43824c1d1092SMatthias Ringwald             17, // 0x03 pairing confirm
43834c1d1092SMatthias Ringwald             17, // 0x04 pairing random
43844c1d1092SMatthias Ringwald             2,  // 0x05 pairing failed
43854c1d1092SMatthias Ringwald             17, // 0x06 encryption information
43867a2e6387SMatthias Ringwald             11, // 0x07 master identification
43874c1d1092SMatthias Ringwald             17, // 0x08 identification information
43884c1d1092SMatthias Ringwald             8,  // 0x09 identify address information
43894c1d1092SMatthias Ringwald             17, // 0x0a signing information
43904c1d1092SMatthias Ringwald             2,  // 0x0b security request
43914c1d1092SMatthias Ringwald             65, // 0x0c pairing public key
43924c1d1092SMatthias Ringwald             17, // 0x0d pairing dhk check
43934c1d1092SMatthias Ringwald             2,  // 0x0e keypress notification
43944c1d1092SMatthias Ringwald     };
43953deb3ec6SMatthias Ringwald 
4396f9bda154SMatthias Ringwald     if (packet_type != SM_DATA_PACKET) return 0;
4397f9bda154SMatthias Ringwald     if (size == 0u) return 0;
43984c1d1092SMatthias Ringwald 
43994c1d1092SMatthias Ringwald     uint8_t sm_pdu_code = packet[0];
44004c1d1092SMatthias Ringwald 
44014c1d1092SMatthias Ringwald     // validate pdu size
4402f9bda154SMatthias Ringwald     if (sm_pdu_code >= sizeof(sm_pdu_size)) return 0;
4403f9bda154SMatthias Ringwald     if (sm_pdu_size[sm_pdu_code] != size)   return 0;
4404f9bda154SMatthias Ringwald 
4405f9bda154SMatthias Ringwald     return sm_pdu_code;
4406f9bda154SMatthias Ringwald }
4407f9bda154SMatthias Ringwald 
4408f94048d1SMatthias Ringwald 
4409f94048d1SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_pdu_handler_pairing_public_key(sm_connection_t * sm_conn,const uint8_t * packet)4410f94048d1SMatthias Ringwald static void sm_pdu_handler_pairing_public_key(sm_connection_t * sm_conn, const uint8_t * packet) {
4411f94048d1SMatthias Ringwald     // store public key for DH Key calculation
4412f94048d1SMatthias Ringwald     reverse_256(&packet[01], &setup->sm_peer_q[0]);
4413f94048d1SMatthias Ringwald     reverse_256(&packet[33], &setup->sm_peer_q[32]);
4414f94048d1SMatthias Ringwald 
4415f94048d1SMatthias Ringwald     // CVE-2020-26558: abort pairing if remote uses the same public key
4416f94048d1SMatthias Ringwald     if (memcmp(&setup->sm_peer_q, ec_q, 64) == 0){
4417f94048d1SMatthias Ringwald         log_info("Remote PK matches ours");
4418f94048d1SMatthias Ringwald         sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
4419f94048d1SMatthias Ringwald         return;
4420f94048d1SMatthias Ringwald     }
4421f94048d1SMatthias Ringwald 
4422f94048d1SMatthias Ringwald     // validate public key
4423f94048d1SMatthias Ringwald     int err = btstack_crypto_ecc_p256_validate_public_key(setup->sm_peer_q);
4424f94048d1SMatthias Ringwald     if (err != 0){
4425f94048d1SMatthias Ringwald         log_info("sm: peer public key invalid %x", err);
4426f94048d1SMatthias Ringwald         sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
4427f94048d1SMatthias Ringwald         return;
4428f94048d1SMatthias Ringwald     }
4429f94048d1SMatthias Ringwald 
4430f94048d1SMatthias Ringwald     // start calculating dhkey
4431f94048d1SMatthias Ringwald     btstack_crypto_ecc_p256_calculate_dhkey(&sm_crypto_ecc_p256_request, setup->sm_peer_q, setup->sm_dhkey, sm_sc_dhkey_calculated, (void*)(uintptr_t) sm_conn->sm_handle);
4432f94048d1SMatthias Ringwald 
4433f94048d1SMatthias Ringwald     log_info("public key received, generation method %u", setup->sm_stk_generation_method);
4434f94048d1SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
4435f94048d1SMatthias Ringwald         // responder
4436f94048d1SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
4437f94048d1SMatthias Ringwald     } else {
4438f94048d1SMatthias Ringwald         // initiator
4439f94048d1SMatthias Ringwald         // stk generation method
4440f94048d1SMatthias Ringwald         // passkey entry: notify app to show passkey or to request passkey
4441f94048d1SMatthias Ringwald         switch (setup->sm_stk_generation_method){
4442f94048d1SMatthias Ringwald             case JUST_WORKS:
4443f94048d1SMatthias Ringwald             case NUMERIC_COMPARISON:
4444f94048d1SMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W4_CONFIRMATION;
4445f94048d1SMatthias Ringwald                 break;
4446f94048d1SMatthias Ringwald             case PK_RESP_INPUT:
4447f94048d1SMatthias Ringwald                 sm_sc_start_calculating_local_confirm(sm_conn);
4448f94048d1SMatthias Ringwald                 break;
4449f94048d1SMatthias Ringwald             case PK_INIT_INPUT:
4450f94048d1SMatthias Ringwald             case PK_BOTH_INPUT:
4451f94048d1SMatthias Ringwald                 if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
4452f94048d1SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
4453f94048d1SMatthias Ringwald                     break;
4454f94048d1SMatthias Ringwald                 }
4455f94048d1SMatthias Ringwald                 sm_sc_start_calculating_local_confirm(sm_conn);
4456f94048d1SMatthias Ringwald                 break;
4457f94048d1SMatthias Ringwald             case OOB:
4458f94048d1SMatthias Ringwald                 if (setup->sm_have_oob_data){
4459f94048d1SMatthias Ringwald                     // if we have received rb & cb, verify Cb = f4(PKb, PKb, rb, 0)
4460f94048d1SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
4461f94048d1SMatthias Ringwald                 } else {
4462f94048d1SMatthias Ringwald                     // otherwise, generate our nonce
4463f94048d1SMatthias Ringwald                     sm_sc_generate_nx_for_send_random(sm_conn);
4464f94048d1SMatthias Ringwald                 }
4465f94048d1SMatthias Ringwald                 break;
4466f94048d1SMatthias Ringwald             default:
4467f94048d1SMatthias Ringwald                 btstack_assert(false);
4468f94048d1SMatthias Ringwald                 break;
4469f94048d1SMatthias Ringwald         }
4470f94048d1SMatthias Ringwald     }
4471f94048d1SMatthias Ringwald }
4472f94048d1SMatthias Ringwald #endif
4473f94048d1SMatthias Ringwald 
4474f94048d1SMatthias Ringwald 
sm_pdu_handler(sm_connection_t * sm_conn,uint8_t sm_pdu_code,const uint8_t * packet)447573970ae5SMatthias Ringwald static void sm_pdu_handler(sm_connection_t *sm_conn, uint8_t sm_pdu_code, const uint8_t *packet) {
44766e46ecceSMatthias Ringwald     log_debug("sm_pdu_handler: state %u, pdu 0x%02x", sm_conn->sm_engine_state, sm_pdu_code);
44776e46ecceSMatthias Ringwald 
4478035b1b64SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
44796e46ecceSMatthias Ringwald     int err;
4480035b1b64SMatthias Ringwald #endif
44816e46ecceSMatthias Ringwald     uint8_t max_encryption_key_size;
44826e46ecceSMatthias Ringwald 
44833deb3ec6SMatthias Ringwald     switch (sm_conn->sm_engine_state){
44843deb3ec6SMatthias Ringwald 
4485c8d0ff33SMatthias Ringwald         // a sm timeout requires a new physical connection
44863deb3ec6SMatthias Ringwald         case SM_GENERAL_TIMEOUT:
44873deb3ec6SMatthias Ringwald             return;
44883deb3ec6SMatthias Ringwald 
448942134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
449042134bc6SMatthias Ringwald 
44913deb3ec6SMatthias Ringwald         // Initiator
44923deb3ec6SMatthias Ringwald         case SM_INITIATOR_CONNECTED:
44934c1d1092SMatthias Ringwald             if ((sm_pdu_code != SM_CODE_SECURITY_REQUEST) || (sm_conn->sm_role)){
44943deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44953deb3ec6SMatthias Ringwald                 break;
44963deb3ec6SMatthias Ringwald             }
449736f0defaSMatthias Ringwald             sm_initiator_connected_handle_security_request(sm_conn, packet);
4498dc8ca372SMatthias Ringwald             break;
44993deb3ec6SMatthias Ringwald 
45003deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH1_W4_PAIRING_RESPONSE:
4501aacfafc3SMatthias Ringwald             // Core 5, Vol 3, Part H, 2.4.6:
4502aacfafc3SMatthias Ringwald             // "The master shall ignore the slave’s Security Request if the master has sent a Pairing Request
4503aacfafc3SMatthias Ringwald             //  without receiving a Pairing Response from the slave or if the master has initiated encryption mode setup."
4504aacfafc3SMatthias Ringwald             if (sm_pdu_code == SM_CODE_SECURITY_REQUEST){
4505aacfafc3SMatthias Ringwald                 log_info("Ignoring Security Request");
4506aacfafc3SMatthias Ringwald                 break;
4507aacfafc3SMatthias Ringwald             }
4508aacfafc3SMatthias Ringwald 
4509aacfafc3SMatthias Ringwald             // all other pdus are incorrect
45104c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RESPONSE){
45113deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
45123deb3ec6SMatthias Ringwald                 break;
45133deb3ec6SMatthias Ringwald             }
45140af429c6SMatthias Ringwald 
45153deb3ec6SMatthias Ringwald             // store pairing request
45166535961aSMatthias Ringwald             (void)memcpy(&setup->sm_s_pres, packet,
45176535961aSMatthias Ringwald                          sizeof(sm_pairing_packet_t));
4518afbd946dSMatthias Ringwald 
4519afbd946dSMatthias Ringwald             // validate encryption key size
4520afbd946dSMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(setup->sm_s_pres);
4521afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4522afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4523afbd946dSMatthias Ringwald                 break;
4524afbd946dSMatthias Ringwald             }
4525afbd946dSMatthias Ringwald 
45263deb3ec6SMatthias Ringwald             err = sm_stk_generation_init(sm_conn);
45270af429c6SMatthias Ringwald 
45280af429c6SMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
45290af429c6SMatthias Ringwald             if (0 < test_pairing_failure && test_pairing_failure < SM_REASON_DHKEY_CHECK_FAILED){
45300af429c6SMatthias Ringwald                 log_info("testing_support: abort with pairing failure %u", test_pairing_failure);
45310af429c6SMatthias Ringwald                 err = test_pairing_failure;
45320af429c6SMatthias Ringwald             }
45330af429c6SMatthias Ringwald #endif
45340af429c6SMatthias Ringwald 
45359305033eSMatthias Ringwald             if (err != 0){
4536f4935286SMatthias Ringwald                 sm_pairing_error(sm_conn, err);
45373deb3ec6SMatthias Ringwald                 break;
45383deb3ec6SMatthias Ringwald             }
4539b41539d5SMatthias Ringwald 
4540b41539d5SMatthias Ringwald             // generate random number first, if we need to show passkey
4541b41539d5SMatthias Ringwald             if (setup->sm_stk_generation_method == PK_RESP_INPUT){
4542f3582630SMatthias Ringwald                 btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph2_tk,  (void *)(uintptr_t) sm_conn->sm_handle);
4543b41539d5SMatthias Ringwald                 break;
4544b41539d5SMatthias Ringwald             }
4545b41539d5SMatthias Ringwald 
4546136d331aSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4547136d331aSMatthias Ringwald             if (setup->sm_use_secure_connections){
45488cba5ca3SMatthias Ringwald                 // SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
45498cba5ca3SMatthias Ringwald                 if (setup->sm_stk_generation_method == JUST_WORKS){
4550136d331aSMatthias Ringwald                     sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
4551136d331aSMatthias Ringwald                     sm_trigger_user_response(sm_conn);
4552136d331aSMatthias Ringwald                     if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
4553c6b7cbd9SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
4554136d331aSMatthias Ringwald                     }
45558cba5ca3SMatthias Ringwald                 } else {
4556c6b7cbd9SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
45578cba5ca3SMatthias Ringwald                 }
4558136d331aSMatthias Ringwald                 break;
4559136d331aSMatthias Ringwald             }
4560136d331aSMatthias Ringwald #endif
45613deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
45623deb3ec6SMatthias Ringwald             sm_trigger_user_response(sm_conn);
45633deb3ec6SMatthias Ringwald             // response_idle == nothing <--> sm_trigger_user_response() did not require response
45643deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
4565f3582630SMatthias Ringwald                 btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_random, 16, &sm_handle_random_result_ph2_random, (void *)(uintptr_t) sm_conn->sm_handle);
45663deb3ec6SMatthias Ringwald             }
45673deb3ec6SMatthias Ringwald             break;
45683deb3ec6SMatthias Ringwald 
45693deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH2_W4_PAIRING_CONFIRM:
45704c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
45713deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
45723deb3ec6SMatthias Ringwald                 break;
45733deb3ec6SMatthias Ringwald             }
45743deb3ec6SMatthias Ringwald 
45753deb3ec6SMatthias Ringwald             // store s_confirm
45769c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
4577192365feSMatthias Ringwald 
4578aa9b34e5SMatthias Ringwald             // abort if s_confirm matches m_confirm
4579aa9b34e5SMatthias Ringwald             if (memcmp(setup->sm_local_confirm, setup->sm_peer_confirm, 16) == 0){
4580aa9b34e5SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4581aa9b34e5SMatthias Ringwald                 break;
4582aa9b34e5SMatthias Ringwald             }
4583aa9b34e5SMatthias Ringwald 
4584192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4585192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4586192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4587192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4588192365feSMatthias Ringwald             }
4589192365feSMatthias Ringwald #endif
45903deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
45913deb3ec6SMatthias Ringwald             break;
45923deb3ec6SMatthias Ringwald 
45933deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH2_W4_PAIRING_RANDOM:
45944c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
45953deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
45963deb3ec6SMatthias Ringwald                 break;;
45973deb3ec6SMatthias Ringwald             }
45983deb3ec6SMatthias Ringwald 
45993deb3ec6SMatthias Ringwald             // received random value
46009c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_random);
46013deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
46023deb3ec6SMatthias Ringwald             break;
4603dc542de1SMatthias Ringwald 
4604e2a5eb63SMatthias Ringwald         case SM_INITIATOR_PH4_HAS_LTK:
4605dc542de1SMatthias Ringwald         case SM_PH4_W4_CONNECTION_ENCRYPTED:
4606dc542de1SMatthias Ringwald             // ignore Security Request, see SM_INITIATOR_PH1_W4_PAIRING_RESPONSE above
4607dc542de1SMatthias Ringwald             if (sm_pdu_code != SM_CODE_SECURITY_REQUEST){
4608dc542de1SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4609dc542de1SMatthias Ringwald             }
4610dc542de1SMatthias Ringwald             break;
461142134bc6SMatthias Ringwald #endif
46123deb3ec6SMatthias Ringwald 
461342134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
46143deb3ec6SMatthias Ringwald         // Responder
46153deb3ec6SMatthias Ringwald         case SM_RESPONDER_IDLE:
46163deb3ec6SMatthias Ringwald         case SM_RESPONDER_SEND_SECURITY_REQUEST:
46173deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
46184c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
46193deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
46203deb3ec6SMatthias Ringwald                 break;;
46213deb3ec6SMatthias Ringwald             }
46223deb3ec6SMatthias Ringwald 
46233deb3ec6SMatthias Ringwald             // store pairing request
4624212d735eSMatthias Ringwald             (void)memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
4625212d735eSMatthias Ringwald 
4626afbd946dSMatthias Ringwald             // validation encryption key size
4627afbd946dSMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(sm_conn->sm_m_preq);
4628afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4629afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4630afbd946dSMatthias Ringwald                 break;
4631afbd946dSMatthias Ringwald             }
4632afbd946dSMatthias Ringwald 
4633212d735eSMatthias Ringwald             // check if IRK completed
4634212d735eSMatthias Ringwald             switch (sm_conn->sm_irk_lookup_state){
4635212d735eSMatthias Ringwald                 case IRK_LOOKUP_SUCCEEDED:
4636212d735eSMatthias Ringwald                 case IRK_LOOKUP_FAILED:
46373deb3ec6SMatthias Ringwald                     sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
46383deb3ec6SMatthias Ringwald                     break;
4639212d735eSMatthias Ringwald                 default:
4640212d735eSMatthias Ringwald                     sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK;
4641212d735eSMatthias Ringwald                     break;
4642212d735eSMatthias Ringwald             }
4643212d735eSMatthias Ringwald             break;
464442134bc6SMatthias Ringwald #endif
46453deb3ec6SMatthias Ringwald 
464627c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4647c6b7cbd9SMatthias Ringwald         case SM_SC_W4_PUBLIC_KEY_COMMAND:
46484c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_PUBLIC_KEY){
464927c32905SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
465027c32905SMatthias Ringwald                 break;
465127c32905SMatthias Ringwald             }
4652f94048d1SMatthias Ringwald             sm_pdu_handler_pairing_public_key(sm_conn, packet);
465327c32905SMatthias Ringwald             break;
4654e53be891SMatthias Ringwald 
4655c6b7cbd9SMatthias Ringwald         case SM_SC_W4_CONFIRMATION:
46564c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
465745a61d50SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
465845a61d50SMatthias Ringwald                 break;
465945a61d50SMatthias Ringwald             }
466045a61d50SMatthias Ringwald             // received confirm value
466145a61d50SMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
466245a61d50SMatthias Ringwald 
4663192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4664192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4665192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4666192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4667192365feSMatthias Ringwald             }
4668192365feSMatthias Ringwald #endif
466942134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
467045a61d50SMatthias Ringwald                 // responder
467107036a04SMatthias Ringwald                 if (sm_passkey_used(setup->sm_stk_generation_method)){
467207036a04SMatthias Ringwald                     if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
467307036a04SMatthias Ringwald                         // still waiting for passkey
467407036a04SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
467507036a04SMatthias Ringwald                         break;
467607036a04SMatthias Ringwald                     }
467707036a04SMatthias Ringwald                 }
4678b35a3de2SMatthias Ringwald                 sm_sc_start_calculating_local_confirm(sm_conn);
467945a61d50SMatthias Ringwald             } else {
468045a61d50SMatthias Ringwald                 // initiator
4681945888f5SMatthias Ringwald                 if (sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method)){
46826ca80073SMatthias Ringwald                     btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_nonce, 16, &sm_handle_random_result_sc_next_send_pairing_random, (void*)(uintptr_t) sm_conn->sm_handle);
4683f1c1783eSMatthias Ringwald                 } else {
4684c6b7cbd9SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
468545a61d50SMatthias Ringwald                 }
4686f1c1783eSMatthias Ringwald             }
468745a61d50SMatthias Ringwald             break;
468845a61d50SMatthias Ringwald 
4689c6b7cbd9SMatthias Ringwald         case SM_SC_W4_PAIRING_RANDOM:
46904c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
4691e53be891SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4692136d331aSMatthias Ringwald                 break;
4693e53be891SMatthias Ringwald             }
4694e53be891SMatthias Ringwald 
4695e53be891SMatthias Ringwald             // received random value
4696e53be891SMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_nonce);
4697e53be891SMatthias Ringwald 
46985a293e6eSMatthias Ringwald             // validate confirm value if Cb = f4(Pkb, Pka, Nb, z)
4699ae451ec5SMatthias Ringwald             // only check for JUST WORK/NC in initiator role OR passkey entry
4700d686b2d0SMatthias Ringwald             log_info("SM_SC_W4_PAIRING_RANDOM, responder: %u, just works: %u, passkey used %u, passkey entry %u",
4701d686b2d0SMatthias Ringwald                      IS_RESPONDER(sm_conn->sm_role), sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method),
4702d686b2d0SMatthias Ringwald                      sm_passkey_used(setup->sm_stk_generation_method), sm_passkey_entry(setup->sm_stk_generation_method));
470365a9a04eSMatthias Ringwald             if ( (!IS_RESPONDER(sm_conn->sm_role) && sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method))
4704d686b2d0SMatthias Ringwald             ||   (sm_passkey_entry(setup->sm_stk_generation_method)) ) {
4705688a08f9SMatthias Ringwald                  sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
4706ae451ec5SMatthias Ringwald                  break;
47075a293e6eSMatthias Ringwald             }
47086f52a196SMatthias Ringwald 
47094acf7b7bSMatthias Ringwald             // OOB
47104acf7b7bSMatthias Ringwald             if (setup->sm_stk_generation_method == OOB){
47114acf7b7bSMatthias Ringwald 
47124acf7b7bSMatthias Ringwald                 // setup local random, set to zero if remote did not receive our data
47134acf7b7bSMatthias Ringwald                 log_info("Received nonce, setup local random ra/rb for dhkey check");
47144acf7b7bSMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)) {
47154ea43905SMatthias Ringwald                     if (sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq) == 0u) {
47164acf7b7bSMatthias Ringwald                         log_info("Reset rb as A does not have OOB data");
47174acf7b7bSMatthias Ringwald                         memset(setup->sm_rb, 0, 16);
47184acf7b7bSMatthias Ringwald                     } else {
47196535961aSMatthias Ringwald                         (void) memcpy(setup->sm_rb, sm_sc_oob_random, 16);
47204acf7b7bSMatthias Ringwald                         log_info("Use stored rb");
47214acf7b7bSMatthias Ringwald                         log_info_hexdump(setup->sm_rb, 16);
47224acf7b7bSMatthias Ringwald                     }
47234acf7b7bSMatthias Ringwald                 } else {
47244ea43905SMatthias Ringwald                     if (sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres) == 0u){
47254acf7b7bSMatthias Ringwald                         log_info("Reset ra as B does not have OOB data");
47264acf7b7bSMatthias Ringwald                         memset(setup->sm_ra, 0, 16);
47274acf7b7bSMatthias Ringwald                     } else {
47286535961aSMatthias Ringwald                         (void)memcpy(setup->sm_ra, sm_sc_oob_random, 16);
47294acf7b7bSMatthias Ringwald                         log_info("Use stored ra");
47304acf7b7bSMatthias Ringwald                         log_info_hexdump(setup->sm_ra, 16);
47314acf7b7bSMatthias Ringwald                     }
47324acf7b7bSMatthias Ringwald                 }
47334acf7b7bSMatthias Ringwald 
47342419120aSMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
47354acf7b7bSMatthias Ringwald                     if (setup->sm_have_oob_data){
47362419120aSMatthias Ringwald                         // if we have received ra & ca, verify Ca = f4(PKa, PKa, ra, 0)
4737a680ba6bSMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
47382419120aSMatthias Ringwald                     } else {
47392419120aSMatthias Ringwald                         // otherwise, generate our nonce
47402419120aSMatthias Ringwald                         sm_sc_generate_nx_for_send_random(sm_conn);
4741a680ba6bSMatthias Ringwald                     }
47422419120aSMatthias Ringwald                 } else {
47432419120aSMatthias Ringwald                     // Confirm value already validated if received before,
47442419120aSMatthias Ringwald                     // move on to DHKey check
47452419120aSMatthias Ringwald                     sm_sc_prepare_dhkey_check(sm_conn);
47462419120aSMatthias Ringwald                 }
47472419120aSMatthias Ringwald                 break;
47484acf7b7bSMatthias Ringwald             }
4749a680ba6bSMatthias Ringwald 
4750a680ba6bSMatthias Ringwald             // TODO: we only get here for Responder role with JW/NC
4751688a08f9SMatthias Ringwald             sm_sc_state_after_receiving_random(sm_conn);
4752e53be891SMatthias Ringwald             break;
4753e53be891SMatthias Ringwald 
4754901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_G2:
4755901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_G2:
47563cf37b8cSMatthias Ringwald         case SM_SC_W4_CALCULATE_DHKEY:
4757901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_SALT:
4758901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_SALT:
4759901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_MACKEY:
4760901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_MACKEY:
4761901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_LTK:
4762901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_LTK:
4763901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK:
4764c6b7cbd9SMatthias Ringwald         case SM_SC_W4_DHKEY_CHECK_COMMAND:
4765901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
4766d08147dfSMatthias Ringwald         case SM_SC_W4_USER_RESPONSE:
47674c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_DHKEY_CHECK){
4768e53be891SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4769e53be891SMatthias Ringwald                 break;
4770e53be891SMatthias Ringwald             }
4771e53be891SMatthias Ringwald             // store DHKey Check
4772901c000fSMatthias Ringwald             setup->sm_state_vars |= SM_STATE_VAR_DHKEY_COMMAND_RECEIVED;
4773e53be891SMatthias Ringwald             reverse_128(&packet[01], setup->sm_peer_dhkey_check);
4774446a8c36SMatthias Ringwald 
4775901c000fSMatthias Ringwald             // have we been only waiting for dhkey check command?
4776901c000fSMatthias Ringwald             if (sm_conn->sm_engine_state == SM_SC_W4_DHKEY_CHECK_COMMAND){
4777019005a0SMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
4778bd57ffebSMatthias Ringwald             }
4779bd57ffebSMatthias Ringwald             break;
478027c32905SMatthias Ringwald #endif
478127c32905SMatthias Ringwald 
478242134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
47833deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH1_W4_PAIRING_CONFIRM:
47844c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
47853deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
478627c32905SMatthias Ringwald                 break;
47873deb3ec6SMatthias Ringwald             }
47883deb3ec6SMatthias Ringwald 
47893deb3ec6SMatthias Ringwald             // received confirm value
47909c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
47913deb3ec6SMatthias Ringwald 
4792192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4793192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4794192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4795192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4796192365feSMatthias Ringwald             }
4797192365feSMatthias Ringwald #endif
47983deb3ec6SMatthias Ringwald             // notify client to hide shown passkey
47993deb3ec6SMatthias Ringwald             if (setup->sm_stk_generation_method == PK_INIT_INPUT){
48005611a760SMatthias Ringwald                 sm_notify_client_base(SM_EVENT_PASSKEY_DISPLAY_CANCEL, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
48013deb3ec6SMatthias Ringwald             }
48023deb3ec6SMatthias Ringwald 
48033deb3ec6SMatthias Ringwald             // handle user cancel pairing?
48043deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_DECLINE){
4805f4935286SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_PASSKEY_ENTRY_FAILED);
48063deb3ec6SMatthias Ringwald                 break;
48073deb3ec6SMatthias Ringwald             }
48083deb3ec6SMatthias Ringwald 
48093deb3ec6SMatthias Ringwald             // wait for user action?
48103deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_PENDING){
48113deb3ec6SMatthias Ringwald                 sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
48123deb3ec6SMatthias Ringwald                 break;
48133deb3ec6SMatthias Ringwald             }
48143deb3ec6SMatthias Ringwald 
48153deb3ec6SMatthias Ringwald             // calculate and send local_confirm
4816f3582630SMatthias Ringwald             btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_random, 16, &sm_handle_random_result_ph2_random, (void *)(uintptr_t) sm_conn->sm_handle);
48173deb3ec6SMatthias Ringwald             break;
48183deb3ec6SMatthias Ringwald 
48193deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH2_W4_PAIRING_RANDOM:
48204c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
48213deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
48223deb3ec6SMatthias Ringwald                 break;;
48233deb3ec6SMatthias Ringwald             }
48243deb3ec6SMatthias Ringwald 
48253deb3ec6SMatthias Ringwald             // received random value
48269c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_random);
48273deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
48283deb3ec6SMatthias Ringwald             break;
482942134bc6SMatthias Ringwald #endif
48303deb3ec6SMatthias Ringwald 
4831672dc582SMatthias Ringwald         case SM_PH2_W4_CONNECTION_ENCRYPTED:
48323deb3ec6SMatthias Ringwald         case SM_PH3_RECEIVE_KEYS:
48334c1d1092SMatthias Ringwald             switch(sm_pdu_code){
48343deb3ec6SMatthias Ringwald                 case SM_CODE_ENCRYPTION_INFORMATION:
48353deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
48369c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_ltk);
48373deb3ec6SMatthias Ringwald                     break;
48383deb3ec6SMatthias Ringwald 
48393deb3ec6SMatthias Ringwald                 case SM_CODE_MASTER_IDENTIFICATION:
48403deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
4841f8fbdce0SMatthias Ringwald                     setup->sm_peer_ediv = little_endian_read_16(packet, 1);
48429c80e4ccSMatthias Ringwald                     reverse_64(&packet[3], setup->sm_peer_rand);
48433deb3ec6SMatthias Ringwald                     break;
48443deb3ec6SMatthias Ringwald 
48453deb3ec6SMatthias Ringwald                 case SM_CODE_IDENTITY_INFORMATION:
48463deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
48479c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_irk);
48483deb3ec6SMatthias Ringwald                     break;
48493deb3ec6SMatthias Ringwald 
48503deb3ec6SMatthias Ringwald                 case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
48513deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
48523deb3ec6SMatthias Ringwald                     setup->sm_peer_addr_type = packet[1];
4853724d70a2SMatthias Ringwald                     reverse_bd_addr(&packet[2], setup->sm_peer_address);
48543deb3ec6SMatthias Ringwald                     break;
48553deb3ec6SMatthias Ringwald 
48563deb3ec6SMatthias Ringwald                 case SM_CODE_SIGNING_INFORMATION:
48573deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
48589c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_csrk);
48593deb3ec6SMatthias Ringwald                     break;
48603deb3ec6SMatthias Ringwald                 default:
48613deb3ec6SMatthias Ringwald                     // Unexpected PDU
48623deb3ec6SMatthias Ringwald                     log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
48633deb3ec6SMatthias Ringwald                     break;
48643deb3ec6SMatthias Ringwald             }
48653deb3ec6SMatthias Ringwald             // done with key distribution?
486661d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
48673deb3ec6SMatthias Ringwald 
48683deb3ec6SMatthias Ringwald                 sm_key_distribution_handle_all_received(sm_conn);
48693deb3ec6SMatthias Ringwald 
487042134bc6SMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
48716f7422f1SMatthias Ringwald                     sm_key_distribution_complete_responder(sm_conn);
48723deb3ec6SMatthias Ringwald                 } else {
4873625f00b2SMatthias Ringwald                     if (setup->sm_use_secure_connections){
4874625f00b2SMatthias Ringwald                         sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
4875bbf8db22SMatthias Ringwald                     } else {
4876f3582630SMatthias Ringwald                         btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph3_random, (void *)(uintptr_t) sm_conn->sm_handle);
4877625f00b2SMatthias Ringwald                     }
48783deb3ec6SMatthias Ringwald                 }
48793deb3ec6SMatthias Ringwald             }
48803deb3ec6SMatthias Ringwald             break;
4881c18be159SMatthias Ringwald 
4882c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4883b322498eSMatthias Ringwald 
4884b322498eSMatthias Ringwald         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
4885b322498eSMatthias Ringwald             // GAP/DM/LEP/BI-02-C - reject CTKD if P-192 encryption is used
4886b322498eSMatthias Ringwald             if (sm_pdu_code == SM_CODE_PAIRING_REQUEST){
4887b322498eSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED);
4888b322498eSMatthias Ringwald             }
4889b322498eSMatthias Ringwald             break;
4890b322498eSMatthias Ringwald 
4891c18be159SMatthias Ringwald         case SM_BR_EDR_INITIATOR_W4_PAIRING_RESPONSE:
4892553c9408SMatthias Ringwald 
4893553c9408SMatthias Ringwald             // dedicated bonding complete
4894f82b8f4bSMatthias Ringwald             hci_dedicated_bonding_defer_disconnect(sm_conn->sm_handle, false);
4895553c9408SMatthias Ringwald 
4896c18be159SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RESPONSE){
4897c18be159SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4898c18be159SMatthias Ringwald                 break;
4899c18be159SMatthias Ringwald             }
4900c18be159SMatthias Ringwald             // store pairing response
4901c18be159SMatthias Ringwald             (void)memcpy(&setup->sm_s_pres, packet, sizeof(sm_pairing_packet_t));
4902c18be159SMatthias Ringwald 
4903c18be159SMatthias Ringwald             // validate encryption key size
4904afbd946dSMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(setup->sm_s_pres);
4905afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4906afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4907afbd946dSMatthias Ringwald                 break;
4908afbd946dSMatthias Ringwald             }
4909afbd946dSMatthias Ringwald             sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(max_encryption_key_size);
4910c18be159SMatthias Ringwald             // SC Only mandates 128 bit key size
4911c18be159SMatthias Ringwald             if (sm_sc_only_mode && (sm_conn->sm_actual_encryption_key_size < 16)) {
4912c18be159SMatthias Ringwald                 sm_conn->sm_actual_encryption_key_size  = 0;
4913c18be159SMatthias Ringwald             }
4914c18be159SMatthias Ringwald             if (sm_conn->sm_actual_encryption_key_size == 0){
4915c18be159SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_ENCRYPTION_KEY_SIZE);
4916c18be159SMatthias Ringwald                 break;
4917c18be159SMatthias Ringwald             }
4918c18be159SMatthias Ringwald 
4919c18be159SMatthias Ringwald             // prepare key exchange, LTK is derived locally
4920c18be159SMatthias Ringwald             sm_setup_key_distribution(sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres) & ~SM_KEYDIST_ENC_KEY,
4921c18be159SMatthias Ringwald                                       sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres) & ~SM_KEYDIST_ENC_KEY);
4922c18be159SMatthias Ringwald 
4923c18be159SMatthias Ringwald             // skip receive if there are none
492461d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
4925c18be159SMatthias Ringwald                 // distribute keys in run handles 'no keys to send'
4926c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
4927c18be159SMatthias Ringwald             } else {
4928c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_RECEIVE_KEYS;
4929c18be159SMatthias Ringwald             }
4930c18be159SMatthias Ringwald             break;
4931c18be159SMatthias Ringwald 
4932c18be159SMatthias Ringwald         case SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST:
4933c18be159SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
4934c18be159SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4935c18be159SMatthias Ringwald                 break;
4936c18be159SMatthias Ringwald             }
4937afbd946dSMatthias Ringwald 
4938c18be159SMatthias Ringwald             // store pairing request
4939c18be159SMatthias Ringwald             (void)memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
4940afbd946dSMatthias Ringwald 
4941c18be159SMatthias Ringwald             // validate encryption key size
4942f5217d52SMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(sm_conn->sm_m_preq);
4943afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4944afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4945afbd946dSMatthias Ringwald                 break;
4946afbd946dSMatthias Ringwald             }
4947afbd946dSMatthias Ringwald             sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(max_encryption_key_size);
4948c18be159SMatthias Ringwald             // SC Only mandates 128 bit key size
4949c18be159SMatthias Ringwald             if (sm_sc_only_mode && (sm_conn->sm_actual_encryption_key_size < 16)) {
4950c18be159SMatthias Ringwald                 sm_conn->sm_actual_encryption_key_size  = 0;
4951c18be159SMatthias Ringwald             }
4952c18be159SMatthias Ringwald             if (sm_conn->sm_actual_encryption_key_size == 0){
4953c18be159SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_ENCRYPTION_KEY_SIZE);
4954c18be159SMatthias Ringwald                 break;
4955c18be159SMatthias Ringwald             }
4956c18be159SMatthias Ringwald             // trigger response
49576a718a5eSMatthias Ringwald             if (sm_ctkd_from_classic(sm_conn)){
4958c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED;
49596a718a5eSMatthias Ringwald             } else {
49606a718a5eSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED);
49616a718a5eSMatthias Ringwald             }
4962c18be159SMatthias Ringwald             break;
4963c18be159SMatthias Ringwald 
4964c18be159SMatthias Ringwald         case SM_BR_EDR_RECEIVE_KEYS:
4965c18be159SMatthias Ringwald             switch(sm_pdu_code){
4966c18be159SMatthias Ringwald                 case SM_CODE_IDENTITY_INFORMATION:
4967c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
4968c18be159SMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_irk);
4969c18be159SMatthias Ringwald                     break;
4970c18be159SMatthias Ringwald                 case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
4971c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
4972c18be159SMatthias Ringwald                     setup->sm_peer_addr_type = packet[1];
4973c18be159SMatthias Ringwald                     reverse_bd_addr(&packet[2], setup->sm_peer_address);
4974c18be159SMatthias Ringwald                     break;
4975c18be159SMatthias Ringwald                 case SM_CODE_SIGNING_INFORMATION:
4976c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
4977c18be159SMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_csrk);
4978c18be159SMatthias Ringwald                     break;
4979c18be159SMatthias Ringwald                 default:
4980c18be159SMatthias Ringwald                     // Unexpected PDU
4981c18be159SMatthias Ringwald                     log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
4982c18be159SMatthias Ringwald                     break;
4983c18be159SMatthias Ringwald             }
4984c18be159SMatthias Ringwald 
4985c18be159SMatthias Ringwald             // all keys received
498661d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
4987c18be159SMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
4988c18be159SMatthias Ringwald                     // responder -> keys exchanged, derive LE LTK
4989c18be159SMatthias Ringwald                     sm_ctkd_start_from_br_edr(sm_conn);
4990c18be159SMatthias Ringwald                 } else {
4991c18be159SMatthias Ringwald                     // initiator -> send our keys if any
4992c18be159SMatthias Ringwald                     sm_conn->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
4993c18be159SMatthias Ringwald                 }
4994c18be159SMatthias Ringwald             }
4995c18be159SMatthias Ringwald             break;
4996c18be159SMatthias Ringwald #endif
4997c18be159SMatthias Ringwald 
49983deb3ec6SMatthias Ringwald         default:
49993deb3ec6SMatthias Ringwald             // Unexpected PDU
50003deb3ec6SMatthias Ringwald             log_info("Unexpected PDU %u in state %u", packet[0], sm_conn->sm_engine_state);
50012d095694SMatthias Ringwald             sm_pdu_received_in_wrong_state(sm_conn);
50023deb3ec6SMatthias Ringwald             break;
50033deb3ec6SMatthias Ringwald     }
50043deb3ec6SMatthias Ringwald 
500570b44dd4SMatthias Ringwald     // try to send next pdu
500670b44dd4SMatthias Ringwald     sm_trigger_run();
50073deb3ec6SMatthias Ringwald }
50083deb3ec6SMatthias Ringwald 
sm_channel_handler(uint8_t packet_type,hci_con_handle_t con_handle,uint8_t * packet,uint16_t size)500973970ae5SMatthias Ringwald static void sm_channel_handler(uint8_t packet_type, hci_con_handle_t con_handle, uint8_t *packet, uint16_t size){
501073970ae5SMatthias Ringwald 
501173970ae5SMatthias Ringwald     if ((packet_type == HCI_EVENT_PACKET) && (packet[0] == L2CAP_EVENT_CAN_SEND_NOW)){
501273970ae5SMatthias Ringwald         sm_run();
501373970ae5SMatthias Ringwald     }
501473970ae5SMatthias Ringwald 
501573970ae5SMatthias Ringwald     uint8_t sm_pdu_code = sm_pdu_validate_and_get_opcode(packet_type, packet, size);
501673970ae5SMatthias Ringwald     if (sm_pdu_code == 0) return;
501773970ae5SMatthias Ringwald 
501873970ae5SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
501973970ae5SMatthias Ringwald     if (!sm_conn) return;
502073970ae5SMatthias Ringwald 
502173970ae5SMatthias Ringwald     if (sm_pdu_code == SM_CODE_PAIRING_FAILED){
502273970ae5SMatthias Ringwald         sm_reencryption_complete(sm_conn, ERROR_CODE_AUTHENTICATION_FAILURE);
502373970ae5SMatthias Ringwald         sm_pairing_complete(sm_conn, ERROR_CODE_AUTHENTICATION_FAILURE, packet[1]);
502473970ae5SMatthias Ringwald         sm_done_for_handle(con_handle);
502573970ae5SMatthias Ringwald         sm_conn->sm_engine_state = sm_conn->sm_role ? SM_RESPONDER_IDLE : SM_INITIATOR_CONNECTED;
502673970ae5SMatthias Ringwald         return;
502773970ae5SMatthias Ringwald     }
502873970ae5SMatthias Ringwald 
502973970ae5SMatthias Ringwald     if (sm_pdu_code == SM_CODE_KEYPRESS_NOTIFICATION){
503073970ae5SMatthias Ringwald         uint8_t buffer[5];
503173970ae5SMatthias Ringwald         buffer[0] = SM_EVENT_KEYPRESS_NOTIFICATION;
503273970ae5SMatthias Ringwald         buffer[1] = 3;
503373970ae5SMatthias Ringwald         little_endian_store_16(buffer, 2, con_handle);
503473970ae5SMatthias Ringwald         buffer[4] = packet[1];
503573970ae5SMatthias Ringwald         sm_dispatch_event(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer));
503673970ae5SMatthias Ringwald         return;
503773970ae5SMatthias Ringwald     }
503873970ae5SMatthias Ringwald 
503973970ae5SMatthias Ringwald     sm_pdu_handler(sm_conn, sm_pdu_code, packet);
504073970ae5SMatthias Ringwald }
504173970ae5SMatthias Ringwald 
50423deb3ec6SMatthias Ringwald // Security Manager Client API
sm_register_oob_data_callback(int (* get_oob_data_callback)(uint8_t address_type,bd_addr_t addr,uint8_t * oob_data))5043a680ba6bSMatthias Ringwald void sm_register_oob_data_callback( int (*get_oob_data_callback)(uint8_t address_type, bd_addr_t addr, uint8_t * oob_data)){
50443deb3ec6SMatthias Ringwald     sm_get_oob_data = get_oob_data_callback;
50453deb3ec6SMatthias Ringwald }
50463deb3ec6SMatthias Ringwald 
sm_register_sc_oob_data_callback(int (* get_sc_oob_data_callback)(uint8_t address_type,bd_addr_t addr,uint8_t * oob_sc_peer_confirm,uint8_t * oob_sc_peer_random))50474acf7b7bSMatthias Ringwald void sm_register_sc_oob_data_callback( int (*get_sc_oob_data_callback)(uint8_t address_type, bd_addr_t addr, uint8_t * oob_sc_peer_confirm, uint8_t * oob_sc_peer_random)){
5048a680ba6bSMatthias Ringwald     sm_get_sc_oob_data = get_sc_oob_data_callback;
5049a680ba6bSMatthias Ringwald }
5050a680ba6bSMatthias Ringwald 
sm_register_ltk_callback(bool (* get_ltk_callback)(hci_con_handle_t con_handle,uint8_t address_type,bd_addr_t addr,uint8_t * ltk))5051b96d60a6SMatthias Ringwald void sm_register_ltk_callback( bool (*get_ltk_callback)(hci_con_handle_t con_handle, uint8_t address_type, bd_addr_t addr, uint8_t * ltk)){
5052b96d60a6SMatthias Ringwald     sm_get_ltk_callback = get_ltk_callback;
5053b96d60a6SMatthias Ringwald }
5054b96d60a6SMatthias Ringwald 
sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler)505589a78d34SMatthias Ringwald void sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler){
505689a78d34SMatthias Ringwald     btstack_linked_list_add_tail(&sm_event_handlers, (btstack_linked_item_t*) callback_handler);
505789a78d34SMatthias Ringwald }
505889a78d34SMatthias Ringwald 
sm_remove_event_handler(btstack_packet_callback_registration_t * callback_handler)505967f708e0SMatthias Ringwald void sm_remove_event_handler(btstack_packet_callback_registration_t * callback_handler){
506067f708e0SMatthias Ringwald     btstack_linked_list_remove(&sm_event_handlers, (btstack_linked_item_t*) callback_handler);
506167f708e0SMatthias Ringwald }
506267f708e0SMatthias Ringwald 
sm_set_accepted_stk_generation_methods(uint8_t accepted_stk_generation_methods)50633deb3ec6SMatthias Ringwald void sm_set_accepted_stk_generation_methods(uint8_t accepted_stk_generation_methods){
50643deb3ec6SMatthias Ringwald     sm_accepted_stk_generation_methods = accepted_stk_generation_methods;
50653deb3ec6SMatthias Ringwald }
50663deb3ec6SMatthias Ringwald 
sm_set_encryption_key_size_range(uint8_t min_size,uint8_t max_size)50673deb3ec6SMatthias Ringwald void sm_set_encryption_key_size_range(uint8_t min_size, uint8_t max_size){
50683deb3ec6SMatthias Ringwald 	sm_min_encryption_key_size = min_size;
50693deb3ec6SMatthias Ringwald 	sm_max_encryption_key_size = max_size;
50703deb3ec6SMatthias Ringwald }
50713deb3ec6SMatthias Ringwald 
sm_set_authentication_requirements(uint8_t auth_req)50723deb3ec6SMatthias Ringwald void sm_set_authentication_requirements(uint8_t auth_req){
507398d95509SMatthias Ringwald #ifndef ENABLE_LE_SECURE_CONNECTIONS
507498d95509SMatthias Ringwald     if (auth_req & SM_AUTHREQ_SECURE_CONNECTION){
507598d95509SMatthias Ringwald         log_error("ENABLE_LE_SECURE_CONNECTIONS not defined, but requested by app. Dropping SC flag");
507698d95509SMatthias Ringwald         auth_req &= ~SM_AUTHREQ_SECURE_CONNECTION;
507798d95509SMatthias Ringwald     }
507898d95509SMatthias Ringwald #endif
50793deb3ec6SMatthias Ringwald     sm_auth_req = auth_req;
50803deb3ec6SMatthias Ringwald }
50813deb3ec6SMatthias Ringwald 
sm_set_io_capabilities(io_capability_t io_capability)50823deb3ec6SMatthias Ringwald void sm_set_io_capabilities(io_capability_t io_capability){
50833deb3ec6SMatthias Ringwald     sm_io_capabilities = io_capability;
50843deb3ec6SMatthias Ringwald }
50853deb3ec6SMatthias Ringwald 
508642134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
sm_set_request_security(bool enable)5087728f6757SMatthias Ringwald void sm_set_request_security(bool enable){
50883deb3ec6SMatthias Ringwald     sm_slave_request_security = enable;
50893deb3ec6SMatthias Ringwald }
509042134bc6SMatthias Ringwald #endif
50913deb3ec6SMatthias Ringwald 
sm_set_er(sm_key_t er)50923deb3ec6SMatthias Ringwald void sm_set_er(sm_key_t er){
50936535961aSMatthias Ringwald     (void)memcpy(sm_persistent_er, er, 16);
50943deb3ec6SMatthias Ringwald }
50953deb3ec6SMatthias Ringwald 
sm_set_ir(sm_key_t ir)50963deb3ec6SMatthias Ringwald void sm_set_ir(sm_key_t ir){
50976535961aSMatthias Ringwald     (void)memcpy(sm_persistent_ir, ir, 16);
50983deb3ec6SMatthias Ringwald }
50993deb3ec6SMatthias Ringwald 
51003deb3ec6SMatthias Ringwald // Testing support only
sm_test_set_irk(sm_key_t irk)51013deb3ec6SMatthias Ringwald void sm_test_set_irk(sm_key_t irk){
51026535961aSMatthias Ringwald     (void)memcpy(sm_persistent_irk, irk, 16);
5103103fa6b0SMatthias Ringwald     dkg_state = DKG_CALC_DHK;
5104841468bbSMatthias Ringwald     test_use_fixed_local_irk = true;
51053deb3ec6SMatthias Ringwald }
51063deb3ec6SMatthias Ringwald 
sm_test_use_fixed_local_csrk(void)51073deb3ec6SMatthias Ringwald void sm_test_use_fixed_local_csrk(void){
5108841468bbSMatthias Ringwald     test_use_fixed_local_csrk = true;
51093deb3ec6SMatthias Ringwald }
51103deb3ec6SMatthias Ringwald 
5111d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_ec_generated(void * arg)5112d1a1f6a4SMatthias Ringwald static void sm_ec_generated(void * arg){
5113d1a1f6a4SMatthias Ringwald     UNUSED(arg);
5114d1a1f6a4SMatthias Ringwald     ec_key_generation_state = EC_KEY_GENERATION_DONE;
511534b6528fSMatthias Ringwald     // trigger pairing if pending for ec key
511670b44dd4SMatthias Ringwald     sm_trigger_run();
5117d1a1f6a4SMatthias Ringwald }
sm_ec_generate_new_key(void)5118674e5b4aSMatthias Ringwald static void sm_ec_generate_new_key(void) {
511934b6528fSMatthias Ringwald     log_info("sm: generate new ec key");
5120db88441fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS_DEBUG_KEY
5121db88441fSMatthias Ringwald     // LE Secure Connections Debug Key
5122db88441fSMatthias Ringwald     const uint8_t debug_key_public[64] = {
5123db88441fSMatthias Ringwald         0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c, 0x5e, 0x2c, 0x83, 0xa7, 0xe9, 0xf9, 0xa5, 0xb9,
5124db88441fSMatthias Ringwald         0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb, 0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6,
5125db88441fSMatthias Ringwald         0xdc, 0x80, 0x9c, 0x49, 0x65, 0x2a, 0xeb, 0x6d, 0x63, 0x32, 0x9a, 0xbf, 0x5a, 0x52, 0x15, 0x5c,
5126db88441fSMatthias Ringwald         0x76, 0x63, 0x45, 0xc2, 0x8f, 0xed, 0x30, 0x24, 0x74, 0x1c, 0x8e, 0xd0, 0x15, 0x89, 0xd2, 0x8b
5127db88441fSMatthias Ringwald     };
5128db88441fSMatthias Ringwald     const uint8_t debug_key_private[32] = {
5129db88441fSMatthias Ringwald         0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3, 0xe3, 0xd2, 0x10, 0x3f, 0x50,
5130db88441fSMatthias Ringwald         0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99, 0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd
5131db88441fSMatthias Ringwald     };
5132db88441fSMatthias Ringwald     if (sm_sc_debug_keys_enabled) {
5133db88441fSMatthias Ringwald         memcpy(ec_q, debug_key_public, 64);
5134db88441fSMatthias Ringwald         btstack_crypto_ecc_p256_set_key(debug_key_public, debug_key_private);
5135db88441fSMatthias Ringwald         ec_key_generation_state = EC_KEY_GENERATION_DONE;
5136db88441fSMatthias Ringwald     } else
5137db88441fSMatthias Ringwald #endif
5138db88441fSMatthias Ringwald     {
5139674e5b4aSMatthias Ringwald         ec_key_generation_state = EC_KEY_GENERATION_ACTIVE;
5140674e5b4aSMatthias Ringwald         btstack_crypto_ecc_p256_generate_key(&sm_crypto_ecc_p256_request, ec_q, &sm_ec_generated, NULL);
5141674e5b4aSMatthias Ringwald     }
5142db88441fSMatthias Ringwald }
5143d1a1f6a4SMatthias Ringwald #endif
5144d1a1f6a4SMatthias Ringwald 
5145192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
sm_test_set_pairing_failure(int reason)5146192365feSMatthias Ringwald void sm_test_set_pairing_failure(int reason){
5147192365feSMatthias Ringwald     test_pairing_failure = reason;
5148192365feSMatthias Ringwald }
5149192365feSMatthias Ringwald #endif
5150192365feSMatthias Ringwald 
sm_state_reset(void)51517887cd92SMatthias Ringwald static void sm_state_reset(void) {
51527f775357SMatthias Ringwald #ifdef USE_CMAC_ENGINE
51537f775357SMatthias Ringwald     sm_cmac_active  = 0;
51547f775357SMatthias Ringwald #endif
51557f775357SMatthias Ringwald     dkg_state = DKG_W4_WORKING;
51567f775357SMatthias Ringwald     rau_state = RAU_IDLE;
51577f775357SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
51587f775357SMatthias Ringwald     sm_address_resolution_test = -1;    // no private address to resolve yet
51597f775357SMatthias Ringwald     sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
51607f775357SMatthias Ringwald     sm_address_resolution_general_queue = NULL;
51617f775357SMatthias Ringwald     sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
5162cbdd51cfSMatthias Ringwald     sm_persistent_keys_random_active = false;
51637f775357SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
516415211b85SMatthias Ringwald     ec_key_generation_state = EC_KEY_GENERATION_IDLE;
51657f775357SMatthias Ringwald #endif
51667f775357SMatthias Ringwald }
51677f775357SMatthias Ringwald 
sm_init(void)51683deb3ec6SMatthias Ringwald void sm_init(void){
51692d2d4d3cSMatthias Ringwald 
51702d2d4d3cSMatthias Ringwald     if (sm_initialized) return;
51712d2d4d3cSMatthias Ringwald 
5172899e6e02SMatthias Ringwald     // set default ER and IR values (should be unique - set by app or sm later using TLV)
5173899e6e02SMatthias Ringwald     sm_er_ir_set_default();
5174899e6e02SMatthias Ringwald 
51753deb3ec6SMatthias Ringwald     // defaults
51763deb3ec6SMatthias Ringwald     sm_accepted_stk_generation_methods = SM_STK_GENERATION_METHOD_JUST_WORKS
51773deb3ec6SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_OOB
5178b4343428SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_PASSKEY
5179b4343428SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON;
5180b4343428SMatthias Ringwald 
51813deb3ec6SMatthias Ringwald     sm_max_encryption_key_size = 16;
51823deb3ec6SMatthias Ringwald     sm_min_encryption_key_size = 7;
51833deb3ec6SMatthias Ringwald 
51845ce1359eSMatthias Ringwald     sm_fixed_passkey_in_display_role = 0xffffffffU;
51851979f09cSMatthias Ringwald     sm_reconstruct_ltk_without_le_device_db_entry = true;
5186caf15bf3SMatthias Ringwald 
51873deb3ec6SMatthias Ringwald     gap_random_adress_update_period = 15 * 60 * 1000L;
51883deb3ec6SMatthias Ringwald 
5189841468bbSMatthias Ringwald     test_use_fixed_local_csrk = false;
51903deb3ec6SMatthias Ringwald 
51917f775357SMatthias Ringwald     // other
519284c0c5c7SMatthias Ringwald     btstack_run_loop_set_timer_handler(&sm_run_timer, &sm_run_timer_handler);
519384c0c5c7SMatthias Ringwald 
5194a036ae12SMatthias Ringwald     // register for HCI Events
5195e03e489aSMatthias Ringwald     hci_event_callback_registration.callback = &sm_event_packet_handler;
5196e03e489aSMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
5197e03e489aSMatthias Ringwald 
5198bad51150SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
5199a036ae12SMatthias Ringwald     // register for L2CAP events
5200a036ae12SMatthias Ringwald     l2cap_event_callback_registration.callback = &sm_event_packet_handler;
5201a036ae12SMatthias Ringwald     l2cap_add_event_handler(&l2cap_event_callback_registration);
5202bad51150SMatthias Ringwald #endif
5203a036ae12SMatthias Ringwald 
5204d1a1f6a4SMatthias Ringwald     //
5205d1a1f6a4SMatthias Ringwald     btstack_crypto_init();
5206d1a1f6a4SMatthias Ringwald 
520751bd74d1SMatthias Ringwald     // init le_device_db
520851bd74d1SMatthias Ringwald     le_device_db_init();
520951bd74d1SMatthias Ringwald 
5210b170b20fSMatthias Ringwald     // and L2CAP PDUs + L2CAP_EVENT_CAN_SEND_NOW
521173970ae5SMatthias Ringwald     l2cap_register_fixed_channel(sm_channel_handler, L2CAP_CID_SECURITY_MANAGER_PROTOCOL);
5212384eabd3SMatthias Ringwald #ifdef ENABLE_CLASSIC
521373970ae5SMatthias Ringwald     l2cap_register_fixed_channel(sm_channel_handler, L2CAP_CID_BR_EDR_SECURITY_MANAGER);
5214384eabd3SMatthias Ringwald #endif
521527c32905SMatthias Ringwald 
52167f775357SMatthias Ringwald     // state
52177f775357SMatthias Ringwald     sm_state_reset();
52182d2d4d3cSMatthias Ringwald 
52192d2d4d3cSMatthias Ringwald     sm_initialized = true;
52203deb3ec6SMatthias Ringwald }
52213deb3ec6SMatthias Ringwald 
sm_deinit(void)522215537ea4SMatthias Ringwald void sm_deinit(void){
522315537ea4SMatthias Ringwald     sm_initialized = false;
522415537ea4SMatthias Ringwald     btstack_run_loop_remove_timer(&sm_run_timer);
522592f8d6b6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined (ENABLE_LE_SECURE_CONNECTION_DEBUG_KEY)
5226db88441fSMatthias Ringwald     sm_sc_debug_keys_enabled = false;
5227db88441fSMatthias Ringwald #endif
522815537ea4SMatthias Ringwald }
522915537ea4SMatthias Ringwald 
sm_use_fixed_passkey_in_display_role(uint32_t passkey)52304b8c611fSMatthias Ringwald void sm_use_fixed_passkey_in_display_role(uint32_t passkey){
52314b8c611fSMatthias Ringwald     sm_fixed_passkey_in_display_role = passkey;
5232caf15bf3SMatthias Ringwald }
5233caf15bf3SMatthias Ringwald 
sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow)52346c39055aSMatthias Ringwald void sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow){
52351979f09cSMatthias Ringwald     sm_reconstruct_ltk_without_le_device_db_entry = allow != 0;
52366c39055aSMatthias Ringwald }
52376c39055aSMatthias Ringwald 
sm_get_connection_for_handle(hci_con_handle_t con_handle)5238711e6c80SMatthias Ringwald static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle){
5239711e6c80SMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(con_handle);
52403deb3ec6SMatthias Ringwald     if (!hci_con) return NULL;
52413deb3ec6SMatthias Ringwald     return &hci_con->sm_connection;
52423deb3ec6SMatthias Ringwald }
52433deb3ec6SMatthias Ringwald 
sm_cache_ltk(sm_connection_t * connection,const sm_key_t ltk)5244916ea5b2SMatthias Ringwald static void sm_cache_ltk(sm_connection_t * connection, const sm_key_t ltk){
5245916ea5b2SMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(connection->sm_handle);
5246916ea5b2SMatthias Ringwald     btstack_assert(hci_con != NULL);
5247916ea5b2SMatthias Ringwald     memcpy(hci_con->link_key, ltk, 16);
5248f728bb7bSMatthias Ringwald     hci_con->link_key_type = COMBINATION_KEY;
5249916ea5b2SMatthias Ringwald }
5250916ea5b2SMatthias Ringwald 
525177e2e5edSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
sm_get_connection_for_bd_addr_and_type(bd_addr_t address,bd_addr_type_t addr_type)525277e2e5edSMatthias Ringwald static sm_connection_t * sm_get_connection_for_bd_addr_and_type(bd_addr_t address, bd_addr_type_t addr_type){
525377e2e5edSMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_bd_addr_and_type(address, addr_type);
525477e2e5edSMatthias Ringwald     if (!hci_con) return NULL;
525577e2e5edSMatthias Ringwald     return &hci_con->sm_connection;
525677e2e5edSMatthias Ringwald }
525777e2e5edSMatthias Ringwald #endif
525877e2e5edSMatthias Ringwald 
52596bc3aba4SMatthias Ringwald // @deprecated: map onto sm_request_pairing
sm_send_security_request(hci_con_handle_t con_handle)5260711e6c80SMatthias Ringwald void sm_send_security_request(hci_con_handle_t con_handle){
5261711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52623deb3ec6SMatthias Ringwald     if (!sm_conn) return;
52636bc3aba4SMatthias Ringwald     if (!IS_RESPONDER(sm_conn->sm_role)) return;
52646bc3aba4SMatthias Ringwald     sm_request_pairing(con_handle);
52653deb3ec6SMatthias Ringwald }
52663deb3ec6SMatthias Ringwald 
52673deb3ec6SMatthias Ringwald // request pairing
sm_request_pairing(hci_con_handle_t con_handle)5268711e6c80SMatthias Ringwald void sm_request_pairing(hci_con_handle_t con_handle){
5269711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52703deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52713deb3ec6SMatthias Ringwald 
52727af5dcd5SMatthias Ringwald     bool have_ltk;
52737af5dcd5SMatthias Ringwald     uint8_t ltk[16];
52742d68601cSMatthias Ringwald     bool auth_required;
52752d68601cSMatthias Ringwald     int authenticated;
52762d68601cSMatthias Ringwald     bool trigger_reencryption;
52773deb3ec6SMatthias Ringwald     log_info("sm_request_pairing in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state);
527842134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
527924c20dc4SMatthias Ringwald         switch (sm_conn->sm_engine_state){
528024c20dc4SMatthias Ringwald             case SM_GENERAL_IDLE:
528124c20dc4SMatthias Ringwald             case SM_RESPONDER_IDLE:
52827af5dcd5SMatthias Ringwald                 switch (sm_conn->sm_irk_lookup_state){
52837af5dcd5SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
52847af5dcd5SMatthias Ringwald                         le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
52857af5dcd5SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
52867af5dcd5SMatthias Ringwald                         log_info("have ltk %u", have_ltk);
52877af5dcd5SMatthias Ringwald                         if (have_ltk){
52885f3874afSMatthias Ringwald                             sm_conn->sm_pairing_requested = true;
528924c20dc4SMatthias Ringwald                             sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
52907af5dcd5SMatthias Ringwald                             sm_reencryption_started(sm_conn);
52917af5dcd5SMatthias Ringwald                             break;
52927af5dcd5SMatthias Ringwald                         }
52937af5dcd5SMatthias Ringwald                         /* fall through */
52947af5dcd5SMatthias Ringwald 
52957af5dcd5SMatthias Ringwald                     case IRK_LOOKUP_FAILED:
52965f3874afSMatthias Ringwald                         sm_conn->sm_pairing_requested = true;
52977af5dcd5SMatthias Ringwald                         sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
52987af5dcd5SMatthias Ringwald                         sm_pairing_started(sm_conn);
52997af5dcd5SMatthias Ringwald                         break;
53007af5dcd5SMatthias Ringwald                     default:
53017af5dcd5SMatthias Ringwald                         log_info("irk lookup pending");
53025f3874afSMatthias Ringwald                         sm_conn->sm_pairing_requested = true;
53037af5dcd5SMatthias Ringwald                         break;
53047af5dcd5SMatthias Ringwald                 }
530524c20dc4SMatthias Ringwald                 break;
530624c20dc4SMatthias Ringwald             default:
530724c20dc4SMatthias Ringwald                 break;
530824c20dc4SMatthias Ringwald         }
53093deb3ec6SMatthias Ringwald     } else {
53103deb3ec6SMatthias Ringwald         // used as a trigger to start central/master/initiator security procedures
5311175b7faaSMatthias Ringwald         switch (sm_conn->sm_engine_state){
5312175b7faaSMatthias Ringwald             case SM_INITIATOR_CONNECTED:
53133deb3ec6SMatthias Ringwald                 switch (sm_conn->sm_irk_lookup_state){
53143deb3ec6SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
53152d68601cSMatthias Ringwald                         le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, &authenticated, NULL, NULL);
5316f53ec649SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
53172d68601cSMatthias Ringwald                         auth_required = sm_auth_req & SM_AUTHREQ_MITM_PROTECTION;
53182d68601cSMatthias Ringwald                         // re-encrypt is sufficient if we have ltk and that is either already authenticated or we don't require authentication
53192d68601cSMatthias Ringwald                         trigger_reencryption = have_ltk && ((authenticated != 0) || (auth_required == false));
53202d68601cSMatthias Ringwald                         log_info("have ltk %u, authenticated %u, auth required %u => reencrypt %u", have_ltk, authenticated, auth_required, trigger_reencryption);
53212d68601cSMatthias Ringwald                         if (trigger_reencryption){
53225f3874afSMatthias Ringwald                             sm_conn->sm_pairing_requested = true;
53235567aa60SMatthias Ringwald                             sm_conn->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
5324c245ca32SMatthias Ringwald                             break;
5325f53ec649SMatthias Ringwald                         }
5326cf373d3aSMatthias Ringwald                         /* fall through */
5327c245ca32SMatthias Ringwald 
532834c39fbdSMatthias Ringwald                     case IRK_LOOKUP_FAILED:
53293deb3ec6SMatthias Ringwald                         sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
53303deb3ec6SMatthias Ringwald                         break;
53313deb3ec6SMatthias Ringwald                     default:
5332d1a1f6a4SMatthias Ringwald                         log_info("irk lookup pending");
53335f3874afSMatthias Ringwald                         sm_conn->sm_pairing_requested = true;
53343deb3ec6SMatthias Ringwald                         break;
53353deb3ec6SMatthias Ringwald                 }
5336175b7faaSMatthias Ringwald                 break;
5337cb6d7eb0SMatthias Ringwald             case SM_GENERAL_REENCRYPTION_FAILED:
5338cb6d7eb0SMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
5339cb6d7eb0SMatthias Ringwald                 break;
5340175b7faaSMatthias Ringwald             case SM_GENERAL_IDLE:
53415f3874afSMatthias Ringwald                 sm_conn->sm_pairing_requested = true;
5342175b7faaSMatthias Ringwald                 break;
5343175b7faaSMatthias Ringwald             default:
5344175b7faaSMatthias Ringwald                 break;
53453deb3ec6SMatthias Ringwald         }
53463deb3ec6SMatthias Ringwald     }
534770b44dd4SMatthias Ringwald     sm_trigger_run();
53483deb3ec6SMatthias Ringwald }
53493deb3ec6SMatthias Ringwald 
53503deb3ec6SMatthias Ringwald // called by client app on authorization request
sm_authorization_decline(hci_con_handle_t con_handle)5351711e6c80SMatthias Ringwald void sm_authorization_decline(hci_con_handle_t con_handle){
5352711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53533deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53543deb3ec6SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_DECLINED;
5355589f5a99SMatthias Ringwald     sm_notify_client_status(SM_EVENT_AUTHORIZATION_RESULT, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, 0);
53563deb3ec6SMatthias Ringwald }
53573deb3ec6SMatthias Ringwald 
sm_authorization_grant(hci_con_handle_t con_handle)5358711e6c80SMatthias Ringwald void sm_authorization_grant(hci_con_handle_t con_handle){
5359711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53603deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53613deb3ec6SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_GRANTED;
5362589f5a99SMatthias Ringwald     sm_notify_client_status(SM_EVENT_AUTHORIZATION_RESULT, sm_conn->sm_handle, sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, 1);
53633deb3ec6SMatthias Ringwald }
53643deb3ec6SMatthias Ringwald 
53653deb3ec6SMatthias Ringwald // GAP Bonding API
53663deb3ec6SMatthias Ringwald 
sm_bonding_decline(hci_con_handle_t con_handle)5367711e6c80SMatthias Ringwald void sm_bonding_decline(hci_con_handle_t con_handle){
5368711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53693deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53703deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_DECLINE;
53710af429c6SMatthias Ringwald     log_info("decline, state %u", sm_conn->sm_engine_state);
53720af429c6SMatthias Ringwald     switch(sm_conn->sm_engine_state){
53730af429c6SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
53740af429c6SMatthias Ringwald         case SM_SC_W4_USER_RESPONSE:
53750af429c6SMatthias Ringwald         case SM_SC_W4_CONFIRMATION:
53760af429c6SMatthias Ringwald         case SM_SC_W4_PUBLIC_KEY_COMMAND:
53770af429c6SMatthias Ringwald #endif
53780af429c6SMatthias Ringwald         case SM_PH1_W4_USER_RESPONSE:
5379de2fd182SMatthias Ringwald             switch (setup->sm_stk_generation_method){
5380de2fd182SMatthias Ringwald                 case PK_RESP_INPUT:
5381de2fd182SMatthias Ringwald                 case PK_INIT_INPUT:
538247fb4255SMatthias Ringwald                 case PK_BOTH_INPUT:
53830af429c6SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_PASSKEY_ENTRY_FAILED);
5384de2fd182SMatthias Ringwald                     break;
538547fb4255SMatthias Ringwald                 case NUMERIC_COMPARISON:
5386de2fd182SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_NUMERIC_COMPARISON_FAILED);
5387de2fd182SMatthias Ringwald                     break;
5388de2fd182SMatthias Ringwald                 case JUST_WORKS:
5389de2fd182SMatthias Ringwald                 case OOB:
5390de2fd182SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_UNSPECIFIED_REASON);
5391de2fd182SMatthias Ringwald                     break;
53927bbeb3adSMilanka Ringwald                 default:
53937bbeb3adSMilanka Ringwald                     btstack_assert(false);
53947bbeb3adSMilanka Ringwald                     break;
5395de2fd182SMatthias Ringwald             }
53960af429c6SMatthias Ringwald             break;
53970af429c6SMatthias Ringwald         default:
53980af429c6SMatthias Ringwald             break;
53993deb3ec6SMatthias Ringwald     }
540070b44dd4SMatthias Ringwald     sm_trigger_run();
54013deb3ec6SMatthias Ringwald }
54023deb3ec6SMatthias Ringwald 
sm_just_works_confirm(hci_con_handle_t con_handle)5403711e6c80SMatthias Ringwald void sm_just_works_confirm(hci_con_handle_t con_handle){
5404711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
54053deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
54063deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_CONFIRM;
54073deb3ec6SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_PH1_W4_USER_RESPONSE){
5408136d331aSMatthias Ringwald         if (setup->sm_use_secure_connections){
5409c6b7cbd9SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
5410bbf8db22SMatthias Ringwald         } else {
5411f3582630SMatthias Ringwald             btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_random, 16, &sm_handle_random_result_ph2_random, (void *)(uintptr_t) sm_conn->sm_handle);
5412136d331aSMatthias Ringwald         }
54133deb3ec6SMatthias Ringwald     }
54140346c37cSMatthias Ringwald 
54150346c37cSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
5416c6b7cbd9SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_USER_RESPONSE){
5417dc300847SMatthias Ringwald         sm_sc_prepare_dhkey_check(sm_conn);
5418446a8c36SMatthias Ringwald     }
54190346c37cSMatthias Ringwald #endif
54200346c37cSMatthias Ringwald 
542170b44dd4SMatthias Ringwald     sm_trigger_run();
54223deb3ec6SMatthias Ringwald }
54233deb3ec6SMatthias Ringwald 
sm_numeric_comparison_confirm(hci_con_handle_t con_handle)5424c8c46d51SMatthias Ringwald void sm_numeric_comparison_confirm(hci_con_handle_t con_handle){
5425c8c46d51SMatthias Ringwald     // for now, it's the same
5426c8c46d51SMatthias Ringwald     sm_just_works_confirm(con_handle);
5427c8c46d51SMatthias Ringwald }
5428c8c46d51SMatthias Ringwald 
sm_passkey_input(hci_con_handle_t con_handle,uint32_t passkey)5429711e6c80SMatthias Ringwald void sm_passkey_input(hci_con_handle_t con_handle, uint32_t passkey){
5430711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
54313deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
54323deb3ec6SMatthias Ringwald     sm_reset_tk();
5433f8fbdce0SMatthias Ringwald     big_endian_store_32(setup->sm_tk, 12, passkey);
54343deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_PASSKEY;
54353deb3ec6SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_PH1_W4_USER_RESPONSE){
5436f3582630SMatthias Ringwald         btstack_crypto_random_generate(&sm_crypto_random_request, setup->sm_local_random, 16, &sm_handle_random_result_ph2_random, (void *)(uintptr_t) sm_conn->sm_handle);
54373deb3ec6SMatthias Ringwald     }
54381c516d8fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
54396535961aSMatthias Ringwald     (void)memcpy(setup->sm_ra, setup->sm_tk, 16);
54406535961aSMatthias Ringwald     (void)memcpy(setup->sm_rb, setup->sm_tk, 16);
544107036a04SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_USER_RESPONSE){
544207036a04SMatthias Ringwald         sm_sc_start_calculating_local_confirm(sm_conn);
544307036a04SMatthias Ringwald     }
54441c516d8fSMatthias Ringwald #endif
544570b44dd4SMatthias Ringwald     sm_trigger_run();
54463deb3ec6SMatthias Ringwald }
54473deb3ec6SMatthias Ringwald 
sm_keypress_notification(hci_con_handle_t con_handle,uint8_t action)54483d7fe1e9SMatthias Ringwald void sm_keypress_notification(hci_con_handle_t con_handle, uint8_t action){
54493d7fe1e9SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
54503d7fe1e9SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
54513d7fe1e9SMatthias Ringwald     if (action > SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED) return;
5452dd4a08fbSMatthias Ringwald     uint8_t num_actions = setup->sm_keypress_notification >> 5;
54534ea43905SMatthias Ringwald     uint8_t flags = setup->sm_keypress_notification & 0x1fu;
5454dd4a08fbSMatthias Ringwald     switch (action){
5455dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_ENTRY_STARTED:
5456dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED:
54574ea43905SMatthias Ringwald             flags |= (1u << action);
5458dd4a08fbSMatthias Ringwald             break;
5459dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_CLEARED:
5460dd4a08fbSMatthias Ringwald             // clear counter, keypress & erased flags + set passkey cleared
54614ea43905SMatthias Ringwald             flags = (flags & 0x19u) | (1u << SM_KEYPRESS_PASSKEY_CLEARED);
5462dd4a08fbSMatthias Ringwald             break;
5463dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_DIGIT_ENTERED:
54641d80f1e6SMatthias Ringwald             if ((flags & (1u << SM_KEYPRESS_PASSKEY_DIGIT_ERASED)) != 0u){
5465dd4a08fbSMatthias Ringwald                 // erase actions queued
5466dd4a08fbSMatthias Ringwald                 num_actions--;
54674ea43905SMatthias Ringwald                 if (num_actions == 0u){
5468dd4a08fbSMatthias Ringwald                     // clear counter, keypress & erased flags
54694ea43905SMatthias Ringwald                     flags &= 0x19u;
5470dd4a08fbSMatthias Ringwald                 }
5471dd4a08fbSMatthias Ringwald                 break;
5472dd4a08fbSMatthias Ringwald             }
5473dd4a08fbSMatthias Ringwald             num_actions++;
54744ea43905SMatthias Ringwald             flags |= (1u << SM_KEYPRESS_PASSKEY_DIGIT_ENTERED);
5475dd4a08fbSMatthias Ringwald             break;
5476dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_DIGIT_ERASED:
54771d80f1e6SMatthias Ringwald             if ((flags & (1u << SM_KEYPRESS_PASSKEY_DIGIT_ENTERED)) != 0u){
5478dd4a08fbSMatthias Ringwald                 // enter actions queued
5479dd4a08fbSMatthias Ringwald                 num_actions--;
54804ea43905SMatthias Ringwald                 if (num_actions == 0u){
5481dd4a08fbSMatthias Ringwald                     // clear counter, keypress & erased flags
54824ea43905SMatthias Ringwald                     flags &= 0x19u;
5483dd4a08fbSMatthias Ringwald                 }
5484dd4a08fbSMatthias Ringwald                 break;
5485dd4a08fbSMatthias Ringwald             }
5486dd4a08fbSMatthias Ringwald             num_actions++;
54874ea43905SMatthias Ringwald             flags |= (1u << SM_KEYPRESS_PASSKEY_DIGIT_ERASED);
5488dd4a08fbSMatthias Ringwald             break;
5489dd4a08fbSMatthias Ringwald         default:
5490dd4a08fbSMatthias Ringwald             break;
5491dd4a08fbSMatthias Ringwald     }
5492dd4a08fbSMatthias Ringwald     setup->sm_keypress_notification = (num_actions << 5) | flags;
549370b44dd4SMatthias Ringwald     sm_trigger_run();
54943d7fe1e9SMatthias Ringwald }
54953d7fe1e9SMatthias Ringwald 
5496c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
sm_handle_random_result_oob(void * arg)5497d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_oob(void * arg){
5498d1a1f6a4SMatthias Ringwald     UNUSED(arg);
5499d1a1f6a4SMatthias Ringwald     sm_sc_oob_state = SM_SC_OOB_W2_CALC_CONFIRM;
550070b44dd4SMatthias Ringwald     sm_trigger_run();
5501d1a1f6a4SMatthias Ringwald }
sm_generate_sc_oob_data(void (* callback)(const uint8_t * confirm_value,const uint8_t * random_value))5502c59d0c92SMatthias Ringwald uint8_t sm_generate_sc_oob_data(void (*callback)(const uint8_t * confirm_value, const uint8_t * random_value)){
55038334d3d8SMatthias Ringwald 
55048334d3d8SMatthias Ringwald     static btstack_crypto_random_t   sm_crypto_random_oob_request;
55058334d3d8SMatthias Ringwald 
5506c59d0c92SMatthias Ringwald     if (sm_sc_oob_state != SM_SC_OOB_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
5507c59d0c92SMatthias Ringwald     sm_sc_oob_callback = callback;
5508d1a1f6a4SMatthias Ringwald     sm_sc_oob_state = SM_SC_OOB_W4_RANDOM;
5509d1a1f6a4SMatthias Ringwald     btstack_crypto_random_generate(&sm_crypto_random_oob_request, sm_sc_oob_random, 16, &sm_handle_random_result_oob, NULL);
5510c59d0c92SMatthias Ringwald     return 0;
5511c59d0c92SMatthias Ringwald }
5512c59d0c92SMatthias Ringwald #endif
5513c59d0c92SMatthias Ringwald 
55143deb3ec6SMatthias Ringwald /**
5515ba394633SMatthias Ringwald  * @brief Get Identity Resolving state
5516ba394633SMatthias Ringwald  * @param con_handle
5517ba394633SMatthias Ringwald  * @return irk_lookup_state_t
5518ba394633SMatthias Ringwald  */
sm_identity_resolving_state(hci_con_handle_t con_handle)5519ba394633SMatthias Ringwald irk_lookup_state_t sm_identity_resolving_state(hci_con_handle_t con_handle){
5520ba394633SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
5521ba394633SMatthias Ringwald     if (!sm_conn) return IRK_LOOKUP_IDLE;
5522ba394633SMatthias Ringwald     return sm_conn->sm_irk_lookup_state;
5523ba394633SMatthias Ringwald }
5524ba394633SMatthias Ringwald 
5525ba394633SMatthias Ringwald /**
55263deb3ec6SMatthias Ringwald  * @brief Identify device in LE Device DB
55273deb3ec6SMatthias Ringwald  * @param handle
55286b65794dSMilanka Ringwald  * @return index from le_device_db or -1 if not found/identified
55293deb3ec6SMatthias Ringwald  */
sm_le_device_index(hci_con_handle_t con_handle)5530711e6c80SMatthias Ringwald int sm_le_device_index(hci_con_handle_t con_handle ){
5531711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
55323deb3ec6SMatthias Ringwald     if (!sm_conn) return -1;
55333deb3ec6SMatthias Ringwald     return sm_conn->sm_le_db_index;
55343deb3ec6SMatthias Ringwald }
55353deb3ec6SMatthias Ringwald 
sm_get_ltk(hci_con_handle_t con_handle,sm_key_t ltk)5536916ea5b2SMatthias Ringwald uint8_t sm_get_ltk(hci_con_handle_t con_handle, sm_key_t ltk){
5537916ea5b2SMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
5538916ea5b2SMatthias Ringwald     if (hci_connection == NULL){
5539916ea5b2SMatthias Ringwald         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
5540916ea5b2SMatthias Ringwald     }
5541f728bb7bSMatthias Ringwald     if (hci_connection->link_key_type == INVALID_LINK_KEY){
5542916ea5b2SMatthias Ringwald         return ERROR_CODE_PIN_OR_KEY_MISSING;
5543916ea5b2SMatthias Ringwald     }
5544916ea5b2SMatthias Ringwald     memcpy(ltk, hci_connection->link_key, 16);
5545916ea5b2SMatthias Ringwald     return ERROR_CODE_SUCCESS;
5546916ea5b2SMatthias Ringwald }
5547916ea5b2SMatthias Ringwald 
gap_random_address_type_requires_updates(void)55488f57b085SMatthias Ringwald static int gap_random_address_type_requires_updates(void){
554947ba4de1SMatthias Ringwald     switch (gap_random_adress_type){
555047ba4de1SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_OFF:
555147ba4de1SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_STATIC:
555247ba4de1SMatthias Ringwald             return 0;
555347ba4de1SMatthias Ringwald         default:
55548f57b085SMatthias Ringwald             return 1;
55558f57b085SMatthias Ringwald     }
555647ba4de1SMatthias Ringwald }
5557d70217a2SMatthias Ringwald 
own_address_type(void)555833373e40SMatthias Ringwald static uint8_t own_address_type(void){
5559b95a5a35SMatthias Ringwald     switch (gap_random_adress_type){
5560b95a5a35SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_OFF:
5561b95a5a35SMatthias Ringwald             return BD_ADDR_TYPE_LE_PUBLIC;
5562b95a5a35SMatthias Ringwald         default:
5563b95a5a35SMatthias Ringwald             return BD_ADDR_TYPE_LE_RANDOM;
5564b95a5a35SMatthias Ringwald     }
556533373e40SMatthias Ringwald }
55668f57b085SMatthias Ringwald 
55673deb3ec6SMatthias Ringwald // GAP LE API
gap_random_address_set_mode(gap_random_address_type_t random_address_type)55683deb3ec6SMatthias Ringwald void gap_random_address_set_mode(gap_random_address_type_t random_address_type){
55693deb3ec6SMatthias Ringwald     gap_random_address_update_stop();
55703deb3ec6SMatthias Ringwald     gap_random_adress_type = random_address_type;
5571b95a5a35SMatthias Ringwald     hci_le_set_own_address_type(own_address_type());
55728f57b085SMatthias Ringwald     if (!gap_random_address_type_requires_updates()) return;
55733deb3ec6SMatthias Ringwald     gap_random_address_update_start();
55743deb3ec6SMatthias Ringwald     gap_random_address_trigger();
55753deb3ec6SMatthias Ringwald }
55763deb3ec6SMatthias Ringwald 
gap_random_address_get_mode(void)55773deb3ec6SMatthias Ringwald gap_random_address_type_t gap_random_address_get_mode(void){
55783deb3ec6SMatthias Ringwald     return gap_random_adress_type;
55793deb3ec6SMatthias Ringwald }
55803deb3ec6SMatthias Ringwald 
gap_random_address_set_update_period(int period_ms)55813deb3ec6SMatthias Ringwald void gap_random_address_set_update_period(int period_ms){
55823deb3ec6SMatthias Ringwald     gap_random_adress_update_period = period_ms;
55838f57b085SMatthias Ringwald     if (!gap_random_address_type_requires_updates()) return;
55843deb3ec6SMatthias Ringwald     gap_random_address_update_stop();
55853deb3ec6SMatthias Ringwald     gap_random_address_update_start();
55863deb3ec6SMatthias Ringwald }
55873deb3ec6SMatthias Ringwald 
gap_random_address_set(const bd_addr_t addr)5588667ba9d1SMatthias Ringwald void gap_random_address_set(const bd_addr_t addr){
55898f57b085SMatthias Ringwald     gap_random_address_set_mode(GAP_RANDOM_ADDRESS_TYPE_STATIC);
55906535961aSMatthias Ringwald     (void)memcpy(sm_random_address, addr, 6);
559163d302e8SMatthias Ringwald     // assert msb bits are set to '11'
559263d302e8SMatthias Ringwald     sm_random_address[0] |= 0xc0;
559363d302e8SMatthias Ringwald     hci_le_random_address_set(sm_random_address);
55947e252622SMatthias Ringwald }
55957e252622SMatthias Ringwald 
5596d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
55973deb3ec6SMatthias Ringwald /*
55983deb3ec6SMatthias Ringwald  * @brief Set Advertisement Paramters
55993deb3ec6SMatthias Ringwald  * @param adv_int_min
56003deb3ec6SMatthias Ringwald  * @param adv_int_max
56013deb3ec6SMatthias Ringwald  * @param adv_type
56023deb3ec6SMatthias Ringwald  * @param direct_address_type
56033deb3ec6SMatthias Ringwald  * @param direct_address
56043deb3ec6SMatthias Ringwald  * @param channel_map
56053deb3ec6SMatthias Ringwald  * @param filter_policy
56063deb3ec6SMatthias Ringwald  *
56073deb3ec6SMatthias Ringwald  * @note own_address_type is used from gap_random_address_set_mode
56083deb3ec6SMatthias Ringwald  */
gap_advertisements_set_params(uint16_t adv_int_min,uint16_t adv_int_max,uint8_t adv_type,uint8_t direct_address_typ,bd_addr_t direct_address,uint8_t channel_map,uint8_t filter_policy)56093deb3ec6SMatthias Ringwald void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
56103deb3ec6SMatthias Ringwald     uint8_t direct_address_typ, bd_addr_t direct_address, uint8_t channel_map, uint8_t filter_policy){
5611b95a5a35SMatthias Ringwald     hci_le_advertisements_set_params(adv_int_min, adv_int_max, adv_type,
56123deb3ec6SMatthias Ringwald         direct_address_typ, direct_address, channel_map, filter_policy);
56133deb3ec6SMatthias Ringwald }
5614d70217a2SMatthias Ringwald #endif
5615dcd6c9b5SMatthias Ringwald 
gap_reconnect_security_setup_active(hci_con_handle_t con_handle)5616c7ceba59SMatthias Ringwald bool gap_reconnect_security_setup_active(hci_con_handle_t con_handle){
5617dcd6c9b5SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
5618dcd6c9b5SMatthias Ringwald      // wrong connection
5619c7ceba59SMatthias Ringwald     if (!sm_conn) return false;
5620dcd6c9b5SMatthias Ringwald     // already encrypted
5621c7ceba59SMatthias Ringwald     if (sm_conn->sm_connection_encrypted) return false;
5622dcd6c9b5SMatthias Ringwald     // irk status?
5623dcd6c9b5SMatthias Ringwald     switch(sm_conn->sm_irk_lookup_state){
5624dcd6c9b5SMatthias Ringwald         case IRK_LOOKUP_FAILED:
5625dcd6c9b5SMatthias Ringwald             // done, cannot setup encryption
5626c7ceba59SMatthias Ringwald             return false;
5627dcd6c9b5SMatthias Ringwald         case IRK_LOOKUP_SUCCEEDED:
5628dcd6c9b5SMatthias Ringwald             break;
5629dcd6c9b5SMatthias Ringwald         default:
5630dcd6c9b5SMatthias Ringwald             // IR Lookup pending
5631c7ceba59SMatthias Ringwald             return true;
5632dcd6c9b5SMatthias Ringwald     }
5633f0674e22SMatthias Ringwald     // IRK Lookup Succeeded, re-encryption should be initiated. When done, state gets reset or indicates failure
5634c7ceba59SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_GENERAL_REENCRYPTION_FAILED) return false;
5635c7ceba59SMatthias Ringwald     if (sm_conn->sm_role != 0){
5636b15d5ceaSMatthias Ringwald         return sm_conn->sm_engine_state != SM_RESPONDER_IDLE;
5637b15d5ceaSMatthias Ringwald     } else {
5638dcd6c9b5SMatthias Ringwald         return sm_conn->sm_engine_state != SM_INITIATOR_CONNECTED;
5639dcd6c9b5SMatthias Ringwald     }
5640b15d5ceaSMatthias Ringwald }
56413cdbe9dbSMatthias Ringwald 
sm_set_secure_connections_only_mode(bool enable)56423cdbe9dbSMatthias Ringwald void sm_set_secure_connections_only_mode(bool enable){
56433cdbe9dbSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
56443cdbe9dbSMatthias Ringwald     sm_sc_only_mode = enable;
56453cdbe9dbSMatthias Ringwald #else
56463cdbe9dbSMatthias Ringwald     // SC Only mode not possible without support for SC
56473cdbe9dbSMatthias Ringwald     btstack_assert(enable == false);
56483cdbe9dbSMatthias Ringwald #endif
56493cdbe9dbSMatthias Ringwald }
5650052bbdc5SMatthias Ringwald 
565192f8d6b6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined (ENABLE_LE_SECURE_CONNECTION_DEBUG_KEY)
sm_test_enable_secure_connections_debug_keys(void)5652db88441fSMatthias Ringwald void sm_test_enable_secure_connections_debug_keys(void) {
5653db88441fSMatthias Ringwald     log_info("Enable LE Secure Connection Debug Keys for testing");
5654db88441fSMatthias Ringwald     sm_sc_debug_keys_enabled = true;
5655db88441fSMatthias Ringwald     // set debug key
5656db88441fSMatthias Ringwald     sm_ec_generate_new_key();
5657db88441fSMatthias Ringwald }
5658db88441fSMatthias Ringwald #endif
5659db88441fSMatthias Ringwald 
gap_get_persistent_irk(void)5660052bbdc5SMatthias Ringwald const uint8_t * gap_get_persistent_irk(void){
5661052bbdc5SMatthias Ringwald     return sm_persistent_irk;
5662052bbdc5SMatthias Ringwald }
56634f384501SMatthias Ringwald 
gap_delete_bonding(bd_addr_type_t address_type,bd_addr_t address)56644f384501SMatthias Ringwald void gap_delete_bonding(bd_addr_type_t address_type, bd_addr_t address){
566522cb578bSMatthias Ringwald     int index = sm_le_device_db_index_lookup(address_type, address);
566622cb578bSMatthias Ringwald     if (index >= 0){
566722cb578bSMatthias Ringwald         sm_remove_le_device_db_entry(index);
56684f384501SMatthias Ringwald     }
56694f384501SMatthias Ringwald }
5670