xref: /btstack/src/ble/sm.c (revision 1d80f1e61a1e6c1ddda1c7055dc13ed074dda35c)
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)
75f688bdb8SMatthias 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)
79f688bdb8SMatthias Ringwald #define IS_RESPONDER(role) (0 && (role == HCI_ROLE_SLAVE))
8042134bc6SMatthias Ringwald #else
8142134bc6SMatthias Ringwald // only peripheral - always responder (avoid 'unused variable' warnings)
82f688bdb8SMatthias 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
201b6f39a74SMatthias Ringwald static uint8_t 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 
4363deb3ec6SMatthias Ringwald static void log_info_hex16(const char * name, uint16_t value){
4373deb3ec6SMatthias Ringwald     log_info("%-6s 0x%04x", name, value);
4383deb3ec6SMatthias Ringwald }
4393deb3ec6SMatthias Ringwald 
4401fbd72c5SMatthias Ringwald // static inline uint8_t sm_pairing_packet_get_code(sm_pairing_packet_t packet){
4411fbd72c5SMatthias Ringwald //     return packet[0];
4421fbd72c5SMatthias Ringwald // }
4431fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_io_capability(sm_pairing_packet_t packet){
4441fbd72c5SMatthias Ringwald     return packet[1];
4451fbd72c5SMatthias Ringwald }
4461fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_oob_data_flag(sm_pairing_packet_t packet){
4471fbd72c5SMatthias Ringwald     return packet[2];
4481fbd72c5SMatthias Ringwald }
4491fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_auth_req(sm_pairing_packet_t packet){
4501fbd72c5SMatthias Ringwald     return packet[3];
4511fbd72c5SMatthias Ringwald }
4521fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_max_encryption_key_size(sm_pairing_packet_t packet){
4531fbd72c5SMatthias Ringwald     return packet[4];
4541fbd72c5SMatthias Ringwald }
4551fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_initiator_key_distribution(sm_pairing_packet_t packet){
4561fbd72c5SMatthias Ringwald     return packet[5];
4571fbd72c5SMatthias Ringwald }
4581fbd72c5SMatthias Ringwald static inline uint8_t sm_pairing_packet_get_responder_key_distribution(sm_pairing_packet_t packet){
4591fbd72c5SMatthias Ringwald     return packet[6];
4601fbd72c5SMatthias Ringwald }
4611fbd72c5SMatthias Ringwald 
4621fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_code(sm_pairing_packet_t packet, uint8_t code){
4631fbd72c5SMatthias Ringwald     packet[0] = code;
4641fbd72c5SMatthias Ringwald }
4651fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_io_capability(sm_pairing_packet_t packet, uint8_t io_capability){
4661fbd72c5SMatthias Ringwald     packet[1] = io_capability;
4671fbd72c5SMatthias Ringwald }
4681fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_oob_data_flag(sm_pairing_packet_t packet, uint8_t oob_data_flag){
4691fbd72c5SMatthias Ringwald     packet[2] = oob_data_flag;
4701fbd72c5SMatthias Ringwald }
4711fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_auth_req(sm_pairing_packet_t packet, uint8_t auth_req){
4721fbd72c5SMatthias Ringwald     packet[3] = auth_req;
4731fbd72c5SMatthias Ringwald }
4741fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_max_encryption_key_size(sm_pairing_packet_t packet, uint8_t max_encryption_key_size){
4751fbd72c5SMatthias Ringwald     packet[4] = max_encryption_key_size;
4761fbd72c5SMatthias Ringwald }
4771fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_initiator_key_distribution(sm_pairing_packet_t packet, uint8_t initiator_key_distribution){
4781fbd72c5SMatthias Ringwald     packet[5] = initiator_key_distribution;
4791fbd72c5SMatthias Ringwald }
4801fbd72c5SMatthias Ringwald static inline void sm_pairing_packet_set_responder_key_distribution(sm_pairing_packet_t packet, uint8_t responder_key_distribution){
4811fbd72c5SMatthias Ringwald     packet[6] = responder_key_distribution;
4821fbd72c5SMatthias Ringwald }
4831fbd72c5SMatthias Ringwald 
4841979f09cSMatthias Ringwald static bool sm_is_null_random(uint8_t random[8]){
48524c4191dSMatthias Ringwald     return btstack_is_null(random, 8);
4863764b551SMatthias Ringwald }
4873764b551SMatthias Ringwald 
4881979f09cSMatthias Ringwald static bool sm_is_null_key(uint8_t * key){
48924c4191dSMatthias Ringwald     return btstack_is_null(key, 16);
4903764b551SMatthias Ringwald }
4913764b551SMatthias Ringwald 
4921c34405fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4931c34405fSMatthias Ringwald static bool sm_is_ff(const uint8_t * buffer, uint16_t size){
4941c34405fSMatthias Ringwald     uint16_t i;
4951c34405fSMatthias Ringwald     for (i=0; i < size ; i++){
4961c34405fSMatthias Ringwald         if (buffer[i] != 0xff) {
4971c34405fSMatthias Ringwald             return false;
4981c34405fSMatthias Ringwald         }
4991c34405fSMatthias Ringwald     }
5001c34405fSMatthias Ringwald     return true;
5011c34405fSMatthias Ringwald }
5021c34405fSMatthias Ringwald #endif
5031c34405fSMatthias Ringwald 
50470b44dd4SMatthias Ringwald // sm_trigger_run allows to schedule callback from main run loop // reduces stack depth
50570b44dd4SMatthias Ringwald static void sm_run_timer_handler(btstack_timer_source_t * ts){
50670b44dd4SMatthias Ringwald 	UNUSED(ts);
50770b44dd4SMatthias Ringwald 	sm_run();
50870b44dd4SMatthias Ringwald }
50970b44dd4SMatthias Ringwald static void sm_trigger_run(void){
5102d2d4d3cSMatthias Ringwald     if (!sm_initialized) return;
51184c0c5c7SMatthias Ringwald 	(void)btstack_run_loop_remove_timer(&sm_run_timer);
51270b44dd4SMatthias Ringwald 	btstack_run_loop_set_timer(&sm_run_timer, 0);
51370b44dd4SMatthias Ringwald 	btstack_run_loop_add_timer(&sm_run_timer);
51470b44dd4SMatthias Ringwald }
51570b44dd4SMatthias Ringwald 
5163deb3ec6SMatthias Ringwald // Key utils
5173deb3ec6SMatthias Ringwald static void sm_reset_tk(void){
5183deb3ec6SMatthias Ringwald     int i;
5193deb3ec6SMatthias Ringwald     for (i=0;i<16;i++){
5203deb3ec6SMatthias Ringwald         setup->sm_tk[i] = 0;
5213deb3ec6SMatthias Ringwald     }
5223deb3ec6SMatthias Ringwald }
5233deb3ec6SMatthias Ringwald 
5243deb3ec6SMatthias Ringwald // "For example, if a 128-bit encryption key is 0x123456789ABCDEF0123456789ABCDEF0
5253deb3ec6SMatthias Ringwald // and it is reduced to 7 octets (56 bits), then the resulting key is 0x0000000000000000003456789ABCDEF0.""
5263deb3ec6SMatthias Ringwald static void sm_truncate_key(sm_key_t key, int max_encryption_size){
5273deb3ec6SMatthias Ringwald     int i;
5283deb3ec6SMatthias Ringwald     for (i = max_encryption_size ; i < 16 ; i++){
5293deb3ec6SMatthias Ringwald         key[15-i] = 0;
5303deb3ec6SMatthias Ringwald     }
5313deb3ec6SMatthias Ringwald }
5323deb3ec6SMatthias Ringwald 
533899e6e02SMatthias Ringwald // ER / IR checks
53421045273SMatthias Ringwald static void sm_er_ir_set_default(void){
535899e6e02SMatthias Ringwald     int i;
536899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
537899e6e02SMatthias Ringwald         sm_persistent_er[i] = 0x30 + i;
538899e6e02SMatthias Ringwald         sm_persistent_ir[i] = 0x90 + i;
539899e6e02SMatthias Ringwald     }
540899e6e02SMatthias Ringwald }
541899e6e02SMatthias Ringwald 
542*1d80f1e6SMatthias Ringwald static bool sm_er_is_default(void){
543899e6e02SMatthias Ringwald     int i;
544899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
545*1d80f1e6SMatthias Ringwald         if (sm_persistent_er[i] != (0x30+i)) return true;
546899e6e02SMatthias Ringwald     }
547*1d80f1e6SMatthias Ringwald     return false;
548899e6e02SMatthias Ringwald }
549899e6e02SMatthias Ringwald 
550*1d80f1e6SMatthias Ringwald static bool sm_ir_is_default(void){
551899e6e02SMatthias Ringwald     int i;
552899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
553*1d80f1e6SMatthias Ringwald         if (sm_persistent_ir[i] != (0x90+i)) return true;
554899e6e02SMatthias Ringwald     }
555*1d80f1e6SMatthias Ringwald     return false;
556899e6e02SMatthias Ringwald }
557899e6e02SMatthias Ringwald 
55873102768SMatthias Ringwald static void sm_dispatch_event(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
55973102768SMatthias Ringwald     UNUSED(channel);
56073102768SMatthias Ringwald 
56173102768SMatthias Ringwald     // log event
56273102768SMatthias Ringwald     hci_dump_packet(packet_type, 1, packet, size);
56373102768SMatthias Ringwald     // dispatch to all event handlers
56473102768SMatthias Ringwald     btstack_linked_list_iterator_t it;
56573102768SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &sm_event_handlers);
56673102768SMatthias Ringwald     while (btstack_linked_list_iterator_has_next(&it)){
56773102768SMatthias Ringwald         btstack_packet_callback_registration_t * entry = (btstack_packet_callback_registration_t*) btstack_linked_list_iterator_next(&it);
56873102768SMatthias Ringwald         entry->callback(packet_type, 0, packet, size);
56973102768SMatthias Ringwald     }
57073102768SMatthias Ringwald }
57173102768SMatthias Ringwald 
57273102768SMatthias 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){
57373102768SMatthias Ringwald     event[0] = type;
57473102768SMatthias Ringwald     event[1] = event_size - 2;
57573102768SMatthias Ringwald     little_endian_store_16(event, 2, con_handle);
57673102768SMatthias Ringwald     event[4] = addr_type;
57773102768SMatthias Ringwald     reverse_bd_addr(address, &event[5]);
57873102768SMatthias Ringwald }
57973102768SMatthias Ringwald 
58073102768SMatthias Ringwald static void sm_notify_client_base(uint8_t type, hci_con_handle_t con_handle, uint8_t addr_type, bd_addr_t address){
58173102768SMatthias Ringwald     uint8_t event[11];
58273102768SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
58373102768SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
58473102768SMatthias Ringwald }
58573102768SMatthias Ringwald 
58673102768SMatthias 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){
58773102768SMatthias Ringwald     // fetch addr and addr type from db, only called for valid entries
58873102768SMatthias Ringwald     bd_addr_t identity_address;
58973102768SMatthias Ringwald     int identity_address_type;
59073102768SMatthias Ringwald     le_device_db_info(index, &identity_address_type, identity_address, NULL);
59173102768SMatthias Ringwald 
59273102768SMatthias Ringwald     uint8_t event[20];
59373102768SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
59473102768SMatthias Ringwald     event[11] = identity_address_type;
59573102768SMatthias Ringwald     reverse_bd_addr(identity_address, &event[12]);
59673102768SMatthias Ringwald     little_endian_store_16(event, 18, index);
59773102768SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
59873102768SMatthias Ringwald }
59973102768SMatthias Ringwald 
60073102768SMatthias 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){
60173102768SMatthias Ringwald     uint8_t event[12];
60273102768SMatthias Ringwald     sm_setup_event_base(event, sizeof(event), type, con_handle, addr_type, address);
60373102768SMatthias Ringwald     event[11] = status;
60473102768SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
60573102768SMatthias Ringwald }
60673102768SMatthias Ringwald 
60773102768SMatthias Ringwald 
60873102768SMatthias Ringwald static void sm_reencryption_started(sm_connection_t * sm_conn){
60973102768SMatthias Ringwald 
6103ab61f77SMatthias Ringwald     if (sm_conn->sm_reencryption_active) return;
6113ab61f77SMatthias Ringwald 
6127b001f4eSMatthias Ringwald     sm_conn->sm_reencryption_active = true;
61373102768SMatthias Ringwald 
61473102768SMatthias Ringwald     int       identity_addr_type;
61573102768SMatthias Ringwald     bd_addr_t identity_addr;
6163c0e26deSMatthias Ringwald     if (sm_conn->sm_le_db_index >= 0){
6173c0e26deSMatthias Ringwald         // fetch addr and addr type from db, only called for valid entries
61873102768SMatthias Ringwald         le_device_db_info(sm_conn->sm_le_db_index, &identity_addr_type, identity_addr, NULL);
6193c0e26deSMatthias Ringwald     } else {
6203c0e26deSMatthias Ringwald         // for legacy pairing with LTK re-construction, use current peer addr
6213c0e26deSMatthias Ringwald         identity_addr_type = sm_conn->sm_peer_addr_type;
622d5529700SMatthias Ringwald         // cppcheck-suppress uninitvar ; identity_addr is reported as uninitialized although it's the destination of the memcpy
6233c0e26deSMatthias Ringwald         memcpy(identity_addr, sm_conn->sm_peer_address, 6);
6243c0e26deSMatthias Ringwald     }
62573102768SMatthias Ringwald 
62673102768SMatthias Ringwald     sm_notify_client_base(SM_EVENT_REENCRYPTION_STARTED, sm_conn->sm_handle, identity_addr_type, identity_addr);
62773102768SMatthias Ringwald }
62873102768SMatthias Ringwald 
62973102768SMatthias Ringwald static void sm_reencryption_complete(sm_connection_t * sm_conn, uint8_t status){
63073102768SMatthias Ringwald 
63160be5b21SMatthias Ringwald     if (!sm_conn->sm_reencryption_active) return;
63260be5b21SMatthias Ringwald 
6337b001f4eSMatthias Ringwald     sm_conn->sm_reencryption_active = false;
63473102768SMatthias Ringwald 
63573102768SMatthias Ringwald     int       identity_addr_type;
63673102768SMatthias Ringwald     bd_addr_t identity_addr;
6373c0e26deSMatthias Ringwald     if (sm_conn->sm_le_db_index >= 0){
6383c0e26deSMatthias Ringwald         // fetch addr and addr type from db, only called for valid entries
63973102768SMatthias Ringwald         le_device_db_info(sm_conn->sm_le_db_index, &identity_addr_type, identity_addr, NULL);
6403c0e26deSMatthias Ringwald     } else {
6413c0e26deSMatthias Ringwald         // for legacy pairing with LTK re-construction, use current peer addr
6423c0e26deSMatthias Ringwald         identity_addr_type = sm_conn->sm_peer_addr_type;
643d5529700SMatthias Ringwald         // cppcheck-suppress uninitvar ; identity_addr is reported as uninitialized although it's the destination of the memcpy
6443c0e26deSMatthias Ringwald         memcpy(identity_addr, sm_conn->sm_peer_address, 6);
6453c0e26deSMatthias Ringwald     }
64673102768SMatthias Ringwald 
64773102768SMatthias Ringwald     sm_notify_client_status(SM_EVENT_REENCRYPTION_COMPLETE, sm_conn->sm_handle, identity_addr_type, identity_addr, status);
64873102768SMatthias Ringwald }
64973102768SMatthias Ringwald 
650d3c12277SMatthias Ringwald static void sm_pairing_started(sm_connection_t * sm_conn){
651d3c12277SMatthias Ringwald 
652d3c12277SMatthias Ringwald     if (sm_conn->sm_pairing_active) return;
653d3c12277SMatthias Ringwald 
654d3c12277SMatthias Ringwald     sm_conn->sm_pairing_active = true;
655d3c12277SMatthias Ringwald 
656d3c12277SMatthias Ringwald     uint8_t event[11];
657d3c12277SMatthias 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);
658d3c12277SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
659d3c12277SMatthias Ringwald }
660d3c12277SMatthias Ringwald 
6610ccf6c9cSMatthias Ringwald static void sm_pairing_complete(sm_connection_t * sm_conn, uint8_t status, uint8_t reason){
662f61072f5SMatthias Ringwald 
663d77906ffSMatthias Ringwald     if (!sm_conn->sm_pairing_active) return;
664d77906ffSMatthias Ringwald 
66569f82ad8SMatthias Ringwald     sm_conn->sm_pairing_active = false;
66669f82ad8SMatthias Ringwald 
6670ccf6c9cSMatthias Ringwald     uint8_t event[13];
6680ccf6c9cSMatthias 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);
6690ccf6c9cSMatthias Ringwald     event[11] = status;
6700ccf6c9cSMatthias Ringwald     event[12] = reason;
6710ccf6c9cSMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, (uint8_t*) &event, sizeof(event));
6720ccf6c9cSMatthias Ringwald }
6730ccf6c9cSMatthias Ringwald 
6743deb3ec6SMatthias Ringwald // SMP Timeout implementation
6753deb3ec6SMatthias Ringwald 
6763deb3ec6SMatthias Ringwald // Upon transmission of the Pairing Request command or reception of the Pairing Request command,
6773deb3ec6SMatthias Ringwald // the Security Manager Timer shall be reset and started.
6783deb3ec6SMatthias Ringwald //
6793deb3ec6SMatthias Ringwald // The Security Manager Timer shall be reset when an L2CAP SMP command is queued for transmission.
6803deb3ec6SMatthias Ringwald //
6813deb3ec6SMatthias Ringwald // If the Security Manager Timer reaches 30 seconds, the procedure shall be considered to have failed,
6823deb3ec6SMatthias Ringwald // and the local higher layer shall be notified. No further SMP commands shall be sent over the L2CAP
6833deb3ec6SMatthias Ringwald // Security Manager Channel. A new SM procedure shall only be performed when a new physical link has been
6843deb3ec6SMatthias Ringwald // established.
6853deb3ec6SMatthias Ringwald 
686ec820d77SMatthias Ringwald static void sm_timeout_handler(btstack_timer_source_t * timer){
6873deb3ec6SMatthias Ringwald     log_info("SM timeout");
688c5b64319SMatthias Ringwald     sm_connection_t * sm_conn = (sm_connection_t*) btstack_run_loop_get_timer_context(timer);
6893deb3ec6SMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_TIMEOUT;
69068a18fb9SMatthias Ringwald     sm_reencryption_complete(sm_conn, ERROR_CODE_CONNECTION_TIMEOUT);
6910ccf6c9cSMatthias Ringwald     sm_pairing_complete(sm_conn, ERROR_CODE_CONNECTION_TIMEOUT, 0);
6923deb3ec6SMatthias Ringwald     sm_done_for_handle(sm_conn->sm_handle);
6933deb3ec6SMatthias Ringwald 
6943deb3ec6SMatthias Ringwald     // trigger handling of next ready connection
6953deb3ec6SMatthias Ringwald     sm_run();
6963deb3ec6SMatthias Ringwald }
6973deb3ec6SMatthias Ringwald static void sm_timeout_start(sm_connection_t * sm_conn){
698528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&setup->sm_timeout);
69991a977e8SMatthias Ringwald     btstack_run_loop_set_timer_context(&setup->sm_timeout, sm_conn);
700528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer_handler(&setup->sm_timeout, sm_timeout_handler);
701528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&setup->sm_timeout, 30000); // 30 seconds sm timeout
702528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&setup->sm_timeout);
7033deb3ec6SMatthias Ringwald }
7043deb3ec6SMatthias Ringwald static void sm_timeout_stop(void){
705528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&setup->sm_timeout);
7063deb3ec6SMatthias Ringwald }
7073deb3ec6SMatthias Ringwald static void sm_timeout_reset(sm_connection_t * sm_conn){
7083deb3ec6SMatthias Ringwald     sm_timeout_stop();
7093deb3ec6SMatthias Ringwald     sm_timeout_start(sm_conn);
7103deb3ec6SMatthias Ringwald }
7113deb3ec6SMatthias Ringwald 
7123deb3ec6SMatthias Ringwald // end of sm timeout
7133deb3ec6SMatthias Ringwald 
7143deb3ec6SMatthias Ringwald // GAP Random Address updates
7153deb3ec6SMatthias Ringwald static gap_random_address_type_t gap_random_adress_type;
716ec820d77SMatthias Ringwald static btstack_timer_source_t gap_random_address_update_timer;
7173deb3ec6SMatthias Ringwald static uint32_t gap_random_adress_update_period;
7183deb3ec6SMatthias Ringwald 
7193deb3ec6SMatthias Ringwald static void gap_random_address_trigger(void){
720899e6e02SMatthias Ringwald     log_info("gap_random_address_trigger, state %u", rau_state);
721d1a1f6a4SMatthias Ringwald     if (rau_state != RAU_IDLE) return;
722fbd4e238SMatthias Ringwald     rau_state = RAU_GET_RANDOM;
72370b44dd4SMatthias Ringwald     sm_trigger_run();
7243deb3ec6SMatthias Ringwald }
7253deb3ec6SMatthias Ringwald 
726ec820d77SMatthias Ringwald static void gap_random_address_update_handler(btstack_timer_source_t * timer){
7279ec2630cSMatthias Ringwald     UNUSED(timer);
7289ec2630cSMatthias Ringwald 
7293deb3ec6SMatthias Ringwald     log_info("GAP Random Address Update due");
730528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&gap_random_address_update_timer, gap_random_adress_update_period);
731528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&gap_random_address_update_timer);
7323deb3ec6SMatthias Ringwald     gap_random_address_trigger();
7333deb3ec6SMatthias Ringwald }
7343deb3ec6SMatthias Ringwald 
7353deb3ec6SMatthias Ringwald static void gap_random_address_update_start(void){
736528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer_handler(&gap_random_address_update_timer, gap_random_address_update_handler);
737528a4a3bSMatthias Ringwald     btstack_run_loop_set_timer(&gap_random_address_update_timer, gap_random_adress_update_period);
738528a4a3bSMatthias Ringwald     btstack_run_loop_add_timer(&gap_random_address_update_timer);
7393deb3ec6SMatthias Ringwald }
7403deb3ec6SMatthias Ringwald 
7413deb3ec6SMatthias Ringwald static void gap_random_address_update_stop(void){
742528a4a3bSMatthias Ringwald     btstack_run_loop_remove_timer(&gap_random_address_update_timer);
7433deb3ec6SMatthias Ringwald }
7443deb3ec6SMatthias Ringwald 
7453deb3ec6SMatthias Ringwald // ah(k,r) helper
7463deb3ec6SMatthias Ringwald // r = padding || r
7473deb3ec6SMatthias Ringwald // r - 24 bit value
7484a6806f3SMatthias Ringwald static void sm_ah_r_prime(uint8_t r[3], uint8_t * r_prime){
7493deb3ec6SMatthias Ringwald     // r'= padding || r
7503deb3ec6SMatthias Ringwald     memset(r_prime, 0, 16);
7516535961aSMatthias Ringwald     (void)memcpy(&r_prime[13], r, 3);
7523deb3ec6SMatthias Ringwald }
7533deb3ec6SMatthias Ringwald 
7543deb3ec6SMatthias Ringwald // d1 helper
7553deb3ec6SMatthias Ringwald // d' = padding || r || d
7563deb3ec6SMatthias Ringwald // d,r - 16 bit values
7574a6806f3SMatthias Ringwald static void sm_d1_d_prime(uint16_t d, uint16_t r, uint8_t * d1_prime){
7583deb3ec6SMatthias Ringwald     // d'= padding || r || d
7593deb3ec6SMatthias Ringwald     memset(d1_prime, 0, 16);
760f8fbdce0SMatthias Ringwald     big_endian_store_16(d1_prime, 12, r);
761f8fbdce0SMatthias Ringwald     big_endian_store_16(d1_prime, 14, d);
7623deb3ec6SMatthias Ringwald }
7633deb3ec6SMatthias Ringwald 
7643deb3ec6SMatthias Ringwald // calculate arguments for first AES128 operation in C1 function
7654a6806f3SMatthias 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){
7663deb3ec6SMatthias Ringwald 
7673deb3ec6SMatthias Ringwald     // p1 = pres || preq || rat’ || iat’
7683deb3ec6SMatthias Ringwald     // "The octet of iat’ becomes the least significant octet of p1 and the most signifi-
7693deb3ec6SMatthias Ringwald     // cant octet of pres becomes the most significant octet of p1.
7703deb3ec6SMatthias Ringwald     // For example, if the 8-bit iat’ is 0x01, the 8-bit rat’ is 0x00, the 56-bit preq
7713deb3ec6SMatthias Ringwald     // is 0x07071000000101 and the 56 bit pres is 0x05000800000302 then
7723deb3ec6SMatthias Ringwald     // p1 is 0x05000800000302070710000001010001."
7733deb3ec6SMatthias Ringwald 
7743deb3ec6SMatthias Ringwald     sm_key_t p1;
7759c80e4ccSMatthias Ringwald     reverse_56(pres, &p1[0]);
7769c80e4ccSMatthias Ringwald     reverse_56(preq, &p1[7]);
7773deb3ec6SMatthias Ringwald     p1[14] = rat;
7783deb3ec6SMatthias Ringwald     p1[15] = iat;
7798314c363SMatthias Ringwald     log_info_key("p1", p1);
7808314c363SMatthias Ringwald     log_info_key("r", r);
7813deb3ec6SMatthias Ringwald 
7823deb3ec6SMatthias Ringwald     // t1 = r xor p1
7833deb3ec6SMatthias Ringwald     int i;
7843deb3ec6SMatthias Ringwald     for (i=0;i<16;i++){
7853deb3ec6SMatthias Ringwald         t1[i] = r[i] ^ p1[i];
7863deb3ec6SMatthias Ringwald     }
7878314c363SMatthias Ringwald     log_info_key("t1", t1);
7883deb3ec6SMatthias Ringwald }
7893deb3ec6SMatthias Ringwald 
7903deb3ec6SMatthias Ringwald // calculate arguments for second AES128 operation in C1 function
7914a6806f3SMatthias Ringwald static void sm_c1_t3(sm_key_t t2, bd_addr_t ia, bd_addr_t ra, uint8_t * t3){
7923deb3ec6SMatthias Ringwald      // p2 = padding || ia || ra
7933deb3ec6SMatthias Ringwald     // "The least significant octet of ra becomes the least significant octet of p2 and
7943deb3ec6SMatthias Ringwald     // the most significant octet of padding becomes the most significant octet of p2.
7953deb3ec6SMatthias Ringwald     // For example, if 48-bit ia is 0xA1A2A3A4A5A6 and the 48-bit ra is
7963deb3ec6SMatthias Ringwald     // 0xB1B2B3B4B5B6 then p2 is 0x00000000A1A2A3A4A5A6B1B2B3B4B5B6.
7973deb3ec6SMatthias Ringwald 
7983deb3ec6SMatthias Ringwald     sm_key_t p2;
799d5529700SMatthias Ringwald     // cppcheck-suppress uninitvar ; p2 is reported as uninitialized
8003deb3ec6SMatthias Ringwald     memset(p2, 0, 16);
8016535961aSMatthias Ringwald     (void)memcpy(&p2[4], ia, 6);
8026535961aSMatthias Ringwald     (void)memcpy(&p2[10], ra, 6);
8038314c363SMatthias Ringwald     log_info_key("p2", p2);
8043deb3ec6SMatthias Ringwald 
8053deb3ec6SMatthias Ringwald     // c1 = e(k, t2_xor_p2)
8063deb3ec6SMatthias Ringwald     int i;
8073deb3ec6SMatthias Ringwald     for (i=0;i<16;i++){
8083deb3ec6SMatthias Ringwald         t3[i] = t2[i] ^ p2[i];
8093deb3ec6SMatthias Ringwald     }
8108314c363SMatthias Ringwald     log_info_key("t3", t3);
8113deb3ec6SMatthias Ringwald }
8123deb3ec6SMatthias Ringwald 
8134a6806f3SMatthias Ringwald static void sm_s1_r_prime(sm_key_t r1, sm_key_t r2, uint8_t * r_prime){
8148314c363SMatthias Ringwald     log_info_key("r1", r1);
8158314c363SMatthias Ringwald     log_info_key("r2", r2);
8166535961aSMatthias Ringwald     (void)memcpy(&r_prime[8], &r2[8], 8);
8176535961aSMatthias Ringwald     (void)memcpy(&r_prime[0], &r1[8], 8);
8183deb3ec6SMatthias Ringwald }
8193deb3ec6SMatthias Ringwald 
820fbe050beSMatthias Ringwald 
8213deb3ec6SMatthias Ringwald // decide on stk generation based on
8223deb3ec6SMatthias Ringwald // - pairing request
8233deb3ec6SMatthias Ringwald // - io capabilities
8243deb3ec6SMatthias Ringwald // - OOB data availability
8253deb3ec6SMatthias Ringwald static void sm_setup_tk(void){
8263deb3ec6SMatthias Ringwald 
8278334d3d8SMatthias Ringwald     // horizontal: initiator capabilities
8288334d3d8SMatthias Ringwald     // vertial:    responder capabilities
8298334d3d8SMatthias Ringwald     static const stk_generation_method_t stk_generation_method [5] [5] = {
8308334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,       PK_INIT_INPUT,   JUST_WORKS,    PK_INIT_INPUT },
8318334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,       PK_INIT_INPUT,   JUST_WORKS,    PK_INIT_INPUT },
8328334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   PK_RESP_INPUT,    PK_BOTH_INPUT,   JUST_WORKS,    PK_RESP_INPUT },
8338334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,       JUST_WORKS,      JUST_WORKS,    JUST_WORKS    },
8348334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   PK_RESP_INPUT,    PK_INIT_INPUT,   JUST_WORKS,    PK_RESP_INPUT },
8358334d3d8SMatthias Ringwald     };
8368334d3d8SMatthias Ringwald 
8378334d3d8SMatthias Ringwald     // uses numeric comparison if one side has DisplayYesNo and KeyboardDisplay combinations
8388334d3d8SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
8398334d3d8SMatthias Ringwald     static const stk_generation_method_t stk_generation_method_with_secure_connection[5][5] = {
8408334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,         PK_INIT_INPUT,   JUST_WORKS,    PK_INIT_INPUT      },
8418334d3d8SMatthias Ringwald             { JUST_WORKS,      NUMERIC_COMPARISON, PK_INIT_INPUT,   JUST_WORKS,    NUMERIC_COMPARISON },
8428334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   PK_RESP_INPUT,      PK_BOTH_INPUT,   JUST_WORKS,    PK_RESP_INPUT      },
8438334d3d8SMatthias Ringwald             { JUST_WORKS,      JUST_WORKS,         JUST_WORKS,      JUST_WORKS,    JUST_WORKS         },
8448334d3d8SMatthias Ringwald             { PK_RESP_INPUT,   NUMERIC_COMPARISON, PK_INIT_INPUT,   JUST_WORKS,    NUMERIC_COMPARISON },
8458334d3d8SMatthias Ringwald     };
8468334d3d8SMatthias Ringwald #endif
8478334d3d8SMatthias Ringwald 
8483deb3ec6SMatthias Ringwald     // default: just works
8493deb3ec6SMatthias Ringwald     setup->sm_stk_generation_method = JUST_WORKS;
8503deb3ec6SMatthias Ringwald 
85127c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
85227c32905SMatthias Ringwald     setup->sm_use_secure_connections = ( sm_pairing_packet_get_auth_req(setup->sm_m_preq)
85327c32905SMatthias Ringwald                                        & sm_pairing_packet_get_auth_req(setup->sm_s_pres)
8544ea43905SMatthias Ringwald                                        & SM_AUTHREQ_SECURE_CONNECTION ) != 0u;
85527c32905SMatthias Ringwald #else
8566777d8fdSMatthias Ringwald     setup->sm_use_secure_connections = false;
85727c32905SMatthias Ringwald #endif
85898d95509SMatthias Ringwald     log_info("Secure pairing: %u", setup->sm_use_secure_connections);
85927c32905SMatthias Ringwald 
86065a9a04eSMatthias Ringwald 
86165a9a04eSMatthias Ringwald     // decide if OOB will be used based on SC vs. Legacy and oob flags
8621979f09cSMatthias Ringwald     bool use_oob;
86365a9a04eSMatthias Ringwald     if (setup->sm_use_secure_connections){
86465a9a04eSMatthias Ringwald         // In LE Secure Connections pairing, the out of band method is used if at least
86565a9a04eSMatthias Ringwald         // one device has the peer device's out of band authentication data available.
8661979f09cSMatthias 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;
86765a9a04eSMatthias Ringwald     } else {
86865a9a04eSMatthias Ringwald         // In LE legacy pairing, the out of band method is used if both the devices have
86965a9a04eSMatthias Ringwald         // the other device's out of band authentication data available.
8701979f09cSMatthias 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;
87165a9a04eSMatthias Ringwald     }
87265a9a04eSMatthias Ringwald     if (use_oob){
87365a9a04eSMatthias Ringwald         log_info("SM: have OOB data");
87465a9a04eSMatthias Ringwald         log_info_key("OOB", setup->sm_tk);
87565a9a04eSMatthias Ringwald         setup->sm_stk_generation_method = OOB;
87665a9a04eSMatthias Ringwald         return;
87765a9a04eSMatthias Ringwald     }
87865a9a04eSMatthias Ringwald 
87927c32905SMatthias Ringwald     // If both devices have not set the MITM option in the Authentication Requirements
88027c32905SMatthias Ringwald     // Flags, then the IO capabilities shall be ignored and the Just Works association
88127c32905SMatthias Ringwald     // model shall be used.
8824ea43905SMatthias Ringwald     if (((sm_pairing_packet_get_auth_req(setup->sm_m_preq) & SM_AUTHREQ_MITM_PROTECTION) == 0u)
8834ea43905SMatthias Ringwald         &&  ((sm_pairing_packet_get_auth_req(setup->sm_s_pres) & SM_AUTHREQ_MITM_PROTECTION) == 0u)){
88427c32905SMatthias Ringwald         log_info("SM: MITM not required by both -> JUST WORKS");
88527c32905SMatthias Ringwald         return;
88627c32905SMatthias Ringwald     }
88727c32905SMatthias Ringwald 
8883deb3ec6SMatthias Ringwald     // Reset TK as it has been setup in sm_init_setup
8893deb3ec6SMatthias Ringwald     sm_reset_tk();
8903deb3ec6SMatthias Ringwald 
8913deb3ec6SMatthias Ringwald     // Also use just works if unknown io capabilites
8928da2e96dSMatthias 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)){
8933deb3ec6SMatthias Ringwald         return;
8943deb3ec6SMatthias Ringwald     }
8953deb3ec6SMatthias Ringwald 
8963deb3ec6SMatthias Ringwald     // Otherwise the IO capabilities of the devices shall be used to determine the
8973deb3ec6SMatthias Ringwald     // pairing method as defined in Table 2.4.
89827c32905SMatthias Ringwald     // see http://stackoverflow.com/a/1052837/393697 for how to specify pointer to 2-dimensional array
89927c32905SMatthias Ringwald     const stk_generation_method_t (*generation_method)[5] = stk_generation_method;
90027c32905SMatthias Ringwald 
90127c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
902c6b7cbd9SMatthias Ringwald     // table not define by default
90327c32905SMatthias Ringwald     if (setup->sm_use_secure_connections){
90427c32905SMatthias Ringwald         generation_method = stk_generation_method_with_secure_connection;
90527c32905SMatthias Ringwald     }
90627c32905SMatthias Ringwald #endif
90727c32905SMatthias 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)];
90827c32905SMatthias Ringwald 
9093deb3ec6SMatthias Ringwald     log_info("sm_setup_tk: master io cap: %u, slave io cap: %u -> method %u",
9101ad129beSMatthias 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);
9113deb3ec6SMatthias Ringwald }
9123deb3ec6SMatthias Ringwald 
9133deb3ec6SMatthias Ringwald static int sm_key_distribution_flags_for_set(uint8_t key_set){
9143deb3ec6SMatthias Ringwald     int flags = 0;
915f688bdb8SMatthias Ringwald     if ((key_set & SM_KEYDIST_ENC_KEY) != 0u){
9163deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
9173deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
9183deb3ec6SMatthias Ringwald     }
919f688bdb8SMatthias Ringwald     if ((key_set & SM_KEYDIST_ID_KEY) != 0u){
9203deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
9213deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
9223deb3ec6SMatthias Ringwald     }
923f688bdb8SMatthias Ringwald     if ((key_set & SM_KEYDIST_SIGN) != 0u){
9243deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
9253deb3ec6SMatthias Ringwald     }
9263deb3ec6SMatthias Ringwald     return flags;
9273deb3ec6SMatthias Ringwald }
9283deb3ec6SMatthias Ringwald 
9299a90d41aSMatthias Ringwald static void sm_setup_key_distribution(uint8_t keys_to_send, uint8_t keys_to_receive){
9303deb3ec6SMatthias Ringwald     setup->sm_key_distribution_received_set = 0;
9319a90d41aSMatthias Ringwald     setup->sm_key_distribution_expected_set = sm_key_distribution_flags_for_set(keys_to_receive);
9329a90d41aSMatthias Ringwald     setup->sm_key_distribution_send_set = sm_key_distribution_flags_for_set(keys_to_send);
933715a43d1SMatthias Ringwald     setup->sm_key_distribution_sent_set = 0;
9349790be5fSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
935715a43d1SMatthias Ringwald     setup->sm_le_device_index = -1;
9369790be5fSMatthias Ringwald #endif
9373deb3ec6SMatthias Ringwald }
9383deb3ec6SMatthias Ringwald 
9393deb3ec6SMatthias Ringwald // CSRK Key Lookup
9403deb3ec6SMatthias Ringwald 
9413deb3ec6SMatthias Ringwald 
942*1d80f1e6SMatthias Ringwald static bool sm_address_resolution_idle(void){
9433deb3ec6SMatthias Ringwald     return sm_address_resolution_mode == ADDRESS_RESOLUTION_IDLE;
9443deb3ec6SMatthias Ringwald }
9453deb3ec6SMatthias Ringwald 
946711e6c80SMatthias 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){
9476535961aSMatthias Ringwald     (void)memcpy(sm_address_resolution_address, addr, 6);
9483deb3ec6SMatthias Ringwald     sm_address_resolution_addr_type = addr_type;
9493deb3ec6SMatthias Ringwald     sm_address_resolution_test = 0;
9503deb3ec6SMatthias Ringwald     sm_address_resolution_mode = mode;
9513deb3ec6SMatthias Ringwald     sm_address_resolution_context = context;
952711e6c80SMatthias Ringwald     sm_notify_client_base(SM_EVENT_IDENTITY_RESOLVING_STARTED, con_handle, addr_type, addr);
9533deb3ec6SMatthias Ringwald }
9543deb3ec6SMatthias Ringwald 
9553deb3ec6SMatthias Ringwald int sm_address_resolution_lookup(uint8_t address_type, bd_addr_t address){
9563deb3ec6SMatthias Ringwald     // check if already in list
957665d90f2SMatthias Ringwald     btstack_linked_list_iterator_t it;
9583deb3ec6SMatthias Ringwald     sm_lookup_entry_t * entry;
959665d90f2SMatthias Ringwald     btstack_linked_list_iterator_init(&it, &sm_address_resolution_general_queue);
960665d90f2SMatthias Ringwald     while(btstack_linked_list_iterator_has_next(&it)){
961665d90f2SMatthias Ringwald         entry = (sm_lookup_entry_t *) btstack_linked_list_iterator_next(&it);
9623deb3ec6SMatthias Ringwald         if (entry->address_type != address_type) continue;
963f688bdb8SMatthias Ringwald         if (memcmp(entry->address, address, 6) != 0)  continue;
9643deb3ec6SMatthias Ringwald         // already in list
9653deb3ec6SMatthias Ringwald         return BTSTACK_BUSY;
9663deb3ec6SMatthias Ringwald     }
9673deb3ec6SMatthias Ringwald     entry = btstack_memory_sm_lookup_entry_get();
9683deb3ec6SMatthias Ringwald     if (!entry) return BTSTACK_MEMORY_ALLOC_FAILED;
9693deb3ec6SMatthias Ringwald     entry->address_type = (bd_addr_type_t) address_type;
9706535961aSMatthias Ringwald     (void)memcpy(entry->address, address, 6);
971665d90f2SMatthias Ringwald     btstack_linked_list_add(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
97270b44dd4SMatthias Ringwald     sm_trigger_run();
9733deb3ec6SMatthias Ringwald     return 0;
9743deb3ec6SMatthias Ringwald }
9753deb3ec6SMatthias Ringwald 
976d1a1f6a4SMatthias Ringwald // CMAC calculation using AES Engineq
977d1a1f6a4SMatthias Ringwald #ifdef USE_CMAC_ENGINE
978514d35fcSMatthias Ringwald 
979d1a1f6a4SMatthias Ringwald static void sm_cmac_done_trampoline(void * arg){
980d1a1f6a4SMatthias Ringwald     UNUSED(arg);
981d1a1f6a4SMatthias Ringwald     sm_cmac_active = 0;
982d1a1f6a4SMatthias Ringwald     (*sm_cmac_done_callback)(sm_cmac_hash);
98370b44dd4SMatthias Ringwald     sm_trigger_run();
9843deb3ec6SMatthias Ringwald }
985514d35fcSMatthias Ringwald 
9864dfd504aSMatthias Ringwald int sm_cmac_ready(void){
9874ea43905SMatthias Ringwald     return sm_cmac_active == 0u;
9883deb3ec6SMatthias Ringwald }
9896d80b495SMatthias Ringwald #endif
9903deb3ec6SMatthias Ringwald 
9916d80b495SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
992514d35fcSMatthias Ringwald // generic cmac calculation
993d1a1f6a4SMatthias 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)){
994d1a1f6a4SMatthias Ringwald     sm_cmac_active = 1;
995d1a1f6a4SMatthias Ringwald     sm_cmac_done_callback = done_callback;
996d1a1f6a4SMatthias Ringwald     btstack_crypto_aes128_cmac_message(&sm_cmac_request, key, message_len, message, sm_cmac_hash, sm_cmac_done_trampoline, NULL);
9973deb3ec6SMatthias Ringwald }
9987a766ebfSMatthias Ringwald #endif
9993deb3ec6SMatthias Ringwald 
1000514d35fcSMatthias Ringwald // cmac for ATT Message signing
10017a766ebfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
1002d1a1f6a4SMatthias Ringwald 
1003d1a1f6a4SMatthias 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)){
1004d1a1f6a4SMatthias Ringwald     sm_cmac_active = 1;
1005d1a1f6a4SMatthias Ringwald     sm_cmac_done_callback = done_callback;
1006d1a1f6a4SMatthias Ringwald     btstack_crypto_aes128_cmac_generator(&sm_cmac_request, key, message_len, get_byte_callback, sm_cmac_hash, sm_cmac_done_trampoline, NULL);
1007d1a1f6a4SMatthias Ringwald }
1008d1a1f6a4SMatthias Ringwald 
10094dfd504aSMatthias Ringwald static uint8_t sm_cmac_signed_write_message_get_byte(uint16_t offset){
1010d1a1f6a4SMatthias Ringwald     if (offset >= sm_cmac_signed_write_message_len) {
1011d1a1f6a4SMatthias Ringwald         log_error("sm_cmac_signed_write_message_get_byte. out of bounds, access %u, len %u", offset, sm_cmac_signed_write_message_len);
10124dfd504aSMatthias Ringwald         return 0;
10134dfd504aSMatthias Ringwald     }
10144dfd504aSMatthias Ringwald 
1015d1a1f6a4SMatthias Ringwald     offset = sm_cmac_signed_write_message_len - 1 - offset;
10164dfd504aSMatthias Ringwald 
1017d1a1f6a4SMatthias Ringwald     // sm_cmac_signed_write_header[3] | message[] | sm_cmac_signed_write_sign_counter[4]
10184dfd504aSMatthias Ringwald     if (offset < 3){
1019d1a1f6a4SMatthias Ringwald         return sm_cmac_signed_write_header[offset];
10204dfd504aSMatthias Ringwald     }
1021d1a1f6a4SMatthias Ringwald     int actual_message_len_incl_header = sm_cmac_signed_write_message_len - 4;
10224dfd504aSMatthias Ringwald     if (offset <  actual_message_len_incl_header){
1023d1a1f6a4SMatthias Ringwald         return sm_cmac_signed_write_message[offset - 3];
10244dfd504aSMatthias Ringwald     }
1025d1a1f6a4SMatthias Ringwald     return sm_cmac_signed_write_sign_counter[offset - actual_message_len_incl_header];
10264dfd504aSMatthias Ringwald }
10274dfd504aSMatthias Ringwald 
10284dfd504aSMatthias 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)){
1029514d35fcSMatthias Ringwald     // ATT Message Signing
1030d1a1f6a4SMatthias Ringwald     sm_cmac_signed_write_header[0] = opcode;
1031d1a1f6a4SMatthias Ringwald     little_endian_store_16(sm_cmac_signed_write_header, 1, con_handle);
1032d1a1f6a4SMatthias Ringwald     little_endian_store_32(sm_cmac_signed_write_sign_counter, 0, sign_counter);
1033514d35fcSMatthias Ringwald     uint16_t total_message_len = 3 + message_len + 4;  // incl. virtually prepended att opcode, handle and appended sign_counter in LE
1034d1a1f6a4SMatthias Ringwald     sm_cmac_signed_write_message     = message;
1035d1a1f6a4SMatthias Ringwald     sm_cmac_signed_write_message_len = total_message_len;
1036d1a1f6a4SMatthias Ringwald     sm_cmac_generator_start(k, total_message_len, &sm_cmac_signed_write_message_get_byte, done_handler);
10373deb3ec6SMatthias Ringwald }
10387a766ebfSMatthias Ringwald #endif
10393deb3ec6SMatthias Ringwald 
1040ea9b6796SMatthias Ringwald static void sm_trigger_user_response_basic(sm_connection_t * sm_conn, uint8_t event_type){
1041ea9b6796SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_PENDING;
10425baa755bSMatthias Ringwald     uint8_t event[12];
1043f6a153d5SMatthias 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);
10445baa755bSMatthias Ringwald     event[11] = setup->sm_use_secure_connections ? 1 : 0;
1045f6a153d5SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
1046ea9b6796SMatthias Ringwald }
1047ea9b6796SMatthias Ringwald 
104874b4d42aSMatthias Ringwald static void sm_trigger_user_response_passkey(sm_connection_t * sm_conn, uint8_t event_type){
10495baa755bSMatthias Ringwald     uint8_t event[16];
1050f6a153d5SMatthias Ringwald     uint32_t passkey = big_endian_read_32(setup->sm_tk, 12);
105174b4d42aSMatthias Ringwald     sm_setup_event_base(event, sizeof(event), event_type, sm_conn->sm_handle,
1052f6a153d5SMatthias Ringwald                         sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address);
10535baa755bSMatthias Ringwald     event[11] = setup->sm_use_secure_connections ? 1 : 0;
10545baa755bSMatthias Ringwald     little_endian_store_32(event, 12, passkey);
1055f6a153d5SMatthias Ringwald     sm_dispatch_event(HCI_EVENT_PACKET, 0, event, sizeof(event));
1056ea9b6796SMatthias Ringwald }
1057ea9b6796SMatthias Ringwald 
10583deb3ec6SMatthias Ringwald static void sm_trigger_user_response(sm_connection_t * sm_conn){
1059446a8c36SMatthias Ringwald     // notify client for: JUST WORKS confirm, Numeric comparison confirm, PASSKEY display or input
10603deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_IDLE;
1061d77906ffSMatthias Ringwald     sm_conn->sm_pairing_active = true;
10623deb3ec6SMatthias Ringwald     switch (setup->sm_stk_generation_method){
10633deb3ec6SMatthias Ringwald         case PK_RESP_INPUT:
106442134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1065ea9b6796SMatthias Ringwald                 sm_trigger_user_response_basic(sm_conn, SM_EVENT_PASSKEY_INPUT_NUMBER);
10663deb3ec6SMatthias Ringwald             } else {
106774b4d42aSMatthias Ringwald                 sm_trigger_user_response_passkey(sm_conn, SM_EVENT_PASSKEY_DISPLAY_NUMBER);
10683deb3ec6SMatthias Ringwald             }
10693deb3ec6SMatthias Ringwald             break;
10703deb3ec6SMatthias Ringwald         case PK_INIT_INPUT:
107142134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
107274b4d42aSMatthias Ringwald                 sm_trigger_user_response_passkey(sm_conn, SM_EVENT_PASSKEY_DISPLAY_NUMBER);
10733deb3ec6SMatthias Ringwald             } else {
1074ea9b6796SMatthias Ringwald                 sm_trigger_user_response_basic(sm_conn, SM_EVENT_PASSKEY_INPUT_NUMBER);
10753deb3ec6SMatthias Ringwald             }
10763deb3ec6SMatthias Ringwald             break;
107747fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
1078ea9b6796SMatthias Ringwald             sm_trigger_user_response_basic(sm_conn, SM_EVENT_PASSKEY_INPUT_NUMBER);
10793deb3ec6SMatthias Ringwald             break;
108047fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
108174b4d42aSMatthias Ringwald             sm_trigger_user_response_passkey(sm_conn, SM_EVENT_NUMERIC_COMPARISON_REQUEST);
108227c32905SMatthias Ringwald             break;
10833deb3ec6SMatthias Ringwald         case JUST_WORKS:
1084ea9b6796SMatthias Ringwald             sm_trigger_user_response_basic(sm_conn, SM_EVENT_JUST_WORKS_REQUEST);
10853deb3ec6SMatthias Ringwald             break;
10863deb3ec6SMatthias Ringwald         case OOB:
10873deb3ec6SMatthias Ringwald             // client already provided OOB data, let's skip notification.
10883deb3ec6SMatthias Ringwald             break;
10897bbeb3adSMilanka Ringwald         default:
10907bbeb3adSMilanka Ringwald             btstack_assert(false);
10917bbeb3adSMilanka Ringwald             break;
10923deb3ec6SMatthias Ringwald     }
10933deb3ec6SMatthias Ringwald }
10943deb3ec6SMatthias Ringwald 
109561d1a45eSMatthias Ringwald static bool sm_key_distribution_all_received(void) {
10965fa700b1SMatthias 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);
1097b2296177SMatthias Ringwald     return (setup->sm_key_distribution_expected_set & setup->sm_key_distribution_received_set) == setup->sm_key_distribution_expected_set;
10983deb3ec6SMatthias Ringwald }
10993deb3ec6SMatthias Ringwald 
1100711e6c80SMatthias Ringwald static void sm_done_for_handle(hci_con_handle_t con_handle){
11017149bde5SMatthias Ringwald     if (sm_active_connection_handle == con_handle){
11023deb3ec6SMatthias Ringwald         sm_timeout_stop();
11037149bde5SMatthias Ringwald         sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
1104711e6c80SMatthias Ringwald         log_info("sm: connection 0x%x released setup context", con_handle);
1105c085d9ffSMatthias Ringwald 
1106c085d9ffSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
1107c085d9ffSMatthias Ringwald         // generate new ec key after each pairing (that used it)
1108c085d9ffSMatthias Ringwald         if (setup->sm_use_secure_connections){
1109c085d9ffSMatthias Ringwald             sm_ec_generate_new_key();
1110c085d9ffSMatthias Ringwald         }
1111c085d9ffSMatthias Ringwald #endif
11123deb3ec6SMatthias Ringwald     }
11133deb3ec6SMatthias Ringwald }
11143deb3ec6SMatthias Ringwald 
11157d1c0c3aSMatthias Ringwald static void sm_master_pairing_success(sm_connection_t *connection) {// master -> all done
11161dca9d8aSMatthias Ringwald     connection->sm_engine_state = SM_INITIATOR_CONNECTED;
11170ccf6c9cSMatthias Ringwald     sm_pairing_complete(connection, ERROR_CODE_SUCCESS, 0);
11181dca9d8aSMatthias Ringwald     sm_done_for_handle(connection->sm_handle);
11191dca9d8aSMatthias Ringwald }
11201dca9d8aSMatthias Ringwald 
11213deb3ec6SMatthias Ringwald static int sm_key_distribution_flags_for_auth_req(void){
1122bb09604fSMatthias Ringwald 
1123bb09604fSMatthias Ringwald     int flags = SM_KEYDIST_ID_KEY;
1124f688bdb8SMatthias Ringwald     if ((sm_auth_req & SM_AUTHREQ_BONDING) != 0u){
1125bb09604fSMatthias Ringwald         // encryption and signing information only if bonding requested
11263deb3ec6SMatthias Ringwald         flags |= SM_KEYDIST_ENC_KEY;
1127bb09604fSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
1128bb09604fSMatthias Ringwald         flags |= SM_KEYDIST_SIGN;
1129bb09604fSMatthias Ringwald #endif
11307ece0eaaSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
11317ece0eaaSMatthias Ringwald         // LinkKey for CTKD requires SC
11327ece0eaaSMatthias Ringwald         if (sm_auth_req & SM_AUTHREQ_SECURE_CONNECTION){
11337ece0eaaSMatthias Ringwald         	flags |= SM_KEYDIST_LINK_KEY;
11347ece0eaaSMatthias Ringwald         }
11357ece0eaaSMatthias Ringwald #endif
11363deb3ec6SMatthias Ringwald     }
11373deb3ec6SMatthias Ringwald     return flags;
11383deb3ec6SMatthias Ringwald }
11393deb3ec6SMatthias Ringwald 
1140d7471931SMatthias Ringwald static void sm_reset_setup(void){
11413deb3ec6SMatthias Ringwald     // fill in sm setup
1142901c000fSMatthias Ringwald     setup->sm_state_vars = 0;
1143dd4a08fbSMatthias Ringwald     setup->sm_keypress_notification = 0;
1144d0ea782aSMatthias Ringwald     setup->sm_have_oob_data = 0;
11453deb3ec6SMatthias Ringwald     sm_reset_tk();
1146d7471931SMatthias Ringwald }
1147d7471931SMatthias Ringwald 
1148d7471931SMatthias Ringwald static void sm_init_setup(sm_connection_t * sm_conn){
1149d7471931SMatthias Ringwald     // fill in sm setup
11503deb3ec6SMatthias Ringwald     setup->sm_peer_addr_type = sm_conn->sm_peer_addr_type;
11516535961aSMatthias Ringwald     (void)memcpy(setup->sm_peer_address, sm_conn->sm_peer_address, 6);
11523deb3ec6SMatthias Ringwald 
1153a680ba6bSMatthias Ringwald     // query client for Legacy Pairing OOB data
11549305033eSMatthias Ringwald     if (sm_get_oob_data != NULL) {
1155a680ba6bSMatthias Ringwald         setup->sm_have_oob_data = (*sm_get_oob_data)(sm_conn->sm_peer_addr_type, sm_conn->sm_peer_address, setup->sm_tk);
11563deb3ec6SMatthias Ringwald     }
11573deb3ec6SMatthias Ringwald 
1158a680ba6bSMatthias Ringwald     // if available and SC supported, also ask for SC OOB Data
1159a680ba6bSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
11604acf7b7bSMatthias Ringwald     memset(setup->sm_ra, 0, 16);
11614acf7b7bSMatthias Ringwald     memset(setup->sm_rb, 0, 16);
1162a680ba6bSMatthias Ringwald     if (setup->sm_have_oob_data && (sm_auth_req & SM_AUTHREQ_SECURE_CONNECTION)){
11639305033eSMatthias Ringwald         if (sm_get_sc_oob_data != NULL){
11644acf7b7bSMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1165a680ba6bSMatthias Ringwald                 setup->sm_have_oob_data = (*sm_get_sc_oob_data)(
1166a680ba6bSMatthias Ringwald                     sm_conn->sm_peer_addr_type,
1167a680ba6bSMatthias Ringwald                     sm_conn->sm_peer_address,
1168a680ba6bSMatthias Ringwald                     setup->sm_peer_confirm,
11694acf7b7bSMatthias Ringwald                     setup->sm_ra);
11704acf7b7bSMatthias Ringwald             } else {
11714acf7b7bSMatthias Ringwald                 setup->sm_have_oob_data = (*sm_get_sc_oob_data)(
11724acf7b7bSMatthias Ringwald                     sm_conn->sm_peer_addr_type,
11734acf7b7bSMatthias Ringwald                     sm_conn->sm_peer_address,
11744acf7b7bSMatthias Ringwald                     setup->sm_peer_confirm,
11754acf7b7bSMatthias Ringwald                     setup->sm_rb);
11764acf7b7bSMatthias Ringwald             }
1177a680ba6bSMatthias Ringwald         } else {
1178a680ba6bSMatthias Ringwald             setup->sm_have_oob_data = 0;
1179a680ba6bSMatthias Ringwald         }
1180a680ba6bSMatthias Ringwald     }
1181a680ba6bSMatthias Ringwald #endif
1182a680ba6bSMatthias Ringwald 
11833deb3ec6SMatthias Ringwald     sm_pairing_packet_t * local_packet;
118442134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
11853deb3ec6SMatthias Ringwald         // slave
11863deb3ec6SMatthias Ringwald         local_packet = &setup->sm_s_pres;
11873deb3ec6SMatthias Ringwald         setup->sm_m_addr_type = sm_conn->sm_peer_addr_type;
1188d5314cbeSMatthias Ringwald         setup->sm_s_addr_type = sm_conn->sm_own_addr_type;
11896535961aSMatthias Ringwald         (void)memcpy(setup->sm_m_address, sm_conn->sm_peer_address, 6);
1190d5314cbeSMatthias Ringwald         (void)memcpy(setup->sm_s_address, sm_conn->sm_own_address, 6);
11913deb3ec6SMatthias Ringwald     } else {
11923deb3ec6SMatthias Ringwald         // master
11933deb3ec6SMatthias Ringwald         local_packet = &setup->sm_m_preq;
11943deb3ec6SMatthias Ringwald         setup->sm_s_addr_type = sm_conn->sm_peer_addr_type;
1195d5314cbeSMatthias Ringwald         setup->sm_m_addr_type = sm_conn->sm_own_addr_type;
11966535961aSMatthias Ringwald         (void)memcpy(setup->sm_s_address, sm_conn->sm_peer_address, 6);
1197d5314cbeSMatthias Ringwald         (void)memcpy(setup->sm_m_address, sm_conn->sm_own_address, 6);
11983deb3ec6SMatthias Ringwald 
1199d0ea782aSMatthias Ringwald         uint8_t key_distribution_flags = sm_key_distribution_flags_for_auth_req();
12001ad129beSMatthias Ringwald         sm_pairing_packet_set_initiator_key_distribution(setup->sm_m_preq, key_distribution_flags);
12011ad129beSMatthias Ringwald         sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags);
12023deb3ec6SMatthias Ringwald     }
12033deb3ec6SMatthias Ringwald 
120457132f12SMatthias Ringwald     uint8_t auth_req = sm_auth_req & ~SM_AUTHREQ_CT2;
1205d0ea782aSMatthias Ringwald     uint8_t max_encryption_key_size = sm_max_encryption_key_size;
12062c041b42SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12072c041b42SMatthias Ringwald     // enable SC for SC only mode
12082c041b42SMatthias Ringwald     if (sm_sc_only_mode){
12092c041b42SMatthias Ringwald         auth_req |= SM_AUTHREQ_SECURE_CONNECTION;
1210d0ea782aSMatthias Ringwald         max_encryption_key_size = 16;
12112c041b42SMatthias Ringwald     }
12122c041b42SMatthias Ringwald #endif
121357132f12SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
121457132f12SMatthias Ringwald 	// set CT2 if SC + Bonding + CTKD
121557132f12SMatthias Ringwald 	const uint8_t auth_req_for_ct2 = SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING;
121657132f12SMatthias Ringwald 	if ((auth_req & auth_req_for_ct2) == auth_req_for_ct2){
121757132f12SMatthias Ringwald 		auth_req |= SM_AUTHREQ_CT2;
121857132f12SMatthias Ringwald 	}
121957132f12SMatthias Ringwald #endif
12201ad129beSMatthias Ringwald     sm_pairing_packet_set_io_capability(*local_packet, sm_io_capabilities);
1221a680ba6bSMatthias Ringwald     sm_pairing_packet_set_oob_data_flag(*local_packet, setup->sm_have_oob_data);
1222df86eb96SMatthias Ringwald     sm_pairing_packet_set_auth_req(*local_packet, auth_req);
1223d0ea782aSMatthias Ringwald     sm_pairing_packet_set_max_encryption_key_size(*local_packet, max_encryption_key_size);
12243deb3ec6SMatthias Ringwald }
12253deb3ec6SMatthias Ringwald 
12263deb3ec6SMatthias Ringwald static int sm_stk_generation_init(sm_connection_t * sm_conn){
12273deb3ec6SMatthias Ringwald 
12283deb3ec6SMatthias Ringwald     sm_pairing_packet_t * remote_packet;
12299a90d41aSMatthias Ringwald     uint8_t               keys_to_send;
12309a90d41aSMatthias Ringwald     uint8_t               keys_to_receive;
123142134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
123252f9cf63SMatthias Ringwald         // slave / responder
12333deb3ec6SMatthias Ringwald         remote_packet   = &setup->sm_m_preq;
12349a90d41aSMatthias Ringwald         keys_to_send    = sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq);
12359a90d41aSMatthias Ringwald         keys_to_receive = sm_pairing_packet_get_initiator_key_distribution(setup->sm_m_preq);
12363deb3ec6SMatthias Ringwald     } else {
12373deb3ec6SMatthias Ringwald         // master / initiator
12383deb3ec6SMatthias Ringwald         remote_packet   = &setup->sm_s_pres;
12399a90d41aSMatthias Ringwald         keys_to_send    = sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres);
12409a90d41aSMatthias Ringwald         keys_to_receive = sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres);
12413deb3ec6SMatthias Ringwald     }
12423deb3ec6SMatthias Ringwald 
12433deb3ec6SMatthias Ringwald     // check key size
12442c041b42SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12452c041b42SMatthias Ringwald     // SC Only mandates 128 bit key size
12462c041b42SMatthias Ringwald     if (sm_sc_only_mode && (sm_pairing_packet_get_max_encryption_key_size(*remote_packet) < 16)) {
12472c041b42SMatthias Ringwald         return SM_REASON_ENCRYPTION_KEY_SIZE;
12482c041b42SMatthias Ringwald     }
12492c041b42SMatthias Ringwald #endif
12501ad129beSMatthias Ringwald     sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(sm_pairing_packet_get_max_encryption_key_size(*remote_packet));
12514ea43905SMatthias Ringwald     if (sm_conn->sm_actual_encryption_key_size == 0u) return SM_REASON_ENCRYPTION_KEY_SIZE;
12523deb3ec6SMatthias Ringwald 
1253eddc894fSMatthias Ringwald     // decide on STK generation method / SC
12543deb3ec6SMatthias Ringwald     sm_setup_tk();
12553deb3ec6SMatthias Ringwald     log_info("SMP: generation method %u", setup->sm_stk_generation_method);
12563deb3ec6SMatthias Ringwald 
12573deb3ec6SMatthias Ringwald     // check if STK generation method is acceptable by client
12583deb3ec6SMatthias Ringwald     if (!sm_validate_stk_generation_method()) return SM_REASON_AUTHENTHICATION_REQUIREMENTS;
12593deb3ec6SMatthias Ringwald 
1260eddc894fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12612c041b42SMatthias Ringwald     // Check LE SC Only mode
12623cdbe9dbSMatthias Ringwald     if (sm_sc_only_mode && (setup->sm_use_secure_connections == false)){
12633cdbe9dbSMatthias Ringwald         log_info("SC Only mode active but SC not possible");
12643cdbe9dbSMatthias Ringwald         return SM_REASON_AUTHENTHICATION_REQUIREMENTS;
12653cdbe9dbSMatthias Ringwald     }
12663cdbe9dbSMatthias Ringwald 
12679a90d41aSMatthias Ringwald     // LTK (= encryption information & master identification) only used exchanged for LE Legacy Connection
1268eddc894fSMatthias Ringwald     if (setup->sm_use_secure_connections){
12699a90d41aSMatthias Ringwald         keys_to_send &= ~SM_KEYDIST_ENC_KEY;
12709a90d41aSMatthias Ringwald         keys_to_receive  &= ~SM_KEYDIST_ENC_KEY;
1271eddc894fSMatthias Ringwald     }
1272eddc894fSMatthias Ringwald #endif
1273eddc894fSMatthias Ringwald 
127452f9cf63SMatthias Ringwald     // identical to responder
12759a90d41aSMatthias Ringwald     sm_setup_key_distribution(keys_to_send, keys_to_receive);
127652f9cf63SMatthias Ringwald 
12773deb3ec6SMatthias Ringwald     // JUST WORKS doens't provide authentication
1278c1ab6cc1SMatthias Ringwald     sm_conn->sm_connection_authenticated = (setup->sm_stk_generation_method == JUST_WORKS) ? 0 : 1;
12793deb3ec6SMatthias Ringwald 
12803deb3ec6SMatthias Ringwald     return 0;
12813deb3ec6SMatthias Ringwald }
12823deb3ec6SMatthias Ringwald 
12833deb3ec6SMatthias Ringwald static void sm_address_resolution_handle_event(address_resolution_event_t event){
12843deb3ec6SMatthias Ringwald 
12853deb3ec6SMatthias Ringwald     // cache and reset context
12863deb3ec6SMatthias Ringwald     int matched_device_id = sm_address_resolution_test;
12873deb3ec6SMatthias Ringwald     address_resolution_mode_t mode = sm_address_resolution_mode;
12883deb3ec6SMatthias Ringwald     void * context = sm_address_resolution_context;
12893deb3ec6SMatthias Ringwald 
12903deb3ec6SMatthias Ringwald     // reset context
12913deb3ec6SMatthias Ringwald     sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
12923deb3ec6SMatthias Ringwald     sm_address_resolution_context = NULL;
12933deb3ec6SMatthias Ringwald     sm_address_resolution_test = -1;
1294711e6c80SMatthias Ringwald     hci_con_handle_t con_handle = 0;
12953deb3ec6SMatthias Ringwald 
12963deb3ec6SMatthias Ringwald     sm_connection_t * sm_connection;
1297d2e90122SMatthias Ringwald     sm_key_t ltk;
12981979f09cSMatthias Ringwald     bool have_ltk;
12996c44b759SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
13001979f09cSMatthias Ringwald     bool trigger_pairing;
13012d68601cSMatthias Ringwald     int authenticated;
130242134bc6SMatthias Ringwald #endif
13033deb3ec6SMatthias Ringwald     switch (mode){
13043deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_GENERAL:
13053deb3ec6SMatthias Ringwald             break;
13063deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_FOR_CONNECTION:
13073deb3ec6SMatthias Ringwald             sm_connection = (sm_connection_t *) context;
1308711e6c80SMatthias Ringwald             con_handle = sm_connection->sm_handle;
13096c44b759SMatthias Ringwald 
13106c44b759SMatthias Ringwald             // have ltk -> start encryption / send security request
13116c44b759SMatthias Ringwald             // Core 5, Vol 3, Part C, 10.3.2 Initiating a Service Request
13126c44b759SMatthias Ringwald             // "When a bond has been created between two devices, any reconnection should result in the local device
13136c44b759SMatthias Ringwald             //  enabling or requesting encryption with the remote device before initiating any service request."
13146c44b759SMatthias Ringwald 
13153deb3ec6SMatthias Ringwald             switch (event){
1316a66b030fSMatthias Ringwald                 case ADDRESS_RESOLUTION_SUCCEEDED:
13173deb3ec6SMatthias Ringwald                     sm_connection->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
13183deb3ec6SMatthias Ringwald                     sm_connection->sm_le_db_index = matched_device_id;
1319a66b030fSMatthias Ringwald                     log_info("ADDRESS_RESOLUTION_SUCCEEDED, index %d", sm_connection->sm_le_db_index);
13206c44b759SMatthias Ringwald 
13212d68601cSMatthias Ringwald                     le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, &authenticated, NULL, NULL);
13226c44b759SMatthias Ringwald                     have_ltk = !sm_is_null_key(ltk);
13236c44b759SMatthias Ringwald 
1324f688bdb8SMatthias Ringwald                     if (IS_RESPONDER(sm_connection->sm_role)) {
13256c44b759SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
1326212d735eSMatthias Ringwald                         // IRK required before, continue
13276c39055aSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){
13286c39055aSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
13296c39055aSMatthias Ringwald                             break;
13306c39055aSMatthias Ringwald                         }
1331212d735eSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK){
1332212d735eSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
1333212d735eSMatthias Ringwald                             break;
1334212d735eSMatthias Ringwald                         }
13357af5dcd5SMatthias Ringwald                         bool trigger_security_request = (sm_connection->sm_pairing_requested != 0) || (sm_slave_request_security != 0);
13367af5dcd5SMatthias Ringwald                         sm_connection->sm_pairing_requested = 0;
13376c44b759SMatthias Ringwald #ifdef ENABLE_LE_PROACTIVE_AUTHENTICATION
13387af5dcd5SMatthias Ringwald                         // trigger security request for Proactive Authentication if LTK available
13397af5dcd5SMatthias Ringwald                         trigger_security_request = trigger_security_request || have_ltk;
13406c44b759SMatthias Ringwald #endif
13417af5dcd5SMatthias Ringwald 
13427af5dcd5SMatthias Ringwald                         log_info("peripheral: pairing request local %u, have_ltk %u => trigger_security_request %u",
13431979f09cSMatthias Ringwald                                  sm_connection->sm_pairing_requested, (int) have_ltk, trigger_security_request);
13447af5dcd5SMatthias Ringwald 
13457af5dcd5SMatthias Ringwald                         if (trigger_security_request){
13467af5dcd5SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
13477af5dcd5SMatthias Ringwald                             if (have_ltk){
13487af5dcd5SMatthias Ringwald                                 sm_reencryption_started(sm_connection);
13497af5dcd5SMatthias Ringwald                             } else {
13507af5dcd5SMatthias Ringwald                                 sm_pairing_started(sm_connection);
13517af5dcd5SMatthias Ringwald                             }
13527af5dcd5SMatthias Ringwald                             sm_trigger_run();
13536c44b759SMatthias Ringwald                         }
13546c44b759SMatthias Ringwald #endif
13556c44b759SMatthias Ringwald                     } else {
13566c44b759SMatthias Ringwald 
135742134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
13586c44b759SMatthias Ringwald                         // check if pairing already requested and reset requests
13596c44b759SMatthias Ringwald                         trigger_pairing = sm_connection->sm_pairing_requested || sm_connection->sm_security_request_received;
13602d68601cSMatthias Ringwald                         bool auth_required = sm_auth_req & SM_AUTHREQ_MITM_PROTECTION;
13612d68601cSMatthias Ringwald 
13626c44b759SMatthias Ringwald                         log_info("central: pairing request local %u, remote %u => trigger_pairing %u. have_ltk %u",
13631979f09cSMatthias Ringwald                                  sm_connection->sm_pairing_requested, sm_connection->sm_security_request_received, (int) trigger_pairing, (int) have_ltk);
13643deb3ec6SMatthias Ringwald                         sm_connection->sm_security_request_received = 0;
136509ea1b62SMatthias Ringwald                         sm_connection->sm_pairing_requested = 0;
136632bc5d65SMatthias Ringwald                         bool trigger_reencryption = false;
1367c245ca32SMatthias Ringwald 
1368d4af1595SMatthias Ringwald                         if (have_ltk){
13692d68601cSMatthias Ringwald                             if (trigger_pairing){
13702d68601cSMatthias Ringwald                                 // if pairing is requested, re-encryption is sufficient, if ltk is already authenticated or we don't require authentication
13712d68601cSMatthias Ringwald                                 trigger_reencryption = (authenticated != 0) || (auth_required == false);
13722d68601cSMatthias Ringwald                             } else {
13736a43f611SMatthias Ringwald #ifdef ENABLE_LE_PROACTIVE_AUTHENTICATION
1374b187cc61SMatthias Ringwald                                 trigger_reencryption = true;
137532bc5d65SMatthias Ringwald #else
137632bc5d65SMatthias Ringwald                                 log_info("central: defer enabling encryption for bonded device");
137732bc5d65SMatthias Ringwald #endif
137832bc5d65SMatthias Ringwald                             }
13792d68601cSMatthias Ringwald                         }
138032bc5d65SMatthias Ringwald 
138132bc5d65SMatthias Ringwald                         if (trigger_reencryption){
13826c44b759SMatthias Ringwald                             log_info("central: enable encryption for bonded device");
13835567aa60SMatthias Ringwald                             sm_connection->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
1384d4af1595SMatthias Ringwald                             break;
1385d4af1595SMatthias Ringwald                         }
13866c44b759SMatthias Ringwald 
13876c44b759SMatthias Ringwald                         // pairing_request -> send pairing request
13886c44b759SMatthias Ringwald                         if (trigger_pairing){
13893deb3ec6SMatthias Ringwald                             sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
1390d4af1595SMatthias Ringwald                             break;
13913deb3ec6SMatthias Ringwald                         }
139242134bc6SMatthias Ringwald #endif
1393298ab52bSMatthias Ringwald                     }
13943deb3ec6SMatthias Ringwald                     break;
13953deb3ec6SMatthias Ringwald                 case ADDRESS_RESOLUTION_FAILED:
13963deb3ec6SMatthias Ringwald                     sm_connection->sm_irk_lookup_state = IRK_LOOKUP_FAILED;
1397f688bdb8SMatthias Ringwald                     if (IS_RESPONDER(sm_connection->sm_role)) {
13987af5dcd5SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
13996c39055aSMatthias Ringwald                         // LTK request received before, IRK required -> negative LTK reply
14006c39055aSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){
14016c39055aSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
14026c39055aSMatthias Ringwald                         }
14037af5dcd5SMatthias Ringwald                         // send security request if requested
14047af5dcd5SMatthias Ringwald                         bool trigger_security_request = (sm_connection->sm_pairing_requested != 0) || (sm_slave_request_security != 0);
14057af5dcd5SMatthias Ringwald                         sm_connection->sm_pairing_requested = 0;
14067af5dcd5SMatthias Ringwald                         if (trigger_security_request){
14077af5dcd5SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
14087af5dcd5SMatthias Ringwald                             sm_pairing_started(sm_connection);
14097af5dcd5SMatthias Ringwald                         }
14106c39055aSMatthias Ringwald                         break;
14117af5dcd5SMatthias Ringwald #endif
14126c39055aSMatthias Ringwald                     }
141342134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
141409ea1b62SMatthias Ringwald                     if (!sm_connection->sm_pairing_requested && !sm_connection->sm_security_request_received) break;
14153deb3ec6SMatthias Ringwald                     sm_connection->sm_security_request_received = 0;
141609ea1b62SMatthias Ringwald                     sm_connection->sm_pairing_requested = 0;
14173deb3ec6SMatthias Ringwald                     sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
141842134bc6SMatthias Ringwald #endif
14193deb3ec6SMatthias Ringwald                     break;
14207bbeb3adSMilanka Ringwald 
14217bbeb3adSMilanka Ringwald                 default:
14227bbeb3adSMilanka Ringwald                     btstack_assert(false);
14237bbeb3adSMilanka Ringwald                     break;
14243deb3ec6SMatthias Ringwald             }
14253deb3ec6SMatthias Ringwald             break;
14263deb3ec6SMatthias Ringwald         default:
14273deb3ec6SMatthias Ringwald             break;
14283deb3ec6SMatthias Ringwald     }
14293deb3ec6SMatthias Ringwald 
14303deb3ec6SMatthias Ringwald     switch (event){
1431a66b030fSMatthias Ringwald         case ADDRESS_RESOLUTION_SUCCEEDED:
1432711e6c80SMatthias Ringwald             sm_notify_client_index(SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED, con_handle, sm_address_resolution_addr_type, sm_address_resolution_address, matched_device_id);
14333deb3ec6SMatthias Ringwald             break;
14343deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_FAILED:
1435711e6c80SMatthias Ringwald             sm_notify_client_base(SM_EVENT_IDENTITY_RESOLVING_FAILED, con_handle, sm_address_resolution_addr_type, sm_address_resolution_address);
14363deb3ec6SMatthias Ringwald             break;
14377bbeb3adSMilanka Ringwald         default:
14387bbeb3adSMilanka Ringwald             btstack_assert(false);
14397bbeb3adSMilanka Ringwald             break;
14403deb3ec6SMatthias Ringwald     }
14413deb3ec6SMatthias Ringwald }
14423deb3ec6SMatthias Ringwald 
144355f09f49SMatthias Ringwald static void sm_store_bonding_information(sm_connection_t * sm_conn){
14443deb3ec6SMatthias Ringwald     int le_db_index = -1;
14453deb3ec6SMatthias Ringwald 
14463deb3ec6SMatthias Ringwald     // lookup device based on IRK
1447f688bdb8SMatthias Ringwald     if ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
14483deb3ec6SMatthias Ringwald         int i;
1449092ec58eSMatthias Ringwald         for (i=0; i < le_device_db_max_count(); i++){
14503deb3ec6SMatthias Ringwald             sm_key_t irk;
14513deb3ec6SMatthias Ringwald             bd_addr_t address;
1452c7e2c1a5SMatthias Ringwald             int address_type = BD_ADDR_TYPE_UNKNOWN;
14533deb3ec6SMatthias Ringwald             le_device_db_info(i, &address_type, address, irk);
1454adf5eaa9SMatthias Ringwald             // skip unused entries
1455c7e2c1a5SMatthias Ringwald             if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
145611d10bdaSMatthias Ringwald             // compare Identity Address
145711d10bdaSMatthias Ringwald             if (memcmp(address, setup->sm_peer_address, 6) != 0) continue;
145811d10bdaSMatthias Ringwald             // compare Identity Resolving Key
1459c7e2c1a5SMatthias Ringwald             if (memcmp(irk, setup->sm_peer_irk, 16) != 0) continue;
1460c7e2c1a5SMatthias Ringwald 
14613deb3ec6SMatthias Ringwald             log_info("sm: device found for IRK, updating");
14623deb3ec6SMatthias Ringwald             le_db_index = i;
14633deb3ec6SMatthias Ringwald             break;
14643deb3ec6SMatthias Ringwald         }
1465c7e2c1a5SMatthias Ringwald     } else {
1466c7e2c1a5SMatthias Ringwald         // assert IRK is set to zero
1467c7e2c1a5SMatthias Ringwald         memset(setup->sm_peer_irk, 0, 16);
14683deb3ec6SMatthias Ringwald     }
14693deb3ec6SMatthias Ringwald 
14703deb3ec6SMatthias Ringwald     // if not found, lookup via public address if possible
14713deb3ec6SMatthias Ringwald     log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address));
1472c1ab6cc1SMatthias Ringwald     if ((le_db_index < 0) && (setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC)){
14733deb3ec6SMatthias Ringwald         int i;
1474092ec58eSMatthias Ringwald         for (i=0; i < le_device_db_max_count(); i++){
14753deb3ec6SMatthias Ringwald             bd_addr_t address;
1476adf5eaa9SMatthias Ringwald             int address_type = BD_ADDR_TYPE_UNKNOWN;
14773deb3ec6SMatthias Ringwald             le_device_db_info(i, &address_type, address, NULL);
1478adf5eaa9SMatthias Ringwald             // skip unused entries
1479adf5eaa9SMatthias Ringwald             if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
14803deb3ec6SMatthias Ringwald             log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address));
14815df9dc78SMatthias Ringwald             if ((address_type == BD_ADDR_TYPE_LE_PUBLIC) && (memcmp(address, setup->sm_peer_address, 6) == 0)){
14823deb3ec6SMatthias Ringwald                 log_info("sm: device found for public address, updating");
14833deb3ec6SMatthias Ringwald                 le_db_index = i;
14843deb3ec6SMatthias Ringwald                 break;
14853deb3ec6SMatthias Ringwald             }
14863deb3ec6SMatthias Ringwald         }
14873deb3ec6SMatthias Ringwald     }
14883deb3ec6SMatthias Ringwald 
14893deb3ec6SMatthias Ringwald     // if not found, add to db
149002b02cffSMatthias Ringwald     bool new_to_le_device_db = false;
14913deb3ec6SMatthias Ringwald     if (le_db_index < 0) {
14923deb3ec6SMatthias Ringwald         le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
149302b02cffSMatthias Ringwald         new_to_le_device_db = true;
14943deb3ec6SMatthias Ringwald     }
14953deb3ec6SMatthias Ringwald 
14963deb3ec6SMatthias Ringwald     if (le_db_index >= 0){
14973deb3ec6SMatthias Ringwald 
149802b02cffSMatthias Ringwald #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
149902b02cffSMatthias Ringwald         if (!new_to_le_device_db){
150002b02cffSMatthias Ringwald             hci_remove_le_device_db_entry_from_resolving_list(le_db_index);
150102b02cffSMatthias Ringwald         }
150202b02cffSMatthias Ringwald         hci_load_le_device_db_entry_into_resolving_list(le_db_index);
150302b02cffSMatthias Ringwald #else
150402b02cffSMatthias Ringwald         UNUSED(new_to_le_device_db);
150502b02cffSMatthias Ringwald #endif
150602b02cffSMatthias Ringwald 
150748163929SMatthias 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);
1508e1086030SMatthias Ringwald         sm_conn->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
15097710ebd2SMatthias Ringwald         sm_conn->sm_le_db_index = le_db_index;
151048163929SMatthias Ringwald 
1511eda85fbfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
15123deb3ec6SMatthias Ringwald         // store local CSRK
1513715a43d1SMatthias Ringwald         setup->sm_le_device_index = le_db_index;
1514715a43d1SMatthias Ringwald         if ((setup->sm_key_distribution_sent_set) & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
15153deb3ec6SMatthias Ringwald             log_info("sm: store local CSRK");
15163deb3ec6SMatthias Ringwald             le_device_db_local_csrk_set(le_db_index, setup->sm_local_csrk);
15173deb3ec6SMatthias Ringwald             le_device_db_local_counter_set(le_db_index, 0);
15183deb3ec6SMatthias Ringwald         }
15193deb3ec6SMatthias Ringwald 
15203deb3ec6SMatthias Ringwald         // store remote CSRK
15213deb3ec6SMatthias Ringwald         if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
15223deb3ec6SMatthias Ringwald             log_info("sm: store remote CSRK");
15233deb3ec6SMatthias Ringwald             le_device_db_remote_csrk_set(le_db_index, setup->sm_peer_csrk);
15243deb3ec6SMatthias Ringwald             le_device_db_remote_counter_set(le_db_index, 0);
15253deb3ec6SMatthias Ringwald         }
1526eda85fbfSMatthias Ringwald #endif
152778f44163SMatthias Ringwald         // store encryption information for secure connections: LTK generated by ECDH
152878f44163SMatthias Ringwald         if (setup->sm_use_secure_connections){
1529e6343eb6SMatthias Ringwald             log_info("sm: store SC LTK (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
153078f44163SMatthias Ringwald             uint8_t zero_rand[8];
153178f44163SMatthias Ringwald             memset(zero_rand, 0, 8);
153278f44163SMatthias Ringwald             le_device_db_encryption_set(le_db_index, 0, zero_rand, setup->sm_ltk, sm_conn->sm_actual_encryption_key_size,
15333dc3a67dSMatthias Ringwald                                         sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 1);
153478f44163SMatthias Ringwald         }
153578f44163SMatthias Ringwald 
1536e6343eb6SMatthias Ringwald         // store encryption information for legacy pairing: peer LTK, EDIV, RAND
153778f44163SMatthias Ringwald         else if ( (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION)
153878f44163SMatthias Ringwald         && (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION )){
1539e6343eb6SMatthias Ringwald             log_info("sm: set encryption information (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
15403deb3ec6SMatthias Ringwald             le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
15413dc3a67dSMatthias Ringwald                                         sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 0);
154278f44163SMatthias Ringwald 
15433deb3ec6SMatthias Ringwald         }
15443deb3ec6SMatthias Ringwald     }
154555f09f49SMatthias Ringwald }
154655f09f49SMatthias Ringwald 
15478980298aSMatthias Ringwald static void sm_pairing_error(sm_connection_t * sm_conn, uint8_t reason){
15488980298aSMatthias Ringwald     sm_conn->sm_pairing_failed_reason = reason;
15498980298aSMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
15508980298aSMatthias Ringwald }
15518980298aSMatthias Ringwald 
155222cb578bSMatthias Ringwald static int sm_le_device_db_index_lookup(bd_addr_type_t address_type, bd_addr_t address){
15531a55487aSMatthias Ringwald     int i;
15541a55487aSMatthias Ringwald     for (i=0; i < le_device_db_max_count(); i++){
155522cb578bSMatthias Ringwald         bd_addr_t db_address;
155622cb578bSMatthias Ringwald         int db_address_type = BD_ADDR_TYPE_UNKNOWN;
155722cb578bSMatthias Ringwald         le_device_db_info(i, &db_address_type, db_address, NULL);
15581a55487aSMatthias Ringwald         // skip unused entries
15591a55487aSMatthias Ringwald         if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
15603548b7cbSDirk Helbig         if ((address_type == (unsigned int)db_address_type) && (memcmp(address, db_address, 6) == 0)){
15611a55487aSMatthias Ringwald             return i;
15621a55487aSMatthias Ringwald         }
15631a55487aSMatthias Ringwald     }
15641a55487aSMatthias Ringwald     return -1;
15651a55487aSMatthias Ringwald }
15661a55487aSMatthias Ringwald 
15672e08b70bSMatthias Ringwald static void sm_remove_le_device_db_entry(uint16_t i) {
15682e08b70bSMatthias Ringwald     le_device_db_remove(i);
1569672dc582SMatthias Ringwald #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
1570672dc582SMatthias Ringwald     // to remove an entry from the resolving list requires its identity address, which was already deleted
1571672dc582SMatthias Ringwald     // fully reload resolving list instead
1572672dc582SMatthias Ringwald     gap_load_resolving_list_from_le_device_db();
1573672dc582SMatthias Ringwald #endif
15742e08b70bSMatthias Ringwald }
15752e08b70bSMatthias Ringwald 
15768980298aSMatthias Ringwald static uint8_t sm_key_distribution_validate_received(sm_connection_t * sm_conn){
15771a55487aSMatthias Ringwald     // if identity is provided, abort if we have bonding with same address but different irk
1578f688bdb8SMatthias Ringwald     if ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
157922cb578bSMatthias Ringwald         int index = sm_le_device_db_index_lookup(BD_ADDR_TYPE_LE_PUBLIC, setup->sm_peer_address);
15801a55487aSMatthias Ringwald         if (index >= 0){
15811a55487aSMatthias Ringwald             sm_key_t irk;
15821a55487aSMatthias Ringwald             le_device_db_info(index, NULL, NULL, irk);
15831a55487aSMatthias Ringwald             if (memcmp(irk, setup->sm_peer_irk, 16) != 0){
15841a55487aSMatthias Ringwald                 // IRK doesn't match, delete bonding information
15851a55487aSMatthias 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);
15869202d845SMatthias Ringwald                 sm_remove_le_device_db_entry(index);
15871a55487aSMatthias Ringwald             }
15881a55487aSMatthias Ringwald         }
15891a55487aSMatthias Ringwald     }
15908980298aSMatthias Ringwald     return 0;
15918980298aSMatthias Ringwald }
15928980298aSMatthias Ringwald 
159355f09f49SMatthias Ringwald static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
159455f09f49SMatthias Ringwald 
15958980298aSMatthias Ringwald     // abort pairing if received keys are not valid
15968980298aSMatthias Ringwald     uint8_t reason = sm_key_distribution_validate_received(sm_conn);
15978980298aSMatthias Ringwald     if (reason != 0){
15988980298aSMatthias Ringwald         sm_pairing_error(sm_conn, reason);
15998980298aSMatthias Ringwald         return;
16008980298aSMatthias Ringwald     }
16018980298aSMatthias Ringwald 
160255f09f49SMatthias Ringwald     // only store pairing information if both sides are bondable, i.e., the bonadble flag is set
160355f09f49SMatthias Ringwald     bool bonding_enabled = (sm_pairing_packet_get_auth_req(setup->sm_m_preq)
160455f09f49SMatthias Ringwald                             & sm_pairing_packet_get_auth_req(setup->sm_s_pres)
160555f09f49SMatthias Ringwald                             & SM_AUTHREQ_BONDING ) != 0u;
160655f09f49SMatthias Ringwald 
160755f09f49SMatthias Ringwald     if (bonding_enabled){
160855f09f49SMatthias Ringwald         sm_store_bonding_information(sm_conn);
160927ef8bc8SMatthias Ringwald     } else {
161027ef8bc8SMatthias Ringwald         log_info("Ignoring received keys, bonding not enabled");
161127ef8bc8SMatthias Ringwald     }
16123deb3ec6SMatthias Ringwald }
16133deb3ec6SMatthias Ringwald 
1614688a08f9SMatthias Ringwald static inline void sm_pdu_received_in_wrong_state(sm_connection_t * sm_conn){
1615688a08f9SMatthias Ringwald     sm_pairing_error(sm_conn, SM_REASON_UNSPECIFIED_REASON);
1616688a08f9SMatthias Ringwald }
1617688a08f9SMatthias Ringwald 
16189af0f475SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
1619688a08f9SMatthias Ringwald 
1620dc300847SMatthias Ringwald static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn);
1621*1d80f1e6SMatthias Ringwald static bool sm_passkey_used(stk_generation_method_t method);
1622*1d80f1e6SMatthias Ringwald static bool sm_just_works_or_numeric_comparison(stk_generation_method_t method);
1623dc300847SMatthias Ringwald 
1624b35a3de2SMatthias Ringwald static void sm_sc_start_calculating_local_confirm(sm_connection_t * sm_conn){
1625b90c4e75SMatthias Ringwald     if (setup->sm_stk_generation_method == OOB){
16261f9d84e9SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CONFIRMATION;
1627b90c4e75SMatthias Ringwald     } else {
1628b90c4e75SMatthias 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);
1629b35a3de2SMatthias Ringwald     }
1630b35a3de2SMatthias Ringwald }
1631b35a3de2SMatthias Ringwald 
1632688a08f9SMatthias Ringwald static void sm_sc_state_after_receiving_random(sm_connection_t * sm_conn){
163342134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1634688a08f9SMatthias Ringwald         // Responder
16354acf7b7bSMatthias Ringwald         if (setup->sm_stk_generation_method == OOB){
16364acf7b7bSMatthias Ringwald             // generate Nb
16374acf7b7bSMatthias Ringwald             log_info("Generate Nb");
16386ca80073SMatthias 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);
16394acf7b7bSMatthias Ringwald         } else {
1640688a08f9SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
16414acf7b7bSMatthias Ringwald         }
1642688a08f9SMatthias Ringwald     } else {
1643688a08f9SMatthias Ringwald         // Initiator role
1644688a08f9SMatthias Ringwald         switch (setup->sm_stk_generation_method){
1645688a08f9SMatthias Ringwald             case JUST_WORKS:
1646dc300847SMatthias Ringwald                 sm_sc_prepare_dhkey_check(sm_conn);
1647688a08f9SMatthias Ringwald                 break;
1648688a08f9SMatthias Ringwald 
164947fb4255SMatthias Ringwald             case NUMERIC_COMPARISON:
1650bd57ffebSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_G2;
1651688a08f9SMatthias Ringwald                 break;
1652688a08f9SMatthias Ringwald             case PK_INIT_INPUT:
1653688a08f9SMatthias Ringwald             case PK_RESP_INPUT:
165447fb4255SMatthias Ringwald             case PK_BOTH_INPUT:
16554ea43905SMatthias Ringwald                 if (setup->sm_passkey_bit < 20u) {
1656b35a3de2SMatthias Ringwald                     sm_sc_start_calculating_local_confirm(sm_conn);
1657688a08f9SMatthias Ringwald                 } else {
1658dc300847SMatthias Ringwald                     sm_sc_prepare_dhkey_check(sm_conn);
1659688a08f9SMatthias Ringwald                 }
1660688a08f9SMatthias Ringwald                 break;
1661688a08f9SMatthias Ringwald             case OOB:
166265a9a04eSMatthias Ringwald                 sm_sc_prepare_dhkey_check(sm_conn);
1663688a08f9SMatthias Ringwald                 break;
16647bbeb3adSMilanka Ringwald             default:
16657bbeb3adSMilanka Ringwald                 btstack_assert(false);
16667bbeb3adSMilanka Ringwald                 break;
1667688a08f9SMatthias Ringwald         }
1668688a08f9SMatthias Ringwald     }
1669688a08f9SMatthias Ringwald }
1670688a08f9SMatthias Ringwald 
1671aec94140SMatthias Ringwald static void sm_sc_cmac_done(uint8_t * hash){
1672688a08f9SMatthias Ringwald     log_info("sm_sc_cmac_done: ");
1673688a08f9SMatthias Ringwald     log_info_hexdump(hash, 16);
1674688a08f9SMatthias Ringwald 
1675c59d0c92SMatthias Ringwald     if (sm_sc_oob_state == SM_SC_OOB_W4_CONFIRM){
1676c59d0c92SMatthias Ringwald         sm_sc_oob_state = SM_SC_OOB_IDLE;
1677a680ba6bSMatthias Ringwald         (*sm_sc_oob_callback)(hash, sm_sc_oob_random);
1678c59d0c92SMatthias Ringwald         return;
1679c59d0c92SMatthias Ringwald     }
1680c59d0c92SMatthias Ringwald 
1681bd57ffebSMatthias Ringwald     sm_connection_t * sm_conn = sm_cmac_connection;
1682bd57ffebSMatthias Ringwald     sm_cmac_connection = NULL;
16836857ad8fSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
16842bacf595SMatthias Ringwald     link_key_type_t link_key_type;
1685b4f65634SMatthias Ringwald #endif
1686bd57ffebSMatthias Ringwald 
1687bd57ffebSMatthias Ringwald     switch (sm_conn->sm_engine_state){
1688aec94140SMatthias Ringwald         case SM_SC_W4_CMAC_FOR_CONFIRMATION:
16896535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_confirm, hash, 16);
1690bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_CONFIRMATION;
1691aec94140SMatthias Ringwald             break;
1692688a08f9SMatthias Ringwald         case SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION:
1693688a08f9SMatthias Ringwald             // check
1694688a08f9SMatthias Ringwald             if (0 != memcmp(hash, setup->sm_peer_confirm, 16)){
1695bd57ffebSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CONFIRM_VALUE_FAILED);
1696688a08f9SMatthias Ringwald                 break;
1697688a08f9SMatthias Ringwald             }
1698bd57ffebSMatthias Ringwald             sm_sc_state_after_receiving_random(sm_conn);
1699688a08f9SMatthias Ringwald             break;
1700901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_G2: {
1701901c000fSMatthias Ringwald             uint32_t vab = big_endian_read_32(hash, 12) % 1000000;
1702901c000fSMatthias Ringwald             big_endian_store_32(setup->sm_tk, 12, vab);
1703901c000fSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
1704901c000fSMatthias Ringwald             sm_trigger_user_response(sm_conn);
1705019005a0SMatthias Ringwald             break;
1706019005a0SMatthias Ringwald         }
17070346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_SALT:
17086535961aSMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
1709bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_MACKEY;
17100346c37cSMatthias Ringwald             break;
17110346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_MACKEY:
17126535961aSMatthias Ringwald             (void)memcpy(setup->sm_mackey, hash, 16);
1713bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_LTK;
17140346c37cSMatthias Ringwald             break;
17150346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_LTK:
1716b18300a6SMatthias Ringwald             // truncate sm_ltk, but keep full LTK for cross-transport key derivation in sm_local_ltk
1717b18300a6SMatthias Ringwald             // Errata Service Release to the Bluetooth Specification: ESR09
1718b18300a6SMatthias Ringwald             //   E6405 – Cross transport key derivation from a key of size less than 128 bits
1719b18300a6SMatthias Ringwald             //   Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
17206535961aSMatthias Ringwald             (void)memcpy(setup->sm_ltk, hash, 16);
17216535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_ltk, hash, 16);
1722893e9333SMatthias Ringwald             sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
1723bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK;
1724019005a0SMatthias Ringwald             break;
1725901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
17266535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_dhkey_check, hash, 16);
172742134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1728901c000fSMatthias Ringwald                 // responder
1729f688bdb8SMatthias Ringwald                 if ((setup->sm_state_vars & SM_STATE_VAR_DHKEY_COMMAND_RECEIVED) != 0u){
1730901c000fSMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
1731901c000fSMatthias Ringwald                 } else {
1732901c000fSMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
1733901c000fSMatthias Ringwald                 }
1734901c000fSMatthias Ringwald             } else {
1735901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
1736901c000fSMatthias Ringwald             }
1737901c000fSMatthias Ringwald             break;
1738901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
1739901c000fSMatthias Ringwald             if (0 != memcmp(hash, setup->sm_peer_dhkey_check, 16) ){
1740901c000fSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
1741aec94140SMatthias Ringwald                 break;
1742aec94140SMatthias Ringwald             }
174342134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1744901c000fSMatthias Ringwald                 // responder
1745901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
1746901c000fSMatthias Ringwald             } else {
1747901c000fSMatthias Ringwald                 // initiator
1748901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
1749bd57ffebSMatthias Ringwald             }
1750901c000fSMatthias Ringwald             break;
17516857ad8fSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
175257132f12SMatthias Ringwald         case SM_SC_W4_CALCULATE_ILK:
17536535961aSMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
175457132f12SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY;
17552bacf595SMatthias Ringwald             break;
175657132f12SMatthias Ringwald         case SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY:
17572bacf595SMatthias Ringwald             reverse_128(hash, setup->sm_t);
17582bacf595SMatthias Ringwald             link_key_type = sm_conn->sm_connection_authenticated ?
17592bacf595SMatthias Ringwald                 AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256 : UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
17608974e43fSMatthias Ringwald             log_info("Derived classic link key from LE using h6, type %u", (int) link_key_type);
176155160b1cSMatthias Ringwald 			gap_store_link_key_for_bd_addr(setup->sm_peer_address, setup->sm_t, link_key_type);
17628974e43fSMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
17632bacf595SMatthias Ringwald                 sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
17642bacf595SMatthias Ringwald             } else {
17652bacf595SMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
17662bacf595SMatthias Ringwald             }
17670ccf6c9cSMatthias Ringwald             sm_pairing_complete(sm_conn, ERROR_CODE_SUCCESS, 0);
17682bacf595SMatthias Ringwald             sm_done_for_handle(sm_conn->sm_handle);
17692bacf595SMatthias Ringwald             break;
1770e0a03c85SMatthias Ringwald         case SM_BR_EDR_W4_CALCULATE_ILK:
1771e0a03c85SMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
1772e0a03c85SMatthias Ringwald             sm_conn->sm_engine_state = SM_BR_EDR_W2_CALCULATE_LE_LTK;
1773e0a03c85SMatthias Ringwald             break;
1774e0a03c85SMatthias Ringwald         case SM_BR_EDR_W4_CALCULATE_LE_LTK:
1775e0a03c85SMatthias Ringwald             log_info("Derived LE LTK from BR/EDR Link Key");
1776e0a03c85SMatthias Ringwald             log_info_key("Link Key", hash);
1777e0a03c85SMatthias Ringwald             (void)memcpy(setup->sm_ltk, hash, 16);
1778e0a03c85SMatthias Ringwald             sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
1779e0a03c85SMatthias Ringwald             sm_conn->sm_connection_authenticated = setup->sm_link_key_type == AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
1780e0a03c85SMatthias Ringwald             sm_store_bonding_information(sm_conn);
1781c18be159SMatthias Ringwald             sm_done_for_handle(sm_conn->sm_handle);
1782e0a03c85SMatthias Ringwald             break;
1783bdb14b0eSMatthias Ringwald #endif
1784bd57ffebSMatthias Ringwald         default:
1785bd57ffebSMatthias Ringwald             log_error("sm_sc_cmac_done in state %u", sm_conn->sm_engine_state);
1786bd57ffebSMatthias Ringwald             break;
1787bd57ffebSMatthias Ringwald     }
178870b44dd4SMatthias Ringwald     sm_trigger_run();
1789aec94140SMatthias Ringwald }
1790aec94140SMatthias Ringwald 
1791688a08f9SMatthias 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){
1792dc300847SMatthias Ringwald     const uint16_t message_len = 65;
1793aec94140SMatthias Ringwald     sm_cmac_connection = sm_conn;
17946535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, u, 32);
17956535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, v, 32);
1796aec94140SMatthias Ringwald     sm_cmac_sc_buffer[64] = z;
1797aec94140SMatthias Ringwald     log_info("f4 key");
1798aec94140SMatthias Ringwald     log_info_hexdump(x, 16);
1799aec94140SMatthias Ringwald     log_info("f4 message");
1800dc300847SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1801d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(x, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1802aec94140SMatthias Ringwald }
1803aec94140SMatthias Ringwald 
18040346c37cSMatthias Ringwald static const uint8_t f5_key_id[] = { 0x62, 0x74, 0x6c, 0x65 };
18050346c37cSMatthias Ringwald static const uint8_t f5_length[] = { 0x01, 0x00};
18060346c37cSMatthias Ringwald 
18070346c37cSMatthias Ringwald static void f5_calculate_salt(sm_connection_t * sm_conn){
18088334d3d8SMatthias Ringwald 
18098334d3d8SMatthias Ringwald     static const sm_key_t f5_salt = { 0x6C ,0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38, 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE};
18108334d3d8SMatthias Ringwald 
181140c5d850SMatthias Ringwald     log_info("f5_calculate_salt");
18120346c37cSMatthias Ringwald     // calculate salt for f5
18130346c37cSMatthias Ringwald     const uint16_t message_len = 32;
18140346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18156535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, setup->sm_dhkey, message_len);
1816d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(f5_salt, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18170346c37cSMatthias Ringwald }
18180346c37cSMatthias Ringwald 
18190346c37cSMatthias 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){
18200346c37cSMatthias Ringwald     const uint16_t message_len = 53;
18210346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18220346c37cSMatthias Ringwald 
18230346c37cSMatthias Ringwald     // f5(W, N1, N2, A1, A2) = AES-CMACT (Counter = 0 || keyID || N1 || N2|| A1|| A2 || Length = 256) -- this is the MacKey
18240346c37cSMatthias Ringwald     sm_cmac_sc_buffer[0] = 0;
18256535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 01, f5_key_id, 4);
18266535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 05, n1, 16);
18276535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 21, n2, 16);
18286535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 37, a1, 7);
18296535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 44, a2, 7);
18306535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 51, f5_length, 2);
18310346c37cSMatthias Ringwald     log_info("f5 key");
18320346c37cSMatthias Ringwald     log_info_hexdump(t, 16);
18330346c37cSMatthias Ringwald     log_info("f5 message for MacKey");
18340346c37cSMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1835d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(t, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18360346c37cSMatthias Ringwald }
18370346c37cSMatthias Ringwald 
18380346c37cSMatthias Ringwald static void f5_calculate_mackey(sm_connection_t * sm_conn){
18390346c37cSMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
18400346c37cSMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
18410346c37cSMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
18426535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
18436535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
184442134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
18450346c37cSMatthias Ringwald         // responder
18460346c37cSMatthias Ringwald         f5_mackkey(sm_conn, setup->sm_t, setup->sm_peer_nonce, setup->sm_local_nonce, bd_addr_master, bd_addr_slave);
18470346c37cSMatthias Ringwald     } else {
18480346c37cSMatthias Ringwald         // initiator
18490346c37cSMatthias Ringwald         f5_mackkey(sm_conn, setup->sm_t, setup->sm_local_nonce, setup->sm_peer_nonce, bd_addr_master, bd_addr_slave);
18500346c37cSMatthias Ringwald     }
18510346c37cSMatthias Ringwald }
18520346c37cSMatthias Ringwald 
18530346c37cSMatthias Ringwald // note: must be called right after f5_mackey, as sm_cmac_buffer[1..52] will be reused
18540346c37cSMatthias Ringwald static inline void f5_ltk(sm_connection_t * sm_conn, sm_key_t t){
18550346c37cSMatthias Ringwald     const uint16_t message_len = 53;
18560346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18570346c37cSMatthias Ringwald     sm_cmac_sc_buffer[0] = 1;
18580346c37cSMatthias Ringwald     // 1..52 setup before
18590346c37cSMatthias Ringwald     log_info("f5 key");
18600346c37cSMatthias Ringwald     log_info_hexdump(t, 16);
18610346c37cSMatthias Ringwald     log_info("f5 message for LTK");
18620346c37cSMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1863d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(t, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18640346c37cSMatthias Ringwald }
1865f92edc8eSMatthias Ringwald 
18660346c37cSMatthias Ringwald static void f5_calculate_ltk(sm_connection_t * sm_conn){
18670346c37cSMatthias Ringwald     f5_ltk(sm_conn, setup->sm_t);
18680346c37cSMatthias Ringwald }
18690346c37cSMatthias Ringwald 
187031f061fbSMatthias 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){
18716535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, n1, 16);
18726535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 16, n2, 16);
18736535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, r, 16);
18746535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 48, io_cap, 3);
18756535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 51, a1, 7);
18766535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 58, a2, 7);
187731f061fbSMatthias Ringwald }
187831f061fbSMatthias Ringwald 
187931f061fbSMatthias Ringwald static void f6_engine(sm_connection_t * sm_conn, const sm_key_t w){
188031f061fbSMatthias Ringwald     const uint16_t message_len = 65;
188131f061fbSMatthias Ringwald     sm_cmac_connection = sm_conn;
1882dc300847SMatthias Ringwald     log_info("f6 key");
1883dc300847SMatthias Ringwald     log_info_hexdump(w, 16);
1884dc300847SMatthias Ringwald     log_info("f6 message");
1885dc300847SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1886d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(w, 65, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1887dc300847SMatthias Ringwald }
1888dc300847SMatthias Ringwald 
1889f92edc8eSMatthias Ringwald // g2(U, V, X, Y) = AES-CMACX(U || V || Y) mod 2^32
1890f92edc8eSMatthias Ringwald // - U is 256 bits
1891f92edc8eSMatthias Ringwald // - V is 256 bits
1892f92edc8eSMatthias Ringwald // - X is 128 bits
1893f92edc8eSMatthias Ringwald // - Y is 128 bits
1894bd57ffebSMatthias 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){
1895bd57ffebSMatthias Ringwald     const uint16_t message_len = 80;
1896bd57ffebSMatthias Ringwald     sm_cmac_connection = sm_conn;
18976535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, u, 32);
18986535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, v, 32);
18996535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 64, y, 16);
1900f92edc8eSMatthias Ringwald     log_info("g2 key");
1901f92edc8eSMatthias Ringwald     log_info_hexdump(x, 16);
1902f92edc8eSMatthias Ringwald     log_info("g2 message");
19032bacf595SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1904d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(x, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1905f92edc8eSMatthias Ringwald }
1906f92edc8eSMatthias Ringwald 
1907b35a3de2SMatthias Ringwald static void g2_calculate(sm_connection_t * sm_conn) {
1908f92edc8eSMatthias Ringwald     // calc Va if numeric comparison
190942134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1910f92edc8eSMatthias Ringwald         // responder
1911fc5bff5fSMatthias Ringwald         g2_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, setup->sm_local_nonce);;
1912f92edc8eSMatthias Ringwald     } else {
1913f92edc8eSMatthias Ringwald         // initiator
1914fc5bff5fSMatthias Ringwald         g2_engine(sm_conn, ec_q, setup->sm_peer_q, setup->sm_local_nonce, setup->sm_peer_nonce);
1915f92edc8eSMatthias Ringwald     }
1916f92edc8eSMatthias Ringwald }
1917f92edc8eSMatthias Ringwald 
1918945888f5SMatthias Ringwald static void sm_sc_calculate_local_confirm(sm_connection_t * sm_conn){
19199af0f475SMatthias Ringwald     uint8_t z = 0;
192040c5d850SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method)){
19219af0f475SMatthias Ringwald         // some form of passkey
19229af0f475SMatthias Ringwald         uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
19234ea43905SMatthias Ringwald         z = 0x80u | ((pk >> setup->sm_passkey_bit) & 1u);
19249af0f475SMatthias Ringwald         setup->sm_passkey_bit++;
19259af0f475SMatthias Ringwald     }
1926fc5bff5fSMatthias Ringwald     f4_engine(sm_conn, ec_q, setup->sm_peer_q, setup->sm_local_nonce, z);
19279af0f475SMatthias Ringwald }
1928688a08f9SMatthias Ringwald 
1929688a08f9SMatthias Ringwald static void sm_sc_calculate_remote_confirm(sm_connection_t * sm_conn){
1930a680ba6bSMatthias Ringwald     // OOB
1931a680ba6bSMatthias Ringwald     if (setup->sm_stk_generation_method == OOB){
19324acf7b7bSMatthias Ringwald         if (IS_RESPONDER(sm_conn->sm_role)){
19334acf7b7bSMatthias Ringwald             f4_engine(sm_conn, setup->sm_peer_q, setup->sm_peer_q, setup->sm_ra, 0);
19344acf7b7bSMatthias Ringwald         } else {
19354acf7b7bSMatthias Ringwald             f4_engine(sm_conn, setup->sm_peer_q, setup->sm_peer_q, setup->sm_rb, 0);
19364acf7b7bSMatthias Ringwald         }
1937a680ba6bSMatthias Ringwald         return;
1938a680ba6bSMatthias Ringwald     }
1939a680ba6bSMatthias Ringwald 
1940688a08f9SMatthias Ringwald     uint8_t z = 0;
194140c5d850SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method)){
1942688a08f9SMatthias Ringwald         // some form of passkey
1943688a08f9SMatthias Ringwald         uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
1944688a08f9SMatthias Ringwald         // sm_passkey_bit was increased before sending confirm value
19454ea43905SMatthias Ringwald         z = 0x80u | ((pk >> (setup->sm_passkey_bit-1u)) & 1u);
1946688a08f9SMatthias Ringwald     }
1947fc5bff5fSMatthias Ringwald     f4_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, z);
1948688a08f9SMatthias Ringwald }
1949688a08f9SMatthias Ringwald 
19500346c37cSMatthias Ringwald static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn){
1951f688bdb8SMatthias Ringwald     log_info("sm_sc_prepare_dhkey_check, DHKEY calculated %u", (setup->sm_state_vars & SM_STATE_VAR_DHKEY_CALCULATED) != 0 ? 1 : 0);
19523cf37b8cSMatthias Ringwald 
1953f688bdb8SMatthias Ringwald     if ((setup->sm_state_vars & SM_STATE_VAR_DHKEY_CALCULATED) != 0u){
19543cf37b8cSMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
19553cf37b8cSMatthias Ringwald     } else {
19563cf37b8cSMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W4_CALCULATE_DHKEY;
19573cf37b8cSMatthias Ringwald     }
1958d1a1f6a4SMatthias Ringwald }
19593cf37b8cSMatthias Ringwald 
1960d1a1f6a4SMatthias Ringwald static void sm_sc_dhkey_calculated(void * arg){
1961f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
1962f3582630SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
1963f3582630SMatthias Ringwald     if (sm_conn == NULL) return;
1964f3582630SMatthias Ringwald 
19651c34405fSMatthias Ringwald     // check for invalid public key detected by Controller
19661c34405fSMatthias Ringwald     if (sm_is_ff(setup->sm_dhkey, 32)){
19671c34405fSMatthias Ringwald         log_info("sm: peer public key invalid");
19681c34405fSMatthias Ringwald         sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
19691c34405fSMatthias Ringwald         return;
19701c34405fSMatthias Ringwald     }
19711c34405fSMatthias Ringwald 
1972d1a1f6a4SMatthias Ringwald     log_info("dhkey");
1973d1a1f6a4SMatthias Ringwald     log_info_hexdump(&setup->sm_dhkey[0], 32);
1974d1a1f6a4SMatthias Ringwald     setup->sm_state_vars |= SM_STATE_VAR_DHKEY_CALCULATED;
1975d1a1f6a4SMatthias Ringwald     // trigger next step
1976d1a1f6a4SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_CALCULATE_DHKEY){
1977d1a1f6a4SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
1978d1a1f6a4SMatthias Ringwald     }
197970b44dd4SMatthias Ringwald     sm_trigger_run();
1980dc300847SMatthias Ringwald }
1981dc300847SMatthias Ringwald 
1982dc300847SMatthias Ringwald static void sm_sc_calculate_f6_for_dhkey_check(sm_connection_t * sm_conn){
1983dc300847SMatthias Ringwald     // calculate DHKCheck
1984dc300847SMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
1985dc300847SMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
1986dc300847SMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
19876535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
19886535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
1989dc300847SMatthias Ringwald     uint8_t iocap_a[3];
1990dc300847SMatthias Ringwald     iocap_a[0] = sm_pairing_packet_get_auth_req(setup->sm_m_preq);
1991dc300847SMatthias Ringwald     iocap_a[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq);
1992dc300847SMatthias Ringwald     iocap_a[2] = sm_pairing_packet_get_io_capability(setup->sm_m_preq);
1993dc300847SMatthias Ringwald     uint8_t iocap_b[3];
1994dc300847SMatthias Ringwald     iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
1995dc300847SMatthias Ringwald     iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
1996dc300847SMatthias Ringwald     iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
199742134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1998dc300847SMatthias Ringwald         // responder
199931f061fbSMatthias Ringwald         f6_setup(setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
200031f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2001dc300847SMatthias Ringwald     } else {
2002dc300847SMatthias Ringwald         // initiator
200331f061fbSMatthias Ringwald         f6_setup( setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
200431f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2005dc300847SMatthias Ringwald     }
2006dc300847SMatthias Ringwald }
2007dc300847SMatthias Ringwald 
2008019005a0SMatthias Ringwald static void sm_sc_calculate_f6_to_verify_dhkey_check(sm_connection_t * sm_conn){
2009019005a0SMatthias Ringwald     // validate E = f6()
2010019005a0SMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
2011019005a0SMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
2012019005a0SMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
20136535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
20146535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
2015019005a0SMatthias Ringwald 
2016019005a0SMatthias Ringwald     uint8_t iocap_a[3];
2017019005a0SMatthias Ringwald     iocap_a[0] = sm_pairing_packet_get_auth_req(setup->sm_m_preq);
2018019005a0SMatthias Ringwald     iocap_a[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq);
2019019005a0SMatthias Ringwald     iocap_a[2] = sm_pairing_packet_get_io_capability(setup->sm_m_preq);
2020019005a0SMatthias Ringwald     uint8_t iocap_b[3];
2021019005a0SMatthias Ringwald     iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
2022019005a0SMatthias Ringwald     iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
2023019005a0SMatthias Ringwald     iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
202442134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
2025019005a0SMatthias Ringwald         // responder
202631f061fbSMatthias Ringwald         f6_setup(setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
202731f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2028019005a0SMatthias Ringwald     } else {
2029019005a0SMatthias Ringwald         // initiator
203031f061fbSMatthias Ringwald         f6_setup(setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
203131f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2032019005a0SMatthias Ringwald     }
2033019005a0SMatthias Ringwald }
20342bacf595SMatthias Ringwald 
203555c62cf5SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
20362bacf595SMatthias Ringwald 
20372bacf595SMatthias Ringwald //
20382bacf595SMatthias Ringwald // Link Key Conversion Function h6
20392bacf595SMatthias Ringwald //
204057132f12SMatthias Ringwald // h6(W, keyID) = AES-CMAC_W(keyID)
20412bacf595SMatthias Ringwald // - W is 128 bits
20422bacf595SMatthias Ringwald // - keyID is 32 bits
20432bacf595SMatthias Ringwald static void h6_engine(sm_connection_t * sm_conn, const sm_key_t w, const uint32_t key_id){
20442bacf595SMatthias Ringwald     const uint16_t message_len = 4;
20452bacf595SMatthias Ringwald     sm_cmac_connection = sm_conn;
20462bacf595SMatthias Ringwald     big_endian_store_32(sm_cmac_sc_buffer, 0, key_id);
20472bacf595SMatthias Ringwald     log_info("h6 key");
20482bacf595SMatthias Ringwald     log_info_hexdump(w, 16);
20492bacf595SMatthias Ringwald     log_info("h6 message");
20502bacf595SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
2051d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(w, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
20522bacf595SMatthias Ringwald }
205357132f12SMatthias Ringwald //
205457132f12SMatthias Ringwald // Link Key Conversion Function h7
205557132f12SMatthias Ringwald //
205657132f12SMatthias Ringwald // h7(SALT, W) = AES-CMAC_SALT(W)
205757132f12SMatthias Ringwald // - SALT is 128 bits
205857132f12SMatthias Ringwald // - W    is 128 bits
205957132f12SMatthias Ringwald static void h7_engine(sm_connection_t * sm_conn, const sm_key_t salt, const sm_key_t w) {
206057132f12SMatthias Ringwald 	const uint16_t message_len = 16;
206157132f12SMatthias Ringwald 	sm_cmac_connection = sm_conn;
206257132f12SMatthias Ringwald 	log_info("h7 key");
206357132f12SMatthias Ringwald 	log_info_hexdump(salt, 16);
206457132f12SMatthias Ringwald 	log_info("h7 message");
206557132f12SMatthias Ringwald 	log_info_hexdump(w, 16);
206657132f12SMatthias Ringwald 	sm_cmac_message_start(salt, message_len, w, &sm_sc_cmac_done);
206757132f12SMatthias Ringwald }
20682bacf595SMatthias Ringwald 
2069b18300a6SMatthias Ringwald // For SC, setup->sm_local_ltk holds full LTK (sm_ltk is already truncated)
2070b18300a6SMatthias Ringwald // Errata Service Release to the Bluetooth Specification: ESR09
2071b18300a6SMatthias Ringwald //   E6405 – Cross transport key derivation from a key of size less than 128 bits
2072b18300a6SMatthias Ringwald //   "Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
207357132f12SMatthias Ringwald 
2074c82679c3SMatthias Ringwald static void h6_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn){
2075b18300a6SMatthias Ringwald     h6_engine(sm_conn, setup->sm_local_ltk, 0x746D7031);    // "tmp1"
20762bacf595SMatthias Ringwald }
20772bacf595SMatthias Ringwald 
2078e0a03c85SMatthias Ringwald static void h6_calculate_ilk_from_br_edr(sm_connection_t * sm_conn){
2079e0a03c85SMatthias Ringwald     h6_engine(sm_conn, setup->sm_link_key, 0x746D7032);    // "tmp2"
2080e0a03c85SMatthias Ringwald }
2081e0a03c85SMatthias Ringwald 
20822bacf595SMatthias Ringwald static void h6_calculate_br_edr_link_key(sm_connection_t * sm_conn){
20832bacf595SMatthias Ringwald     h6_engine(sm_conn, setup->sm_t, 0x6c656272);    // "lebr"
20842bacf595SMatthias Ringwald }
20852bacf595SMatthias Ringwald 
2086e0a03c85SMatthias Ringwald static void h6_calculate_le_ltk(sm_connection_t * sm_conn){
2087e0a03c85SMatthias Ringwald     h6_engine(sm_conn, setup->sm_t, 0x62726C65);    // "brle"
2088e0a03c85SMatthias Ringwald }
2089e0a03c85SMatthias Ringwald 
2090c82679c3SMatthias Ringwald static void h7_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn){
209157132f12SMatthias Ringwald 	const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x31};  // "tmp1"
209257132f12SMatthias Ringwald 	h7_engine(sm_conn, salt, setup->sm_local_ltk);
209357132f12SMatthias Ringwald }
2094e0a03c85SMatthias Ringwald 
2095e0a03c85SMatthias Ringwald static void h7_calculate_ilk_from_br_edr(sm_connection_t * sm_conn){
2096e0a03c85SMatthias Ringwald     const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x32};  // "tmp2"
2097e0a03c85SMatthias Ringwald     h7_engine(sm_conn, salt, setup->sm_link_key);
2098e0a03c85SMatthias Ringwald }
2099e0a03c85SMatthias Ringwald 
2100c18be159SMatthias Ringwald static void sm_ctkd_fetch_br_edr_link_key(sm_connection_t * sm_conn){
2101e0a03c85SMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(sm_conn->sm_handle);
2102e0a03c85SMatthias Ringwald     btstack_assert(hci_connection != NULL);
2103e0a03c85SMatthias Ringwald     reverse_128(hci_connection->link_key, setup->sm_link_key);
2104e0a03c85SMatthias Ringwald     setup->sm_link_key_type =  hci_connection->link_key_type;
2105e0a03c85SMatthias Ringwald }
2106e0a03c85SMatthias Ringwald 
210713aed524SMatthias Ringwald static void sm_ctkd_start_from_br_edr(sm_connection_t * sm_conn){
210813aed524SMatthias Ringwald     // only derive LTK if EncKey is set by both
210913aed524SMatthias Ringwald     bool derive_ltk = (sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres) &
211013aed524SMatthias Ringwald                               sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres) & SM_KEYDIST_ENC_KEY) != 0;
211113aed524SMatthias Ringwald     if (derive_ltk){
2112c18be159SMatthias 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;
211313aed524SMatthias Ringwald         sm_conn->sm_engine_state = use_h7 ? SM_BR_EDR_W2_CALCULATE_ILK_USING_H7 : SM_BR_EDR_W2_CALCULATE_ILK_USING_H6;
211413aed524SMatthias Ringwald     } else {
211513aed524SMatthias Ringwald         sm_done_for_handle(sm_conn->sm_handle);
211613aed524SMatthias Ringwald     }
2117c18be159SMatthias Ringwald }
2118c18be159SMatthias Ringwald 
21199af0f475SMatthias Ringwald #endif
21209af0f475SMatthias Ringwald 
212155c62cf5SMatthias Ringwald #endif
212255c62cf5SMatthias Ringwald 
2123613da3deSMatthias Ringwald // key management legacy connections:
2124613da3deSMatthias Ringwald // - potentially two different LTKs based on direction. each device stores LTK provided by peer
2125613da3deSMatthias Ringwald // - master stores LTK, EDIV, RAND. responder optionally stored master LTK (only if it needs to reconnect)
2126613da3deSMatthias Ringwald // - initiators reconnects: initiator uses stored LTK, EDIV, RAND generated by responder
2127613da3deSMatthias Ringwald // - responder  reconnects: responder uses LTK receveived from master
2128613da3deSMatthias Ringwald 
2129613da3deSMatthias Ringwald // key management secure connections:
2130613da3deSMatthias Ringwald // - both devices store same LTK from ECDH key exchange.
2131613da3deSMatthias Ringwald 
213242134bc6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) || defined(ENABLE_LE_CENTRAL)
21335829ebe2SMatthias Ringwald static void sm_load_security_info(sm_connection_t * sm_connection){
21345829ebe2SMatthias Ringwald     int encryption_key_size;
21355829ebe2SMatthias Ringwald     int authenticated;
21365829ebe2SMatthias Ringwald     int authorized;
21373dc3a67dSMatthias Ringwald     int secure_connection;
21385829ebe2SMatthias Ringwald 
21395829ebe2SMatthias Ringwald     // fetch data from device db - incl. authenticated/authorized/key size. Note all sm_connection_X require encryption enabled
21405829ebe2SMatthias Ringwald     le_device_db_encryption_get(sm_connection->sm_le_db_index, &setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
21413dc3a67dSMatthias Ringwald                                 &encryption_key_size, &authenticated, &authorized, &secure_connection);
21423dc3a67dSMatthias 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);
21435829ebe2SMatthias Ringwald     sm_connection->sm_actual_encryption_key_size = encryption_key_size;
21445829ebe2SMatthias Ringwald     sm_connection->sm_connection_authenticated = authenticated;
21455829ebe2SMatthias Ringwald     sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
21463dc3a67dSMatthias Ringwald     sm_connection->sm_connection_sc = secure_connection;
21475829ebe2SMatthias Ringwald }
214842134bc6SMatthias Ringwald #endif
2149bd57ffebSMatthias Ringwald 
215042134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
215159066796SMatthias Ringwald static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_connection){
21526535961aSMatthias Ringwald     (void)memcpy(setup->sm_local_rand, sm_connection->sm_local_rand, 8);
215359066796SMatthias Ringwald     setup->sm_local_ediv = sm_connection->sm_local_ediv;
215459066796SMatthias Ringwald     // re-establish used key encryption size
215559066796SMatthias Ringwald     // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
21564ea43905SMatthias Ringwald     sm_connection->sm_actual_encryption_key_size = (setup->sm_local_rand[7u] & 0x0fu) + 1u;
215759066796SMatthias Ringwald     // no db for authenticated flag hack: flag is stored in bit 4 of LSB
21584ea43905SMatthias Ringwald     sm_connection->sm_connection_authenticated = (setup->sm_local_rand[7u] & 0x10u) >> 4u;
21593dc3a67dSMatthias Ringwald     // Legacy paring -> not SC
21603dc3a67dSMatthias Ringwald     sm_connection->sm_connection_sc = 0;
216159066796SMatthias Ringwald     log_info("sm: received ltk request with key size %u, authenticated %u",
216259066796SMatthias Ringwald             sm_connection->sm_actual_encryption_key_size, sm_connection->sm_connection_authenticated);
216359066796SMatthias Ringwald }
216442134bc6SMatthias Ringwald #endif
216559066796SMatthias Ringwald 
21663deb3ec6SMatthias Ringwald // distributed key generation
2167d7f1c72eSMatthias Ringwald static bool sm_run_dpkg(void){
21683deb3ec6SMatthias Ringwald     switch (dkg_state){
21693deb3ec6SMatthias Ringwald         case DKG_CALC_IRK:
21703deb3ec6SMatthias Ringwald             // already busy?
21713deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2172d1a1f6a4SMatthias Ringwald                 log_info("DKG_CALC_IRK started");
21733deb3ec6SMatthias Ringwald                 // IRK = d1(IR, 1, 0)
2174d1a1f6a4SMatthias Ringwald                 sm_d1_d_prime(1, 0, sm_aes128_plaintext);  // plaintext = d1 prime
2175d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2176d1a1f6a4SMatthias 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);
2177d7f1c72eSMatthias Ringwald                 return true;
21783deb3ec6SMatthias Ringwald             }
21793deb3ec6SMatthias Ringwald             break;
21803deb3ec6SMatthias Ringwald         case DKG_CALC_DHK:
21813deb3ec6SMatthias Ringwald             // already busy?
21823deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2183d1a1f6a4SMatthias Ringwald                 log_info("DKG_CALC_DHK started");
21843deb3ec6SMatthias Ringwald                 // DHK = d1(IR, 3, 0)
2185d1a1f6a4SMatthias Ringwald                 sm_d1_d_prime(3, 0, sm_aes128_plaintext);  // plaintext = d1 prime
2186d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2187d1a1f6a4SMatthias 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);
2188d7f1c72eSMatthias Ringwald                 return true;
21893deb3ec6SMatthias Ringwald             }
21903deb3ec6SMatthias Ringwald             break;
21913deb3ec6SMatthias Ringwald         default:
21923deb3ec6SMatthias Ringwald             break;
21933deb3ec6SMatthias Ringwald     }
2194d7f1c72eSMatthias Ringwald     return false;
2195d7f1c72eSMatthias Ringwald }
21963deb3ec6SMatthias Ringwald 
21973deb3ec6SMatthias Ringwald // random address updates
2198d7f1c72eSMatthias Ringwald static bool sm_run_rau(void){
21993deb3ec6SMatthias Ringwald     switch (rau_state){
2200fbd4e238SMatthias Ringwald         case RAU_GET_RANDOM:
2201fbd4e238SMatthias Ringwald             rau_state = RAU_W4_RANDOM;
22025b4dd597SMatthias Ringwald             btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_address, 6, &sm_handle_random_result_rau, NULL);
2203d7f1c72eSMatthias Ringwald             return true;
22043deb3ec6SMatthias Ringwald         case RAU_GET_ENC:
22053deb3ec6SMatthias Ringwald             // already busy?
22063deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2207d1a1f6a4SMatthias Ringwald                 sm_ah_r_prime(sm_random_address, sm_aes128_plaintext);
2208d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2209d1a1f6a4SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_irk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_rau, NULL);
2210d7f1c72eSMatthias Ringwald                 return true;
22113deb3ec6SMatthias Ringwald             }
22123deb3ec6SMatthias Ringwald             break;
22133deb3ec6SMatthias Ringwald         default:
22143deb3ec6SMatthias Ringwald             break;
22153deb3ec6SMatthias Ringwald     }
2216d7f1c72eSMatthias Ringwald     return false;
2217d7f1c72eSMatthias Ringwald }
22183deb3ec6SMatthias Ringwald 
22193deb3ec6SMatthias Ringwald // CSRK Lookup
2220d7f1c72eSMatthias Ringwald static bool sm_run_csrk(void){
2221d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
2222d7f1c72eSMatthias Ringwald 
22233deb3ec6SMatthias Ringwald     // -- if csrk lookup ready, find connection that require csrk lookup
22243deb3ec6SMatthias Ringwald     if (sm_address_resolution_idle()){
22253deb3ec6SMatthias Ringwald         hci_connections_get_iterator(&it);
2226665d90f2SMatthias Ringwald         while(btstack_linked_list_iterator_has_next(&it)){
2227665d90f2SMatthias Ringwald             hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
22283deb3ec6SMatthias Ringwald             sm_connection_t  * sm_connection  = &hci_connection->sm_connection;
22293deb3ec6SMatthias Ringwald             if (sm_connection->sm_irk_lookup_state == IRK_LOOKUP_W4_READY){
22303deb3ec6SMatthias Ringwald                 // and start lookup
22313deb3ec6SMatthias 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);
22323deb3ec6SMatthias Ringwald                 sm_connection->sm_irk_lookup_state = IRK_LOOKUP_STARTED;
22333deb3ec6SMatthias Ringwald                 break;
22343deb3ec6SMatthias Ringwald             }
22353deb3ec6SMatthias Ringwald         }
22363deb3ec6SMatthias Ringwald     }
22373deb3ec6SMatthias Ringwald 
22383deb3ec6SMatthias Ringwald     // -- if csrk lookup ready, resolved addresses for received addresses
22393deb3ec6SMatthias Ringwald     if (sm_address_resolution_idle()) {
2240665d90f2SMatthias Ringwald         if (!btstack_linked_list_empty(&sm_address_resolution_general_queue)){
22413deb3ec6SMatthias Ringwald             sm_lookup_entry_t * entry = (sm_lookup_entry_t *) sm_address_resolution_general_queue;
2242665d90f2SMatthias Ringwald             btstack_linked_list_remove(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
22433deb3ec6SMatthias Ringwald             sm_address_resolution_start_lookup(entry->address_type, 0, entry->address, ADDRESS_RESOLUTION_GENERAL, NULL);
22443deb3ec6SMatthias Ringwald             btstack_memory_sm_lookup_entry_free(entry);
22453deb3ec6SMatthias Ringwald         }
22463deb3ec6SMatthias Ringwald     }
22473deb3ec6SMatthias Ringwald 
2248ca685291SMatthias Ringwald     // -- Continue with device lookup by public or resolvable private address
22493deb3ec6SMatthias Ringwald     if (!sm_address_resolution_idle()){
2250092ec58eSMatthias Ringwald         while (sm_address_resolution_test < le_device_db_max_count()){
2251adf5eaa9SMatthias Ringwald             int addr_type = BD_ADDR_TYPE_UNKNOWN;
22523deb3ec6SMatthias Ringwald             bd_addr_t addr;
22533deb3ec6SMatthias Ringwald             sm_key_t irk;
22543deb3ec6SMatthias Ringwald             le_device_db_info(sm_address_resolution_test, &addr_type, addr, irk);
22553deb3ec6SMatthias Ringwald 
2256adf5eaa9SMatthias Ringwald             // skip unused entries
2257adf5eaa9SMatthias Ringwald             if (addr_type == BD_ADDR_TYPE_UNKNOWN){
2258adf5eaa9SMatthias Ringwald                 sm_address_resolution_test++;
2259adf5eaa9SMatthias Ringwald                 continue;
2260adf5eaa9SMatthias Ringwald             }
2261adf5eaa9SMatthias Ringwald 
2262ca685291SMatthias Ringwald             log_info("LE Device Lookup: device %u of %u", sm_address_resolution_test, le_device_db_max_count());
2263ca685291SMatthias Ringwald 
2264515f33beSMatthias Ringwald             // map resolved identiry addresses to regular addresses
2265515f33beSMatthias Ringwald             int regular_addr_type = sm_address_resolution_addr_type & 1;
2266515f33beSMatthias Ringwald             if ((regular_addr_type == addr_type) && (memcmp(addr, sm_address_resolution_address, 6) == 0)){
2267ca685291SMatthias Ringwald                 log_info("LE Device Lookup: found by { addr_type, address} ");
2268a66b030fSMatthias Ringwald                 sm_address_resolution_handle_event(ADDRESS_RESOLUTION_SUCCEEDED);
22693deb3ec6SMatthias Ringwald                 break;
22703deb3ec6SMatthias Ringwald             }
22713deb3ec6SMatthias Ringwald 
2272a9987c8eSMatthias Ringwald             // if connection type is public, it must be a different one
2273a9987c8eSMatthias Ringwald             if (sm_address_resolution_addr_type == BD_ADDR_TYPE_LE_PUBLIC){
22743deb3ec6SMatthias Ringwald                 sm_address_resolution_test++;
22753deb3ec6SMatthias Ringwald                 continue;
22763deb3ec6SMatthias Ringwald             }
22773deb3ec6SMatthias Ringwald 
22788cc81b50SMatthias Ringwald             // skip AH if no IRK
22798cc81b50SMatthias Ringwald             if (sm_is_null_key(irk)){
22808cc81b50SMatthias Ringwald                 sm_address_resolution_test++;
22818cc81b50SMatthias Ringwald                 continue;
22828cc81b50SMatthias Ringwald             }
22838cc81b50SMatthias Ringwald 
22843deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_ACTIVE) break;
22853deb3ec6SMatthias Ringwald 
22863deb3ec6SMatthias Ringwald             log_info("LE Device Lookup: calculate AH");
22878314c363SMatthias Ringwald             log_info_key("IRK", irk);
22883deb3ec6SMatthias Ringwald 
22896535961aSMatthias Ringwald             (void)memcpy(sm_aes128_key, irk, 16);
2290d1a1f6a4SMatthias Ringwald             sm_ah_r_prime(sm_address_resolution_address, sm_aes128_plaintext);
2291d1a1f6a4SMatthias Ringwald             sm_aes128_state = SM_AES128_ACTIVE;
2292d1a1f6a4SMatthias 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);
2293d7f1c72eSMatthias Ringwald             return true;
22943deb3ec6SMatthias Ringwald         }
22953deb3ec6SMatthias Ringwald 
2296092ec58eSMatthias Ringwald         if (sm_address_resolution_test >= le_device_db_max_count()){
22973deb3ec6SMatthias Ringwald             log_info("LE Device Lookup: not found");
22983deb3ec6SMatthias Ringwald             sm_address_resolution_handle_event(ADDRESS_RESOLUTION_FAILED);
22993deb3ec6SMatthias Ringwald         }
23003deb3ec6SMatthias Ringwald     }
2301d7f1c72eSMatthias Ringwald     return false;
2302d7f1c72eSMatthias Ringwald }
23033deb3ec6SMatthias Ringwald 
2304d7f1c72eSMatthias Ringwald // SC OOB
2305d7f1c72eSMatthias Ringwald static bool sm_run_oob(void){
2306c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2307c59d0c92SMatthias Ringwald     switch (sm_sc_oob_state){
2308c59d0c92SMatthias Ringwald         case SM_SC_OOB_W2_CALC_CONFIRM:
2309c59d0c92SMatthias Ringwald             if (!sm_cmac_ready()) break;
2310c59d0c92SMatthias Ringwald             sm_sc_oob_state = SM_SC_OOB_W4_CONFIRM;
2311c59d0c92SMatthias Ringwald             f4_engine(NULL, ec_q, ec_q, sm_sc_oob_random, 0);
2312d7f1c72eSMatthias Ringwald             return true;
2313c59d0c92SMatthias Ringwald         default:
2314c59d0c92SMatthias Ringwald             break;
2315c59d0c92SMatthias Ringwald     }
2316c59d0c92SMatthias Ringwald #endif
2317d7f1c72eSMatthias Ringwald     return false;
2318d7f1c72eSMatthias Ringwald }
2319275aafe8SMatthias Ringwald 
2320687a03c8SMatthias Ringwald static void sm_send_connectionless(sm_connection_t * sm_connection, const uint8_t * buffer, uint16_t size){
2321687a03c8SMatthias Ringwald     l2cap_send_connectionless(sm_connection->sm_handle, sm_connection->sm_cid, (uint8_t*) buffer, size);
2322687a03c8SMatthias Ringwald }
2323687a03c8SMatthias Ringwald 
232441d32297SMatthias Ringwald // handle basic actions that don't requires the full context
2325d7f1c72eSMatthias Ringwald static bool sm_run_basic(void){
2326d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
232741d32297SMatthias Ringwald     hci_connections_get_iterator(&it);
2328e9af1bf6SMatthias Ringwald     while(btstack_linked_list_iterator_has_next(&it)){
232941d32297SMatthias Ringwald         hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
233041d32297SMatthias Ringwald         sm_connection_t  * sm_connection = &hci_connection->sm_connection;
233141d32297SMatthias Ringwald         switch(sm_connection->sm_engine_state){
2332f4935286SMatthias Ringwald 
2333f4935286SMatthias Ringwald             // general
2334f4935286SMatthias Ringwald             case SM_GENERAL_SEND_PAIRING_FAILED: {
2335f4935286SMatthias Ringwald                 uint8_t buffer[2];
2336f4935286SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_FAILED;
2337f4935286SMatthias Ringwald                 buffer[1] = sm_connection->sm_pairing_failed_reason;
2338f4935286SMatthias Ringwald                 sm_connection->sm_engine_state = sm_connection->sm_role ? SM_RESPONDER_IDLE : SM_INITIATOR_CONNECTED;
2339687a03c8SMatthias Ringwald                 sm_send_connectionless(sm_connection, (uint8_t*) buffer, sizeof(buffer));
2340f4935286SMatthias Ringwald                 sm_pairing_complete(sm_connection, ERROR_CODE_AUTHENTICATION_FAILURE, sm_connection->sm_pairing_failed_reason);
2341f4935286SMatthias Ringwald                 sm_done_for_handle(sm_connection->sm_handle);
2342f4935286SMatthias Ringwald                 break;
2343f4935286SMatthias Ringwald             }
2344f4935286SMatthias Ringwald 
234541d32297SMatthias Ringwald             // responder side
234641d32297SMatthias Ringwald             case SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY:
234741d32297SMatthias Ringwald                 sm_connection->sm_engine_state = SM_RESPONDER_IDLE;
234841d32297SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle);
2349d7f1c72eSMatthias Ringwald                 return true;
23504b8b5afeSMatthias Ringwald 
23514b8b5afeSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
23524b8b5afeSMatthias Ringwald             case SM_SC_RECEIVED_LTK_REQUEST:
23534b8b5afeSMatthias Ringwald                 switch (sm_connection->sm_irk_lookup_state){
23544b8b5afeSMatthias Ringwald                     case IRK_LOOKUP_FAILED:
2355e9af1bf6SMatthias Ringwald                         log_info("LTK Request: IRK Lookup Failed)");
23564b8b5afeSMatthias Ringwald                         sm_connection->sm_engine_state = SM_RESPONDER_IDLE;
23574b8b5afeSMatthias Ringwald                         hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle);
2358d7f1c72eSMatthias Ringwald                         return true;
23594b8b5afeSMatthias Ringwald                     default:
23604b8b5afeSMatthias Ringwald                         break;
23614b8b5afeSMatthias Ringwald                 }
23624b8b5afeSMatthias Ringwald                 break;
23634b8b5afeSMatthias Ringwald #endif
236441d32297SMatthias Ringwald             default:
236541d32297SMatthias Ringwald                 break;
236641d32297SMatthias Ringwald         }
236741d32297SMatthias Ringwald     }
2368d7f1c72eSMatthias Ringwald     return false;
2369d7f1c72eSMatthias Ringwald }
23703deb3ec6SMatthias Ringwald 
2371d7f1c72eSMatthias Ringwald static void sm_run_activate_connection(void){
23723deb3ec6SMatthias Ringwald     // Find connections that requires setup context and make active if no other is locked
2373d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
23743deb3ec6SMatthias Ringwald     hci_connections_get_iterator(&it);
23757149bde5SMatthias Ringwald     while((sm_active_connection_handle == HCI_CON_HANDLE_INVALID) && btstack_linked_list_iterator_has_next(&it)){
2376665d90f2SMatthias Ringwald         hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
23773deb3ec6SMatthias Ringwald         sm_connection_t  * sm_connection = &hci_connection->sm_connection;
23783deb3ec6SMatthias Ringwald         // - if no connection locked and we're ready/waiting for setup context, fetch it and start
23791979f09cSMatthias Ringwald         bool done = true;
23803deb3ec6SMatthias Ringwald         int err;
238142134bc6SMatthias Ringwald         UNUSED(err);
238234b6528fSMatthias Ringwald 
238334b6528fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
238434b6528fSMatthias Ringwald         // assert ec key is ready
2385505f1c30SMatthias Ringwald         if (   (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED)
2386178e8c1bSMatthias Ringwald             || (sm_connection->sm_engine_state == SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST)
2387178e8c1bSMatthias Ringwald 			|| (sm_connection->sm_engine_state == SM_RESPONDER_SEND_SECURITY_REQUEST)){
238834b6528fSMatthias Ringwald             if (ec_key_generation_state == EC_KEY_GENERATION_IDLE){
238934b6528fSMatthias Ringwald                 sm_ec_generate_new_key();
239034b6528fSMatthias Ringwald             }
239134b6528fSMatthias Ringwald             if (ec_key_generation_state != EC_KEY_GENERATION_DONE){
239234b6528fSMatthias Ringwald                 continue;
239334b6528fSMatthias Ringwald             }
239434b6528fSMatthias Ringwald         }
239534b6528fSMatthias Ringwald #endif
239634b6528fSMatthias Ringwald 
23973deb3ec6SMatthias Ringwald         switch (sm_connection->sm_engine_state) {
239842134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
23993deb3ec6SMatthias Ringwald             case SM_RESPONDER_SEND_SECURITY_REQUEST:
24003deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
240142134bc6SMatthias Ringwald             case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
2402549ad5d2SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
240306cd539fSMatthias Ringwald             case SM_SC_RECEIVED_LTK_REQUEST:
240487014f74SMatthias Ringwald #endif
240587014f74SMatthias Ringwald #endif
240634c39fbdSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
24075567aa60SMatthias Ringwald             case SM_INITIATOR_PH4_HAS_LTK:
240834c39fbdSMatthias Ringwald 			case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
2409549ad5d2SMatthias Ringwald #endif
2410c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
2411c18be159SMatthias Ringwald             case SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED:
2412c18be159SMatthias Ringwald             case SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST:
2413c18be159SMatthias Ringwald #endif
241487014f74SMatthias Ringwald 				// just lock context
241587014f74SMatthias Ringwald 				break;
24163deb3ec6SMatthias Ringwald             default:
24171979f09cSMatthias Ringwald                 done = false;
24183deb3ec6SMatthias Ringwald                 break;
24193deb3ec6SMatthias Ringwald         }
24203deb3ec6SMatthias Ringwald         if (done){
24217149bde5SMatthias Ringwald             sm_active_connection_handle = sm_connection->sm_handle;
24227149bde5SMatthias 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);
24233deb3ec6SMatthias Ringwald         }
24243deb3ec6SMatthias Ringwald     }
2425d7f1c72eSMatthias Ringwald }
2426d7f1c72eSMatthias Ringwald 
2427403280b9SMatthias Ringwald static void sm_run_send_keypress_notification(sm_connection_t * connection){
2428403280b9SMatthias Ringwald     int i;
2429403280b9SMatthias Ringwald     uint8_t flags       = setup->sm_keypress_notification & 0x1fu;
2430403280b9SMatthias Ringwald     uint8_t num_actions = setup->sm_keypress_notification >> 5;
2431403280b9SMatthias Ringwald     uint8_t action = 0;
2432403280b9SMatthias Ringwald     for (i=SM_KEYPRESS_PASSKEY_ENTRY_STARTED;i<=SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED;i++){
2433*1d80f1e6SMatthias Ringwald         if ((flags & (1u<<i)) != 0u){
2434403280b9SMatthias Ringwald             bool clear_flag = true;
2435403280b9SMatthias Ringwald             switch (i){
2436403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_ENTRY_STARTED:
2437403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_CLEARED:
2438403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED:
2439403280b9SMatthias Ringwald                 default:
2440403280b9SMatthias Ringwald                     break;
2441403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_DIGIT_ENTERED:
2442403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_DIGIT_ERASED:
2443403280b9SMatthias Ringwald                     num_actions--;
2444403280b9SMatthias Ringwald                     clear_flag = num_actions == 0u;
2445403280b9SMatthias Ringwald                     break;
2446403280b9SMatthias Ringwald             }
2447403280b9SMatthias Ringwald             if (clear_flag){
2448403280b9SMatthias Ringwald                 flags &= ~(1<<i);
2449403280b9SMatthias Ringwald             }
2450403280b9SMatthias Ringwald             action = i;
2451403280b9SMatthias Ringwald             break;
2452403280b9SMatthias Ringwald         }
2453403280b9SMatthias Ringwald     }
2454403280b9SMatthias Ringwald     setup->sm_keypress_notification = (num_actions << 5) | flags;
2455403280b9SMatthias Ringwald 
2456403280b9SMatthias Ringwald     // send keypress notification
2457403280b9SMatthias Ringwald     uint8_t buffer[2];
2458403280b9SMatthias Ringwald     buffer[0] = SM_CODE_KEYPRESS_NOTIFICATION;
2459403280b9SMatthias Ringwald     buffer[1] = action;
2460687a03c8SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2461403280b9SMatthias Ringwald 
2462403280b9SMatthias Ringwald     // try
2463384eabd3SMatthias Ringwald     l2cap_request_can_send_fix_channel_now_event(sm_active_connection_handle, connection->sm_cid);
2464403280b9SMatthias Ringwald }
2465403280b9SMatthias Ringwald 
2466403280b9SMatthias Ringwald static void sm_run_distribute_keys(sm_connection_t * connection){
2467*1d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION) != 0u){
2468403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
2469403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
2470403280b9SMatthias Ringwald         uint8_t buffer[17];
2471403280b9SMatthias Ringwald         buffer[0] = SM_CODE_ENCRYPTION_INFORMATION;
2472403280b9SMatthias Ringwald         reverse_128(setup->sm_ltk, &buffer[1]);
2473687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2474403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2475403280b9SMatthias Ringwald         return;
2476403280b9SMatthias Ringwald     }
2477*1d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_MASTER_IDENTIFICATION) != 0u){
2478403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
2479403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
2480403280b9SMatthias Ringwald         uint8_t buffer[11];
2481403280b9SMatthias Ringwald         buffer[0] = SM_CODE_MASTER_IDENTIFICATION;
2482403280b9SMatthias Ringwald         little_endian_store_16(buffer, 1, setup->sm_local_ediv);
2483403280b9SMatthias Ringwald         reverse_64(setup->sm_local_rand, &buffer[3]);
2484687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2485403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2486403280b9SMatthias Ringwald         return;
2487403280b9SMatthias Ringwald     }
2488*1d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
2489403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
2490403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
2491403280b9SMatthias Ringwald         uint8_t buffer[17];
2492403280b9SMatthias Ringwald         buffer[0] = SM_CODE_IDENTITY_INFORMATION;
2493403280b9SMatthias Ringwald         reverse_128(sm_persistent_irk, &buffer[1]);
2494687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2495403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2496403280b9SMatthias Ringwald         return;
2497403280b9SMatthias Ringwald     }
2498*1d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION) != 0u){
2499403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
2500403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
2501403280b9SMatthias Ringwald         bd_addr_t local_address;
2502403280b9SMatthias Ringwald         uint8_t buffer[8];
2503403280b9SMatthias Ringwald         buffer[0] = SM_CODE_IDENTITY_ADDRESS_INFORMATION;
2504403280b9SMatthias Ringwald         switch (gap_random_address_get_mode()){
2505403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_TYPE_OFF:
2506403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_TYPE_STATIC:
2507403280b9SMatthias Ringwald                 // public or static random
2508403280b9SMatthias Ringwald                 gap_le_get_own_address(&buffer[1], local_address);
2509403280b9SMatthias Ringwald                 break;
2510403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_NON_RESOLVABLE:
2511403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_RESOLVABLE:
2512403280b9SMatthias Ringwald                 // fallback to public
2513403280b9SMatthias Ringwald                 gap_local_bd_addr(local_address);
2514403280b9SMatthias Ringwald                 buffer[1] = 0;
2515403280b9SMatthias Ringwald                 break;
2516403280b9SMatthias Ringwald             default:
2517403280b9SMatthias Ringwald                 btstack_assert(false);
2518403280b9SMatthias Ringwald                 break;
2519403280b9SMatthias Ringwald         }
2520403280b9SMatthias Ringwald         reverse_bd_addr(local_address, &buffer[2]);
2521687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2522403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2523403280b9SMatthias Ringwald         return;
2524403280b9SMatthias Ringwald     }
2525*1d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION) != 0u){
2526403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
2527403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
2528403280b9SMatthias Ringwald 
2529403280b9SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
2530403280b9SMatthias Ringwald         // hack to reproduce test runs
2531403280b9SMatthias Ringwald                     if (test_use_fixed_local_csrk){
2532403280b9SMatthias Ringwald                         memset(setup->sm_local_csrk, 0xcc, 16);
2533403280b9SMatthias Ringwald                     }
2534403280b9SMatthias Ringwald 
2535403280b9SMatthias Ringwald                     // store local CSRK
2536403280b9SMatthias Ringwald                     if (setup->sm_le_device_index >= 0){
2537403280b9SMatthias Ringwald                         log_info("sm: store local CSRK");
2538403280b9SMatthias Ringwald                         le_device_db_local_csrk_set(setup->sm_le_device_index, setup->sm_local_csrk);
2539403280b9SMatthias Ringwald                         le_device_db_local_counter_set(setup->sm_le_device_index, 0);
2540403280b9SMatthias Ringwald                     }
2541403280b9SMatthias Ringwald #endif
2542403280b9SMatthias Ringwald 
2543403280b9SMatthias Ringwald         uint8_t buffer[17];
2544403280b9SMatthias Ringwald         buffer[0] = SM_CODE_SIGNING_INFORMATION;
2545403280b9SMatthias Ringwald         reverse_128(setup->sm_local_csrk, &buffer[1]);
2546687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2547403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2548403280b9SMatthias Ringwald         return;
2549403280b9SMatthias Ringwald     }
2550403280b9SMatthias Ringwald     btstack_assert(false);
2551403280b9SMatthias Ringwald }
2552403280b9SMatthias Ringwald 
2553bbd73538SMatthias Ringwald static bool sm_ctkd_from_le(sm_connection_t *sm_connection) {
2554bbd73538SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
2555bbd73538SMatthias Ringwald     // requirements to derive link key from  LE:
2556bbd73538SMatthias Ringwald     // - use secure connections
2557bbd73538SMatthias Ringwald     if (setup->sm_use_secure_connections == 0) return false;
2558bbd73538SMatthias Ringwald     // - bonding needs to be enabled:
2559bbd73538SMatthias 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;
2560bbd73538SMatthias Ringwald     if (!bonding_enabled) return false;
2561bbd73538SMatthias Ringwald     // - need identity address / public addr
2562bbd73538SMatthias 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);
2563bbd73538SMatthias Ringwald     if (!have_identity_address_info) return false;
2564bbd73538SMatthias 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)
2565bbd73538SMatthias Ringwald     //   this requirement is motivated by BLURtooth paper. The paper recommends to not overwrite keys at all.
2566bbd73538SMatthias Ringwald     //      If SC is authenticated, we consider it safe to overwrite a stored key.
2567bbd73538SMatthias 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.
2568bbd73538SMatthias Ringwald     uint8_t link_key[16];
2569bbd73538SMatthias Ringwald     link_key_type_t link_key_type;
2570bbd73538SMatthias Ringwald     bool have_link_key             = gap_get_link_key_for_bd_addr(setup->sm_peer_address, link_key, &link_key_type);
25717040ba26SMatthias Ringwald     bool link_key_authenticated    = gap_authenticated_for_link_key_type(link_key_type);
2572bbd73538SMatthias Ringwald     bool derived_key_authenticated = sm_connection->sm_connection_authenticated != 0;
2573bbd73538SMatthias Ringwald     if (have_link_key && link_key_authenticated && !derived_key_authenticated) {
2574bbd73538SMatthias Ringwald         return false;
2575bbd73538SMatthias Ringwald     }
2576bbd73538SMatthias Ringwald     // get started (all of the above are true)
2577bbd73538SMatthias Ringwald     return true;
2578bbd73538SMatthias Ringwald #else
2579bbd73538SMatthias Ringwald     UNUSED(sm_connection);
2580bbd73538SMatthias Ringwald 	return false;
2581bbd73538SMatthias Ringwald #endif
2582bbd73538SMatthias Ringwald }
2583bbd73538SMatthias Ringwald 
25846a718a5eSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
25856a718a5eSMatthias Ringwald static bool sm_ctkd_from_classic(sm_connection_t * sm_connection){
25866a718a5eSMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(sm_connection->sm_handle);
25876a718a5eSMatthias Ringwald     btstack_assert(hci_connection != NULL);
25886a718a5eSMatthias Ringwald     // requirements to derive ltk from BR/EDR:
25896a718a5eSMatthias Ringwald     // - BR/EDR uses secure connections
25906a718a5eSMatthias Ringwald     if (gap_secure_connection_for_link_key_type(hci_connection->link_key_type) == false) return false;
25916a718a5eSMatthias Ringwald     // - bonding needs to be enabled:
25926a718a5eSMatthias 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;
25936a718a5eSMatthias Ringwald     if (!bonding_enabled) return false;
25946a718a5eSMatthias 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)
25956a718a5eSMatthias Ringwald     bool link_key_authenticated = gap_authenticated_for_link_key_type(hci_connection->link_key_type);
25966a718a5eSMatthias Ringwald     if (link_key_authenticated) return true;
25976a718a5eSMatthias Ringwald     int index = sm_le_device_db_index_lookup(BD_ADDR_TYPE_LE_PUBLIC, hci_connection->address);
25986a718a5eSMatthias Ringwald     if (index >= 0){
25996a718a5eSMatthias Ringwald         int ltk_authenticated;
26006a718a5eSMatthias Ringwald         sm_key_t ltk;
26016a718a5eSMatthias Ringwald         le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, &ltk_authenticated, NULL, NULL);
26026a718a5eSMatthias Ringwald         bool have_ltk = !sm_is_null_key(ltk);
26036a718a5eSMatthias Ringwald         if (have_ltk && ltk_authenticated) return false;
26046a718a5eSMatthias Ringwald     }
26056a718a5eSMatthias Ringwald     return true;
26066a718a5eSMatthias Ringwald }
26076a718a5eSMatthias Ringwald #endif
26086a718a5eSMatthias Ringwald 
26096f7422f1SMatthias Ringwald static void sm_key_distribution_complete_responder(sm_connection_t * connection){
26106f7422f1SMatthias Ringwald     if (sm_ctkd_from_le(connection)){
26116f7422f1SMatthias 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;
26126f7422f1SMatthias Ringwald         connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
26136f7422f1SMatthias Ringwald     } else {
26146f7422f1SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_IDLE;
26156f7422f1SMatthias Ringwald         sm_pairing_complete(connection, ERROR_CODE_SUCCESS, 0);
26166f7422f1SMatthias Ringwald         sm_done_for_handle(connection->sm_handle);
26176f7422f1SMatthias Ringwald     }
26186f7422f1SMatthias Ringwald }
26196f7422f1SMatthias Ringwald 
2620af7ef9d1SMatthias Ringwald static void sm_key_distribution_complete_initiator(sm_connection_t * connection){
2621af7ef9d1SMatthias Ringwald     if (sm_ctkd_from_le(connection)){
2622af7ef9d1SMatthias 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;
2623af7ef9d1SMatthias Ringwald         connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
2624af7ef9d1SMatthias Ringwald     } else {
2625af7ef9d1SMatthias Ringwald         sm_master_pairing_success(connection);
2626af7ef9d1SMatthias Ringwald     }
2627af7ef9d1SMatthias Ringwald }
2628af7ef9d1SMatthias Ringwald 
2629b919f264SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2630b919f264SMatthias Ringwald static void sm_run_state_sc_send_confirmation(sm_connection_t *connection) {
2631b919f264SMatthias Ringwald     uint8_t buffer[17];
2632b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_CONFIRM;
2633b919f264SMatthias Ringwald     reverse_128(setup->sm_local_confirm, &buffer[1]);
2634b919f264SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
2635b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2636b919f264SMatthias Ringwald     } else {
2637b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2638b919f264SMatthias Ringwald     }
2639b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2640b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2641b919f264SMatthias Ringwald }
2642b919f264SMatthias Ringwald 
2643b919f264SMatthias Ringwald static void sm_run_state_sc_send_pairing_random(sm_connection_t *connection) {
2644b919f264SMatthias Ringwald     uint8_t buffer[17];
2645b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_RANDOM;
2646b919f264SMatthias Ringwald     reverse_128(setup->sm_local_nonce, &buffer[1]);
2647b919f264SMatthias Ringwald     log_info("stk method %u, bit num: %u", setup->sm_stk_generation_method, setup->sm_passkey_bit);
2648b919f264SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method) && (setup->sm_passkey_bit < 20u)){
2649b919f264SMatthias Ringwald         log_info("SM_SC_SEND_PAIRING_RANDOM A");
2650b919f264SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
2651b919f264SMatthias Ringwald             // responder
2652b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2653b919f264SMatthias Ringwald         } else {
2654b919f264SMatthias Ringwald             // initiator
2655b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2656b919f264SMatthias Ringwald         }
2657b919f264SMatthias Ringwald     } else {
2658b919f264SMatthias Ringwald         log_info("SM_SC_SEND_PAIRING_RANDOM B");
2659b919f264SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
2660b919f264SMatthias Ringwald             // responder
2661b919f264SMatthias Ringwald             if (setup->sm_stk_generation_method == NUMERIC_COMPARISON){
2662b919f264SMatthias Ringwald                 log_info("SM_SC_SEND_PAIRING_RANDOM B1");
2663b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W2_CALCULATE_G2;
2664b919f264SMatthias Ringwald             } else {
2665b919f264SMatthias Ringwald                 log_info("SM_SC_SEND_PAIRING_RANDOM B2");
2666b919f264SMatthias Ringwald                 sm_sc_prepare_dhkey_check(connection);
2667b919f264SMatthias Ringwald             }
2668b919f264SMatthias Ringwald         } else {
2669b919f264SMatthias Ringwald             // initiator
2670b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2671b919f264SMatthias Ringwald         }
2672b919f264SMatthias Ringwald     }
2673b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2674b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2675b919f264SMatthias Ringwald }
2676b919f264SMatthias Ringwald 
2677b919f264SMatthias Ringwald static void sm_run_state_sc_send_dhkey_check_command(sm_connection_t *connection) {
2678b919f264SMatthias Ringwald     uint8_t buffer[17];
2679b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_DHKEY_CHECK;
2680b919f264SMatthias Ringwald     reverse_128(setup->sm_local_dhkey_check, &buffer[1]);
2681b919f264SMatthias Ringwald 
2682b919f264SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
2683b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_LTK_REQUEST_SC;
2684b919f264SMatthias Ringwald     } else {
2685b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
2686b919f264SMatthias Ringwald     }
2687b919f264SMatthias Ringwald 
2688b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2689b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2690b919f264SMatthias Ringwald }
2691b919f264SMatthias Ringwald 
2692b919f264SMatthias Ringwald static void sm_run_state_sc_send_public_key_command(sm_connection_t *connection) {
2693b919f264SMatthias Ringwald     bool trigger_user_response   = false;
2694b919f264SMatthias Ringwald     bool trigger_start_calculating_local_confirm = false;
2695b919f264SMatthias Ringwald     uint8_t buffer[65];
2696b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_PUBLIC_KEY;
2697b919f264SMatthias Ringwald     //
2698b919f264SMatthias Ringwald     reverse_256(&ec_q[0],  &buffer[1]);
2699b919f264SMatthias Ringwald     reverse_256(&ec_q[32], &buffer[33]);
2700b919f264SMatthias Ringwald 
2701b919f264SMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
2702b919f264SMatthias Ringwald     if (test_pairing_failure == SM_REASON_DHKEY_CHECK_FAILED){
2703b919f264SMatthias Ringwald             log_info("testing_support: invalidating public key");
2704b919f264SMatthias Ringwald             // flip single bit of public key coordinate
2705b919f264SMatthias Ringwald             buffer[1] ^= 1;
2706b919f264SMatthias Ringwald         }
2707b919f264SMatthias Ringwald #endif
2708b919f264SMatthias Ringwald 
2709b919f264SMatthias Ringwald     // stk generation method
2710b919f264SMatthias Ringwald // passkey entry: notify app to show passkey or to request passkey
2711b919f264SMatthias Ringwald     switch (setup->sm_stk_generation_method){
2712b919f264SMatthias Ringwald         case JUST_WORKS:
2713b919f264SMatthias Ringwald         case NUMERIC_COMPARISON:
2714b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2715b919f264SMatthias Ringwald                 // responder
2716b919f264SMatthias Ringwald                 trigger_start_calculating_local_confirm = true;
2717b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_LOCAL_NONCE;
2718b919f264SMatthias Ringwald             } else {
2719b919f264SMatthias Ringwald                 // initiator
2720b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2721b919f264SMatthias Ringwald             }
2722b919f264SMatthias Ringwald             break;
2723b919f264SMatthias Ringwald         case PK_INIT_INPUT:
2724b919f264SMatthias Ringwald         case PK_RESP_INPUT:
2725b919f264SMatthias Ringwald         case PK_BOTH_INPUT:
2726b919f264SMatthias Ringwald             // use random TK for display
2727b919f264SMatthias Ringwald             (void)memcpy(setup->sm_ra, setup->sm_tk, 16);
2728b919f264SMatthias Ringwald             (void)memcpy(setup->sm_rb, setup->sm_tk, 16);
2729b919f264SMatthias Ringwald             setup->sm_passkey_bit = 0;
2730b919f264SMatthias Ringwald 
2731b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2732b919f264SMatthias Ringwald                 // responder
2733b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2734b919f264SMatthias Ringwald             } else {
2735b919f264SMatthias Ringwald                 // initiator
2736b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2737b919f264SMatthias Ringwald             }
2738b919f264SMatthias Ringwald             trigger_user_response = true;
2739b919f264SMatthias Ringwald             break;
2740b919f264SMatthias Ringwald         case OOB:
2741b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2742b919f264SMatthias Ringwald                 // responder
2743b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
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         default:
2750b919f264SMatthias Ringwald             btstack_assert(false);
2751b919f264SMatthias Ringwald             break;
2752b919f264SMatthias Ringwald     }
2753b919f264SMatthias Ringwald 
2754b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2755b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2756b919f264SMatthias Ringwald 
2757b919f264SMatthias Ringwald     // trigger user response and calc confirm after sending pdu
2758b919f264SMatthias Ringwald     if (trigger_user_response){
2759b919f264SMatthias Ringwald         sm_trigger_user_response(connection);
2760b919f264SMatthias Ringwald     }
2761b919f264SMatthias Ringwald     if (trigger_start_calculating_local_confirm){
2762b919f264SMatthias Ringwald         sm_sc_start_calculating_local_confirm(connection);
2763b919f264SMatthias Ringwald     }
2764b919f264SMatthias Ringwald }
2765b919f264SMatthias Ringwald #endif
2766b919f264SMatthias Ringwald 
2767de42cac5SMatthias Ringwald static bool sm_run_non_connection_logic(void){
2768de42cac5SMatthias Ringwald     bool done;;
2769de42cac5SMatthias Ringwald 
2770de42cac5SMatthias Ringwald     done = sm_run_dpkg();
2771de42cac5SMatthias Ringwald     if (done) return true;
2772de42cac5SMatthias Ringwald 
2773de42cac5SMatthias Ringwald     done = sm_run_rau();
2774de42cac5SMatthias Ringwald     if (done) return true;
2775de42cac5SMatthias Ringwald 
2776de42cac5SMatthias Ringwald     done = sm_run_csrk();
2777de42cac5SMatthias Ringwald     if (done) return true;
2778de42cac5SMatthias Ringwald 
2779de42cac5SMatthias Ringwald     done = sm_run_oob();
2780de42cac5SMatthias Ringwald     return done;
2781de42cac5SMatthias Ringwald }
2782b919f264SMatthias Ringwald 
2783d7f1c72eSMatthias Ringwald static void sm_run(void){
2784d7f1c72eSMatthias Ringwald 
2785d7f1c72eSMatthias Ringwald     // assert that stack has already bootet
2786d7f1c72eSMatthias Ringwald     if (hci_get_state() != HCI_STATE_WORKING) return;
2787d7f1c72eSMatthias Ringwald 
2788d7f1c72eSMatthias Ringwald     // assert that we can send at least commands
2789d7f1c72eSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return;
2790d7f1c72eSMatthias Ringwald 
2791d7f1c72eSMatthias Ringwald     // pause until IR/ER are ready
2792d7f1c72eSMatthias Ringwald     if (sm_persistent_keys_random_active) return;
2793d7f1c72eSMatthias Ringwald 
2794d7f1c72eSMatthias Ringwald     // non-connection related behaviour
2795de42cac5SMatthias Ringwald     bool done = sm_run_non_connection_logic();
2796d7f1c72eSMatthias Ringwald     if (done) return;
2797d7f1c72eSMatthias Ringwald 
2798d7f1c72eSMatthias Ringwald     // assert that we can send at least commands - cmd might have been sent by crypto engine
2799d7f1c72eSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return;
2800d7f1c72eSMatthias Ringwald 
2801d7f1c72eSMatthias Ringwald     // handle basic actions that don't requires the full context
2802d7f1c72eSMatthias Ringwald     done = sm_run_basic();
2803d7f1c72eSMatthias Ringwald     if (done) return;
2804d7f1c72eSMatthias Ringwald 
2805d7f1c72eSMatthias Ringwald     //
2806d7f1c72eSMatthias Ringwald     // active connection handling
2807d7f1c72eSMatthias Ringwald     // -- use loop to handle next connection if lock on setup context is released
2808d7f1c72eSMatthias Ringwald 
2809d7f1c72eSMatthias Ringwald     while (true) {
2810d7f1c72eSMatthias Ringwald 
2811d7f1c72eSMatthias Ringwald         sm_run_activate_connection();
2812d7f1c72eSMatthias Ringwald 
2813d7f1c72eSMatthias Ringwald         if (sm_active_connection_handle == HCI_CON_HANDLE_INVALID) return;
28143deb3ec6SMatthias Ringwald 
28153deb3ec6SMatthias Ringwald         //
28163deb3ec6SMatthias Ringwald         // active connection handling
28173deb3ec6SMatthias Ringwald         //
28183deb3ec6SMatthias Ringwald 
28193cf37b8cSMatthias Ringwald         sm_connection_t * connection = sm_get_connection_for_handle(sm_active_connection_handle);
28203cf37b8cSMatthias Ringwald         if (!connection) {
28213cf37b8cSMatthias Ringwald             log_info("no connection for handle 0x%04x", sm_active_connection_handle);
28223cf37b8cSMatthias Ringwald             return;
28233cf37b8cSMatthias Ringwald         }
28243cf37b8cSMatthias Ringwald 
28253deb3ec6SMatthias Ringwald         // assert that we could send a SM PDU - not needed for all of the following
2826384eabd3SMatthias Ringwald         if (!l2cap_can_send_fixed_channel_packet_now(sm_active_connection_handle, connection->sm_cid)) {
28277149bde5SMatthias Ringwald             log_info("cannot send now, requesting can send now event");
2828384eabd3SMatthias Ringwald             l2cap_request_can_send_fix_channel_now_event(sm_active_connection_handle, connection->sm_cid);
2829b170b20fSMatthias Ringwald             return;
2830b170b20fSMatthias Ringwald         }
28313deb3ec6SMatthias Ringwald 
28323d7fe1e9SMatthias Ringwald         // send keypress notifications
2833*1d80f1e6SMatthias Ringwald         if (setup->sm_keypress_notification != 0u){
2834403280b9SMatthias Ringwald             sm_run_send_keypress_notification(connection);
2835d7471931SMatthias Ringwald             return;
28363d7fe1e9SMatthias Ringwald         }
28373d7fe1e9SMatthias Ringwald 
2838f7ea4423SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2839234022e5SMatthias Ringwald         // assert that sm cmac engine is ready
2840234022e5SMatthias Ringwald         if (sm_cmac_ready() == false){
2841234022e5SMatthias Ringwald             break;
2842234022e5SMatthias Ringwald         }
2843f7ea4423SMatthias Ringwald #endif
2844234022e5SMatthias Ringwald 
28453deb3ec6SMatthias Ringwald         int key_distribution_flags;
284642134bc6SMatthias Ringwald         UNUSED(key_distribution_flags);
2847b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
2848b6afa23eSMatthias Ringwald         int err;
28499b75de03SMatthias Ringwald         bool have_ltk;
28509b75de03SMatthias Ringwald         uint8_t ltk[16];
2851b6f39a74SMatthias Ringwald #endif
28523deb3ec6SMatthias Ringwald 
28533deb3ec6SMatthias Ringwald         log_info("sm_run: state %u", connection->sm_engine_state);
28543deb3ec6SMatthias Ringwald         switch (connection->sm_engine_state){
28553deb3ec6SMatthias Ringwald 
2856f32b7a88SMatthias Ringwald             // secure connections, initiator + responding states
2857aec94140SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2858aec94140SMatthias Ringwald             case SM_SC_W2_CMAC_FOR_CONFIRMATION:
2859aec94140SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CMAC_FOR_CONFIRMATION;
2860aec94140SMatthias Ringwald                 sm_sc_calculate_local_confirm(connection);
2861aec94140SMatthias Ringwald                 break;
2862688a08f9SMatthias Ringwald             case SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION:
2863688a08f9SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION;
2864688a08f9SMatthias Ringwald                 sm_sc_calculate_remote_confirm(connection);
2865688a08f9SMatthias Ringwald                 break;
2866dc300847SMatthias Ringwald             case SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK:
2867dc300847SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK;
2868dc300847SMatthias Ringwald                 sm_sc_calculate_f6_for_dhkey_check(connection);
2869dc300847SMatthias Ringwald                 break;
2870019005a0SMatthias Ringwald             case SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
2871019005a0SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
28720346c37cSMatthias Ringwald                 sm_sc_calculate_f6_to_verify_dhkey_check(connection);
28730346c37cSMatthias Ringwald                 break;
28740346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_SALT:
28750346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_SALT;
28760346c37cSMatthias Ringwald                 f5_calculate_salt(connection);
28770346c37cSMatthias Ringwald                 break;
28780346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_MACKEY:
28790346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_MACKEY;
28800346c37cSMatthias Ringwald                 f5_calculate_mackey(connection);
28810346c37cSMatthias Ringwald                 break;
28820346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_LTK:
28830346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_LTK;
28840346c37cSMatthias Ringwald                 f5_calculate_ltk(connection);
2885019005a0SMatthias Ringwald                 break;
2886bd57ffebSMatthias Ringwald             case SM_SC_W2_CALCULATE_G2:
2887bd57ffebSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_G2;
2888b35a3de2SMatthias Ringwald                 g2_calculate(connection);
2889bd57ffebSMatthias Ringwald                 break;
2890e0a03c85SMatthias Ringwald #endif
2891e0a03c85SMatthias Ringwald 
289242134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
28933deb3ec6SMatthias Ringwald             // initiator side
2894f32b7a88SMatthias Ringwald 
28955567aa60SMatthias Ringwald             case SM_INITIATOR_PH4_HAS_LTK: {
2896f32b7a88SMatthias Ringwald 				sm_reset_setup();
2897f32b7a88SMatthias Ringwald 				sm_load_security_info(connection);
2898f32b7a88SMatthias Ringwald 
28993deb3ec6SMatthias Ringwald                 sm_key_t peer_ltk_flipped;
29009c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_peer_ltk, peer_ltk_flipped);
29015567aa60SMatthias Ringwald                 connection->sm_engine_state = SM_PH4_W4_CONNECTION_ENCRYPTED;
29023deb3ec6SMatthias Ringwald                 log_info("sm: hci_le_start_encryption ediv 0x%04x", setup->sm_peer_ediv);
2903c9b8fdd9SMatthias Ringwald                 uint32_t rand_high = big_endian_read_32(setup->sm_peer_rand, 0);
2904c9b8fdd9SMatthias Ringwald                 uint32_t rand_low  = big_endian_read_32(setup->sm_peer_rand, 4);
29053deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_start_encryption, connection->sm_handle,rand_low, rand_high, setup->sm_peer_ediv, peer_ltk_flipped);
290649c9e430SMatthias Ringwald 
290749c9e430SMatthias Ringwald                 // notify after sending
290849c9e430SMatthias Ringwald                 sm_reencryption_started(connection);
29093deb3ec6SMatthias Ringwald                 return;
29103deb3ec6SMatthias Ringwald             }
29113deb3ec6SMatthias Ringwald 
2912b26f445fSMatthias Ringwald 			case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
2913b26f445fSMatthias Ringwald 				sm_reset_setup();
2914b26f445fSMatthias Ringwald 				sm_init_setup(connection);
2915b26f445fSMatthias Ringwald 
29161ad129beSMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST);
29173deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_INITIATOR_PH1_W4_PAIRING_RESPONSE;
2918687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
29193deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
292049c9e430SMatthias Ringwald 
292149c9e430SMatthias Ringwald                 // notify after sending
292249c9e430SMatthias Ringwald                 sm_pairing_started(connection);
29233deb3ec6SMatthias Ringwald                 break;
292442134bc6SMatthias Ringwald #endif
29253deb3ec6SMatthias Ringwald 
292627c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2927b919f264SMatthias Ringwald             case SM_SC_SEND_PUBLIC_KEY_COMMAND:
2928b919f264SMatthias Ringwald                 sm_run_state_sc_send_public_key_command(connection);
292945a61d50SMatthias Ringwald                 break;
2930b919f264SMatthias Ringwald             case SM_SC_SEND_CONFIRMATION:
2931b919f264SMatthias Ringwald                 sm_run_state_sc_send_confirmation(connection);
293245a61d50SMatthias Ringwald                 break;
2933b919f264SMatthias Ringwald             case SM_SC_SEND_PAIRING_RANDOM:
2934b919f264SMatthias Ringwald                 sm_run_state_sc_send_pairing_random(connection);
293545a61d50SMatthias Ringwald                 break;
2936b919f264SMatthias Ringwald             case SM_SC_SEND_DHKEY_CHECK_COMMAND:
2937b919f264SMatthias Ringwald                 sm_run_state_sc_send_dhkey_check_command(connection);
29387bbeb3adSMilanka Ringwald                 break;
2939e53be891SMatthias Ringwald #endif
294042134bc6SMatthias Ringwald 
294142134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
2942dd12a62bSMatthias Ringwald 
294387014f74SMatthias Ringwald 			case SM_RESPONDER_SEND_SECURITY_REQUEST: {
294487014f74SMatthias Ringwald 				const uint8_t buffer[2] = {SM_CODE_SECURITY_REQUEST, sm_auth_req};
294587014f74SMatthias Ringwald 				connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
2946687a03c8SMatthias Ringwald 				sm_send_connectionless(connection,  (uint8_t *) buffer, sizeof(buffer));
2947c8d0ff33SMatthias Ringwald 				sm_timeout_start(connection);
294887014f74SMatthias Ringwald 				break;
294987014f74SMatthias Ringwald 			}
295087014f74SMatthias Ringwald 
295138196718SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
295238196718SMatthias Ringwald 			case SM_SC_RECEIVED_LTK_REQUEST:
295338196718SMatthias Ringwald 				switch (connection->sm_irk_lookup_state){
295438196718SMatthias Ringwald 					case IRK_LOOKUP_SUCCEEDED:
295538196718SMatthias Ringwald 						// assuming Secure Connection, we have a stored LTK and the EDIV/RAND are null
295638196718SMatthias Ringwald 						// start using context by loading security info
295738196718SMatthias Ringwald 						sm_reset_setup();
295838196718SMatthias Ringwald 						sm_load_security_info(connection);
295938196718SMatthias Ringwald 						if ((setup->sm_peer_ediv == 0u) && sm_is_null_random(setup->sm_peer_rand) && !sm_is_null_key(setup->sm_peer_ltk)){
296038196718SMatthias Ringwald 							(void)memcpy(setup->sm_ltk, setup->sm_peer_ltk, 16);
296138196718SMatthias Ringwald 							connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
296242646f38SMatthias Ringwald                             sm_reencryption_started(connection);
296338196718SMatthias Ringwald                             sm_trigger_run();
296438196718SMatthias Ringwald 							break;
296538196718SMatthias Ringwald 						}
296638196718SMatthias Ringwald 						log_info("LTK Request: ediv & random are empty, but no stored LTK (IRK Lookup Succeeded)");
296738196718SMatthias Ringwald 						connection->sm_engine_state = SM_RESPONDER_IDLE;
296838196718SMatthias Ringwald 						hci_send_cmd(&hci_le_long_term_key_negative_reply, connection->sm_handle);
296938196718SMatthias Ringwald 						return;
297038196718SMatthias Ringwald 					default:
297138196718SMatthias Ringwald 						// just wait until IRK lookup is completed
297238196718SMatthias Ringwald 						break;
297338196718SMatthias Ringwald 				}
297438196718SMatthias Ringwald 				break;
297538196718SMatthias Ringwald #endif /* ENABLE_LE_SECURE_CONNECTIONS */
297638196718SMatthias Ringwald 
2977b6afa23eSMatthias Ringwald 			case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
2978b6afa23eSMatthias Ringwald                 sm_reset_setup();
29799b75de03SMatthias Ringwald 
29809b75de03SMatthias Ringwald 			    // handle Pairing Request with LTK available
29819b75de03SMatthias Ringwald                 switch (connection->sm_irk_lookup_state) {
29829b75de03SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
29839b75de03SMatthias Ringwald                         le_device_db_encryption_get(connection->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
29849b75de03SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
29859b75de03SMatthias Ringwald                         if (have_ltk){
29869b75de03SMatthias Ringwald                             log_info("pairing request but LTK available");
298719a40772SMatthias Ringwald                             // emit re-encryption start/fail sequence
29889b75de03SMatthias Ringwald                             sm_reencryption_started(connection);
29899b75de03SMatthias Ringwald                             sm_reencryption_complete(connection, ERROR_CODE_PIN_OR_KEY_MISSING);
29909b75de03SMatthias Ringwald                         }
29919b75de03SMatthias Ringwald                         break;
29929b75de03SMatthias Ringwald                     default:
29939b75de03SMatthias Ringwald                         break;
29949b75de03SMatthias Ringwald                 }
29959b75de03SMatthias Ringwald 
2996b6afa23eSMatthias Ringwald 				sm_init_setup(connection);
299739543d07SMatthias Ringwald 
2998b6afa23eSMatthias Ringwald 				// recover pairing request
2999b6afa23eSMatthias Ringwald 				(void)memcpy(&setup->sm_m_preq, &connection->sm_m_preq, sizeof(sm_pairing_packet_t));
3000b6afa23eSMatthias Ringwald 				err = sm_stk_generation_init(connection);
3001b6afa23eSMatthias Ringwald 
3002b6afa23eSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
3003b6afa23eSMatthias Ringwald 				if ((0 < test_pairing_failure) && (test_pairing_failure < SM_REASON_DHKEY_CHECK_FAILED)){
3004b6afa23eSMatthias Ringwald                         log_info("testing_support: respond with pairing failure %u", test_pairing_failure);
3005b6afa23eSMatthias Ringwald                         err = test_pairing_failure;
3006b6afa23eSMatthias Ringwald                     }
3007b6afa23eSMatthias Ringwald #endif
30089305033eSMatthias Ringwald 				if (err != 0){
300949c9e430SMatthias Ringwald                     // emit pairing started/failed sequence
301049c9e430SMatthias Ringwald                     sm_pairing_started(connection);
3011f4935286SMatthias Ringwald                     sm_pairing_error(connection, err);
3012b6afa23eSMatthias Ringwald 					sm_trigger_run();
3013b6afa23eSMatthias Ringwald 					break;
3014b6afa23eSMatthias Ringwald 				}
3015b6afa23eSMatthias Ringwald 
3016b6afa23eSMatthias Ringwald 				sm_timeout_start(connection);
3017b6afa23eSMatthias Ringwald 
3018b6afa23eSMatthias Ringwald 				// generate random number first, if we need to show passkey, otherwise send response
3019b6afa23eSMatthias Ringwald 				if (setup->sm_stk_generation_method == PK_INIT_INPUT){
3020b6afa23eSMatthias 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);
3021b6afa23eSMatthias Ringwald 					break;
3022b6afa23eSMatthias Ringwald 				}
3023b6afa23eSMatthias Ringwald 
3024b6afa23eSMatthias Ringwald 				/* fall through */
3025b6afa23eSMatthias Ringwald 
30263deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE:
30271ad129beSMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_s_pres,SM_CODE_PAIRING_RESPONSE);
3028f55bd529SMatthias Ringwald 
3029f55bd529SMatthias Ringwald                 // start with initiator key dist flags
30303deb3ec6SMatthias Ringwald                 key_distribution_flags = sm_key_distribution_flags_for_auth_req();
30311ad129beSMatthias Ringwald 
3032f55bd529SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
3033f55bd529SMatthias Ringwald                 // LTK (= encyrption information & master identification) only exchanged for LE Legacy Connection
3034f55bd529SMatthias Ringwald                 if (setup->sm_use_secure_connections){
3035f55bd529SMatthias Ringwald                     key_distribution_flags &= ~SM_KEYDIST_ENC_KEY;
3036f55bd529SMatthias Ringwald                 }
3037f55bd529SMatthias Ringwald #endif
3038f55bd529SMatthias Ringwald                 // setup in response
3039f55bd529SMatthias 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);
3040f55bd529SMatthias 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);
3041f55bd529SMatthias Ringwald 
3042f55bd529SMatthias Ringwald                 // update key distribution after ENC was dropped
30439a90d41aSMatthias 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));
3044f55bd529SMatthias Ringwald 
304527c32905SMatthias Ringwald                 if (setup->sm_use_secure_connections){
3046c6b7cbd9SMatthias Ringwald                     connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
30470b8af2a5SMatthias Ringwald                 } else {
30480b8af2a5SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_CONFIRM;
304927c32905SMatthias Ringwald                 }
30500b8af2a5SMatthias Ringwald 
3051687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
30523deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
305349c9e430SMatthias Ringwald 
305449c9e430SMatthias Ringwald                 // notify after sending
305549c9e430SMatthias Ringwald                 sm_pairing_started(connection);
305649c9e430SMatthias Ringwald 
3057446a8c36SMatthias Ringwald                 // SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
3058c1ab6cc1SMatthias Ringwald                 if (!setup->sm_use_secure_connections || (setup->sm_stk_generation_method == JUST_WORKS)){
30593deb3ec6SMatthias Ringwald                     sm_trigger_user_response(connection);
3060446a8c36SMatthias Ringwald                 }
30613deb3ec6SMatthias Ringwald                 return;
306242134bc6SMatthias Ringwald #endif
30633deb3ec6SMatthias Ringwald 
30643deb3ec6SMatthias Ringwald             case SM_PH2_SEND_PAIRING_RANDOM: {
30653deb3ec6SMatthias Ringwald                 uint8_t buffer[17];
30663deb3ec6SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_RANDOM;
30679c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_local_random, &buffer[1]);
306842134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
30693deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH2_W4_LTK_REQUEST;
30703deb3ec6SMatthias Ringwald                 } else {
30713deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_RANDOM;
30723deb3ec6SMatthias Ringwald                 }
3073687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
30743deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
30753deb3ec6SMatthias Ringwald                 break;
30763deb3ec6SMatthias Ringwald             }
30773deb3ec6SMatthias Ringwald 
3078d1a1f6a4SMatthias Ringwald             case SM_PH2_C1_GET_ENC_A:
30793deb3ec6SMatthias Ringwald                 // already busy?
30803deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
3081d1a1f6a4SMatthias Ringwald                 // calculate confirm using aes128 engine - step 1
3082d1a1f6a4SMatthias 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);
3083d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_C1_W4_ENC_A;
3084d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3085f3582630SMatthias 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);
30863deb3ec6SMatthias Ringwald                 break;
30873deb3ec6SMatthias Ringwald 
30883deb3ec6SMatthias Ringwald             case SM_PH2_C1_GET_ENC_C:
30893deb3ec6SMatthias Ringwald                 // already busy?
30903deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
30913deb3ec6SMatthias Ringwald                 // calculate m_confirm using aes128 engine - step 1
3092d1a1f6a4SMatthias 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);
3093d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_C1_W4_ENC_C;
3094d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3095f3582630SMatthias 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);
30963deb3ec6SMatthias Ringwald                 break;
3097d1a1f6a4SMatthias Ringwald 
30983deb3ec6SMatthias Ringwald             case SM_PH2_CALC_STK:
30993deb3ec6SMatthias Ringwald                 // already busy?
31003deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31013deb3ec6SMatthias Ringwald                 // calculate STK
310242134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
3103d1a1f6a4SMatthias Ringwald                     sm_s1_r_prime(setup->sm_local_random, setup->sm_peer_random, sm_aes128_plaintext);
31043deb3ec6SMatthias Ringwald                 } else {
3105d1a1f6a4SMatthias Ringwald                     sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, sm_aes128_plaintext);
31063deb3ec6SMatthias Ringwald                 }
3107d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_STK;
3108d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3109f3582630SMatthias 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);
31103deb3ec6SMatthias Ringwald                 break;
3111d1a1f6a4SMatthias Ringwald 
31123deb3ec6SMatthias Ringwald             case SM_PH3_Y_GET_ENC:
31133deb3ec6SMatthias Ringwald                 // already busy?
31143deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31153deb3ec6SMatthias Ringwald                 // PH3B2 - calculate Y from      - enc
31169ad0dd7cSMatthias Ringwald 
31179ad0dd7cSMatthias Ringwald                 // dm helper (was sm_dm_r_prime)
31189ad0dd7cSMatthias Ringwald                 // r' = padding || r
31199ad0dd7cSMatthias Ringwald                 // r - 64 bit value
31209ad0dd7cSMatthias Ringwald                 memset(&sm_aes128_plaintext[0], 0, 8);
31216535961aSMatthias Ringwald                 (void)memcpy(&sm_aes128_plaintext[8], setup->sm_local_rand, 8);
31229ad0dd7cSMatthias Ringwald 
31233deb3ec6SMatthias Ringwald                 // Y = dm(DHK, Rand)
3124d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH3_Y_W4_ENC;
3125d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3126f3582630SMatthias 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);
3127d1a1f6a4SMatthias Ringwald                 break;
3128d1a1f6a4SMatthias Ringwald 
31293deb3ec6SMatthias Ringwald             case SM_PH2_C1_SEND_PAIRING_CONFIRM: {
31303deb3ec6SMatthias Ringwald                 uint8_t buffer[17];
31313deb3ec6SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_CONFIRM;
31329c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_local_confirm, &buffer[1]);
313342134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
31343deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH2_W4_PAIRING_RANDOM;
31353deb3ec6SMatthias Ringwald                 } else {
31363deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_CONFIRM;
31373deb3ec6SMatthias Ringwald                 }
3138687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
31393deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
31403deb3ec6SMatthias Ringwald                 return;
31413deb3ec6SMatthias Ringwald             }
314242134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
31433deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH2_SEND_LTK_REPLY: {
3144916ea5b2SMatthias Ringwald                 // cache key before using
3145916ea5b2SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
31463deb3ec6SMatthias Ringwald                 sm_key_t stk_flipped;
31479c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_ltk, stk_flipped);
31483deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
31493deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, stk_flipped);
31503deb3ec6SMatthias Ringwald                 return;
31513deb3ec6SMatthias Ringwald             }
3152d7471931SMatthias Ringwald             case SM_RESPONDER_PH4_SEND_LTK_REPLY: {
3153b96d60a6SMatthias Ringwald                 // allow to override LTK
3154b96d60a6SMatthias Ringwald                 if (sm_get_ltk_callback != NULL){
3155b96d60a6SMatthias Ringwald                     (void)(*sm_get_ltk_callback)(connection->sm_handle, connection->sm_peer_addr_type, connection->sm_peer_address, setup->sm_ltk);
3156b96d60a6SMatthias Ringwald                 }
3157916ea5b2SMatthias Ringwald                 // cache key before using
3158916ea5b2SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
31593deb3ec6SMatthias Ringwald                 sm_key_t ltk_flipped;
31609c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_ltk, ltk_flipped);
31615567aa60SMatthias Ringwald                 connection->sm_engine_state = SM_PH4_W4_CONNECTION_ENCRYPTED;
31623deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, ltk_flipped);
31633deb3ec6SMatthias Ringwald                 return;
31643deb3ec6SMatthias Ringwald             }
3165dd12a62bSMatthias Ringwald 
3166dd12a62bSMatthias Ringwald 			case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
31673deb3ec6SMatthias Ringwald                 // already busy?
31683deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31693deb3ec6SMatthias Ringwald                 log_info("LTK Request: recalculating with ediv 0x%04x", setup->sm_local_ediv);
3170c61cfe5aSMatthias Ringwald 
3171dd12a62bSMatthias Ringwald 				sm_reset_setup();
3172dd12a62bSMatthias Ringwald 				sm_start_calculating_ltk_from_ediv_and_rand(connection);
3173dd12a62bSMatthias Ringwald 
317442646f38SMatthias Ringwald 				sm_reencryption_started(connection);
317542646f38SMatthias Ringwald 
3176c61cfe5aSMatthias Ringwald                 // dm helper (was sm_dm_r_prime)
3177c61cfe5aSMatthias Ringwald                 // r' = padding || r
3178c61cfe5aSMatthias Ringwald                 // r - 64 bit value
3179c61cfe5aSMatthias Ringwald                 memset(&sm_aes128_plaintext[0], 0, 8);
31806535961aSMatthias Ringwald                 (void)memcpy(&sm_aes128_plaintext[8], setup->sm_local_rand, 8);
3181c61cfe5aSMatthias Ringwald 
31823deb3ec6SMatthias Ringwald                 // Y = dm(DHK, Rand)
3183d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_RESPONDER_PH4_Y_W4_ENC;
3184d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3185f3582630SMatthias 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);
31863deb3ec6SMatthias Ringwald                 return;
318742134bc6SMatthias Ringwald #endif
318842134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
318942134bc6SMatthias Ringwald             case SM_INITIATOR_PH3_SEND_START_ENCRYPTION: {
319042134bc6SMatthias Ringwald                 sm_key_t stk_flipped;
319142134bc6SMatthias Ringwald                 reverse_128(setup->sm_ltk, stk_flipped);
319242134bc6SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
319342134bc6SMatthias Ringwald                 hci_send_cmd(&hci_le_start_encryption, connection->sm_handle, 0, 0, 0, stk_flipped);
319442134bc6SMatthias Ringwald                 return;
319542134bc6SMatthias Ringwald             }
319642134bc6SMatthias Ringwald #endif
31973deb3ec6SMatthias Ringwald 
31983deb3ec6SMatthias Ringwald             case SM_PH3_DISTRIBUTE_KEYS:
3199e94757aeSMatthias Ringwald                 // send next key
3200403280b9SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
3201403280b9SMatthias Ringwald                     sm_run_distribute_keys(connection);
3202e94757aeSMatthias Ringwald                 }
3203e94757aeSMatthias Ringwald 
3204e94757aeSMatthias Ringwald                 // more to send?
3205e94757aeSMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
32063deb3ec6SMatthias Ringwald                     return;
32073deb3ec6SMatthias Ringwald                 }
32083deb3ec6SMatthias Ringwald 
32093deb3ec6SMatthias Ringwald                 // keys are sent
321042134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
32113deb3ec6SMatthias Ringwald                     // slave -> receive master keys if any
321261d1a45eSMatthias Ringwald                     if (sm_key_distribution_all_received()){
32133deb3ec6SMatthias Ringwald                         sm_key_distribution_handle_all_received(connection);
3214f5020412SMatthias Ringwald                         sm_key_distribution_complete_responder(connection);
3215f5020412SMatthias Ringwald                         // start CTKD right away
3216f5020412SMatthias Ringwald                         continue;
32173deb3ec6SMatthias Ringwald                     } else {
32183deb3ec6SMatthias Ringwald                         connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
32193deb3ec6SMatthias Ringwald                     }
32203deb3ec6SMatthias Ringwald                 } else {
32211dca9d8aSMatthias Ringwald                     sm_master_pairing_success(connection);
32223deb3ec6SMatthias Ringwald                 }
32233deb3ec6SMatthias Ringwald                 break;
32243deb3ec6SMatthias Ringwald 
3225c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3226c18be159SMatthias Ringwald             case SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST:
3227c18be159SMatthias Ringwald                 // fill in sm setup (lite version of sm_init_setup)
3228c18be159SMatthias Ringwald                 sm_reset_setup();
3229c18be159SMatthias Ringwald                 setup->sm_peer_addr_type = connection->sm_peer_addr_type;
3230c18be159SMatthias Ringwald                 setup->sm_m_addr_type = connection->sm_peer_addr_type;
3231c18be159SMatthias Ringwald                 setup->sm_s_addr_type = connection->sm_own_addr_type;
3232c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_peer_address, connection->sm_peer_address, 6);
3233c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_m_address, connection->sm_peer_address, 6);
3234c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_s_address, connection->sm_own_address, 6);
3235c18be159SMatthias Ringwald                 setup->sm_use_secure_connections = true;
3236c18be159SMatthias Ringwald                 sm_ctkd_fetch_br_edr_link_key(connection);
3237c18be159SMatthias Ringwald 
3238c18be159SMatthias Ringwald                 // Enc Key and IRK if requested
3239c18be159SMatthias Ringwald                 key_distribution_flags = SM_KEYDIST_ID_KEY | SM_KEYDIST_ENC_KEY;
3240c18be159SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
3241c18be159SMatthias Ringwald                 // Plus signing key if supported
3242c18be159SMatthias Ringwald                 key_distribution_flags |= SM_KEYDIST_ID_KEY;
3243c18be159SMatthias Ringwald #endif
3244c18be159SMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST);
3245c18be159SMatthias Ringwald                 sm_pairing_packet_set_io_capability(setup->sm_m_preq, 0);
3246c18be159SMatthias Ringwald                 sm_pairing_packet_set_oob_data_flag(setup->sm_m_preq, 0);
3247c18be159SMatthias Ringwald                 sm_pairing_packet_set_auth_req(setup->sm_m_preq, SM_AUTHREQ_CT2);
3248c18be159SMatthias Ringwald                 sm_pairing_packet_set_max_encryption_key_size(setup->sm_m_preq, sm_max_encryption_key_size);
3249c18be159SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_m_preq, key_distribution_flags);
3250c18be159SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags);
3251c18be159SMatthias Ringwald 
3252c18be159SMatthias Ringwald                 // set state and send pairing response
3253c18be159SMatthias Ringwald                 sm_timeout_start(connection);
3254c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_INITIATOR_W4_PAIRING_RESPONSE;
3255c18be159SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t *) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
3256c18be159SMatthias Ringwald                 break;
3257c18be159SMatthias Ringwald 
3258c18be159SMatthias Ringwald             case SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED:
3259c18be159SMatthias Ringwald                 // fill in sm setup (lite version of sm_init_setup)
3260c18be159SMatthias Ringwald                 sm_reset_setup();
3261c18be159SMatthias Ringwald                 setup->sm_peer_addr_type = connection->sm_peer_addr_type;
3262c18be159SMatthias Ringwald                 setup->sm_m_addr_type = connection->sm_peer_addr_type;
3263c18be159SMatthias Ringwald                 setup->sm_s_addr_type = connection->sm_own_addr_type;
3264c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_peer_address, connection->sm_peer_address, 6);
3265c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_m_address, connection->sm_peer_address, 6);
3266c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_s_address, connection->sm_own_address, 6);
3267c18be159SMatthias Ringwald                 setup->sm_use_secure_connections = true;
3268c18be159SMatthias Ringwald                 sm_ctkd_fetch_br_edr_link_key(connection);
3269c18be159SMatthias Ringwald                 (void) memcpy(&setup->sm_m_preq, &connection->sm_m_preq, sizeof(sm_pairing_packet_t));
3270c18be159SMatthias Ringwald 
3271c18be159SMatthias Ringwald                 // Enc Key and IRK if requested
3272c18be159SMatthias Ringwald                 key_distribution_flags = SM_KEYDIST_ID_KEY | SM_KEYDIST_ENC_KEY;
3273c18be159SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
3274c18be159SMatthias Ringwald                 // Plus signing key if supported
3275c18be159SMatthias Ringwald                 key_distribution_flags |= SM_KEYDIST_ID_KEY;
3276c18be159SMatthias Ringwald #endif
3277c18be159SMatthias Ringwald                 // drop flags not requested by initiator
3278c18be159SMatthias Ringwald                 key_distribution_flags &= sm_pairing_packet_get_initiator_key_distribution(connection->sm_m_preq);
3279c18be159SMatthias Ringwald 
3280c18be159SMatthias 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:
3281c18be159SMatthias Ringwald                 // - the IO Capability field,
3282c18be159SMatthias Ringwald                 // - the OOB data flag field, and
3283c18be159SMatthias Ringwald                 // - all bits in the Auth Req field except the CT2 bit.
3284c18be159SMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_s_pres, SM_CODE_PAIRING_RESPONSE);
3285c18be159SMatthias Ringwald                 sm_pairing_packet_set_io_capability(setup->sm_s_pres, 0);
3286c18be159SMatthias Ringwald                 sm_pairing_packet_set_oob_data_flag(setup->sm_s_pres, 0);
3287c18be159SMatthias Ringwald                 sm_pairing_packet_set_auth_req(setup->sm_s_pres, SM_AUTHREQ_CT2);
3288c18be159SMatthias Ringwald                 sm_pairing_packet_set_max_encryption_key_size(setup->sm_s_pres, connection->sm_actual_encryption_key_size);
3289c18be159SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_s_pres, key_distribution_flags);
3290c18be159SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_s_pres, key_distribution_flags);
3291c18be159SMatthias Ringwald 
3292c18be159SMatthias Ringwald                 // configure key distribution, LTK is derived locally
3293c18be159SMatthias Ringwald                 key_distribution_flags &= ~SM_KEYDIST_ENC_KEY;
3294c18be159SMatthias Ringwald                 sm_setup_key_distribution(key_distribution_flags, key_distribution_flags);
3295c18be159SMatthias Ringwald 
3296c18be159SMatthias Ringwald                 // set state and send pairing response
3297c18be159SMatthias Ringwald                 sm_timeout_start(connection);
3298c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
3299c18be159SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t *) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
3300c18be159SMatthias Ringwald                 break;
3301c18be159SMatthias Ringwald             case SM_BR_EDR_DISTRIBUTE_KEYS:
3302c18be159SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0) {
3303c18be159SMatthias Ringwald                     sm_run_distribute_keys(connection);
3304c18be159SMatthias Ringwald                     return;
3305c18be159SMatthias Ringwald                 }
3306c18be159SMatthias Ringwald                 // keys are sent
3307c18be159SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)) {
3308c18be159SMatthias Ringwald                     // responder -> receive master keys if there are any
330961d1a45eSMatthias Ringwald                     if (!sm_key_distribution_all_received()){
3310c18be159SMatthias Ringwald                         connection->sm_engine_state = SM_BR_EDR_RECEIVE_KEYS;
3311c18be159SMatthias Ringwald                         break;
3312c18be159SMatthias Ringwald                     }
3313c18be159SMatthias Ringwald                 }
3314c18be159SMatthias Ringwald                 // otherwise start CTKD right away (responder and no keys to receive / initiator)
3315c18be159SMatthias Ringwald                 sm_ctkd_start_from_br_edr(connection);
3316c18be159SMatthias Ringwald                 continue;
3317c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_ILK_USING_H6:
3318c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
3319c18be159SMatthias Ringwald                 h6_calculate_ilk_from_le_ltk(connection);
3320c18be159SMatthias Ringwald                 break;
3321c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY:
3322c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY;
3323c18be159SMatthias Ringwald                 h6_calculate_br_edr_link_key(connection);
3324c18be159SMatthias Ringwald                 break;
3325c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_ILK_USING_H7:
3326c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
3327c18be159SMatthias Ringwald                 h7_calculate_ilk_from_le_ltk(connection);
3328c18be159SMatthias Ringwald                 break;
3329c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_ILK_USING_H6:
3330c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_ILK;
3331c18be159SMatthias Ringwald                 h6_calculate_ilk_from_br_edr(connection);
3332c18be159SMatthias Ringwald                 break;
3333c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_LE_LTK:
3334c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_LE_LTK;
3335c18be159SMatthias Ringwald                 h6_calculate_le_ltk(connection);
3336c18be159SMatthias Ringwald                 break;
3337c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_ILK_USING_H7:
3338c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_ILK;
3339c18be159SMatthias Ringwald                 h7_calculate_ilk_from_br_edr(connection);
3340c18be159SMatthias Ringwald                 break;
3341c18be159SMatthias Ringwald #endif
3342c18be159SMatthias Ringwald 
33433deb3ec6SMatthias Ringwald             default:
33443deb3ec6SMatthias Ringwald                 break;
33453deb3ec6SMatthias Ringwald         }
33463deb3ec6SMatthias Ringwald 
33473deb3ec6SMatthias Ringwald         // check again if active connection was released
33487149bde5SMatthias Ringwald         if (sm_active_connection_handle != HCI_CON_HANDLE_INVALID) break;
33493deb3ec6SMatthias Ringwald     }
33503deb3ec6SMatthias Ringwald }
33513deb3ec6SMatthias Ringwald 
3352d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3353d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_a(void *arg){
3354f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
335504678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
335604678764SMatthias Ringwald 
3357f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3358f3582630SMatthias Ringwald     if (connection == NULL) return;
3359f3582630SMatthias Ringwald 
3360d1a1f6a4SMatthias Ringwald     sm_c1_t3(sm_aes128_ciphertext, setup->sm_m_address, setup->sm_s_address, setup->sm_c1_t3_value);
336104678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3362f3582630SMatthias 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);
3363d1a1f6a4SMatthias Ringwald }
33643deb3ec6SMatthias Ringwald 
3365d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_b(void *arg){
3366f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
336704678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
336804678764SMatthias Ringwald 
3369f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3370f3582630SMatthias Ringwald     if (connection == NULL) return;
3371f3582630SMatthias Ringwald 
33728314c363SMatthias Ringwald     log_info_key("c1!", setup->sm_local_confirm);
33733deb3ec6SMatthias Ringwald     connection->sm_engine_state = SM_PH2_C1_SEND_PAIRING_CONFIRM;
337470b44dd4SMatthias Ringwald     sm_trigger_run();
3375d1a1f6a4SMatthias Ringwald }
3376d1a1f6a4SMatthias Ringwald 
3377d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3378d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_c(void *arg){
3379f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
338004678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
338104678764SMatthias Ringwald 
3382f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3383f3582630SMatthias Ringwald     if (connection == NULL) return;
3384f3582630SMatthias Ringwald 
3385d1a1f6a4SMatthias Ringwald     sm_c1_t3(sm_aes128_ciphertext, setup->sm_m_address, setup->sm_s_address, setup->sm_c1_t3_value);
338604678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3387f3582630SMatthias 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);
3388d1a1f6a4SMatthias Ringwald }
3389d1a1f6a4SMatthias Ringwald 
3390d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_d(void * arg){
3391f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
339204678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
339304678764SMatthias Ringwald 
3394f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3395f3582630SMatthias Ringwald     if (connection == NULL) return;
3396f3582630SMatthias Ringwald 
3397d1a1f6a4SMatthias Ringwald     log_info_key("c1!", sm_aes128_ciphertext);
3398d1a1f6a4SMatthias Ringwald     if (memcmp(setup->sm_peer_confirm, sm_aes128_ciphertext, 16) != 0){
3399f4935286SMatthias Ringwald         sm_pairing_error(connection, SM_REASON_CONFIRM_VALUE_FAILED);
340070b44dd4SMatthias Ringwald         sm_trigger_run();
34013deb3ec6SMatthias Ringwald         return;
34023deb3ec6SMatthias Ringwald     }
340342134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
34043deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
340570b44dd4SMatthias Ringwald         sm_trigger_run();
34063deb3ec6SMatthias Ringwald     } else {
3407d1a1f6a4SMatthias Ringwald         sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, sm_aes128_plaintext);
3408d1a1f6a4SMatthias Ringwald         sm_aes128_state = SM_AES128_ACTIVE;
3409f3582630SMatthias 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);
34103deb3ec6SMatthias Ringwald     }
34113deb3ec6SMatthias Ringwald }
3412d1a1f6a4SMatthias Ringwald 
3413d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_stk(void *arg){
341404678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
3415f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
341604678764SMatthias Ringwald 
3417f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3418f3582630SMatthias Ringwald     if (connection == NULL) return;
3419f3582630SMatthias Ringwald 
34203deb3ec6SMatthias Ringwald     sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
34218314c363SMatthias Ringwald     log_info_key("stk", setup->sm_ltk);
342242134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
34233deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
34243deb3ec6SMatthias Ringwald     } else {
34253deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
34263deb3ec6SMatthias Ringwald     }
342770b44dd4SMatthias Ringwald     sm_trigger_run();
3428d1a1f6a4SMatthias Ringwald }
3429d1a1f6a4SMatthias Ringwald 
3430d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3431d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_y(void *arg){
3432f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
343304678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
343404678764SMatthias Ringwald 
3435f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3436f3582630SMatthias Ringwald     if (connection == NULL) return;
3437f3582630SMatthias Ringwald 
3438d1a1f6a4SMatthias Ringwald     setup->sm_local_y = big_endian_read_16(sm_aes128_ciphertext, 14);
34393deb3ec6SMatthias Ringwald     log_info_hex16("y", setup->sm_local_y);
34403deb3ec6SMatthias Ringwald     // PH3B3 - calculate EDIV
34413deb3ec6SMatthias Ringwald     setup->sm_local_ediv = setup->sm_local_y ^ setup->sm_local_div;
34423deb3ec6SMatthias Ringwald     log_info_hex16("ediv", setup->sm_local_ediv);
34433deb3ec6SMatthias Ringwald     // PH3B4 - calculate LTK         - enc
34443deb3ec6SMatthias Ringwald     // LTK = d1(ER, DIV, 0))
3445d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 0, sm_aes128_plaintext);
344604678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3447f3582630SMatthias 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);
34483deb3ec6SMatthias Ringwald }
3449d1a1f6a4SMatthias Ringwald 
34502a526f21SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
3451d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3452d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_y(void *arg){
345304678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
3454f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
345504678764SMatthias Ringwald 
3456f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3457f3582630SMatthias Ringwald     if (connection == NULL) return;
3458f3582630SMatthias Ringwald 
3459d1a1f6a4SMatthias Ringwald     setup->sm_local_y = big_endian_read_16(sm_aes128_ciphertext, 14);
34603deb3ec6SMatthias Ringwald     log_info_hex16("y", setup->sm_local_y);
34613deb3ec6SMatthias Ringwald 
34623deb3ec6SMatthias Ringwald     // PH3B3 - calculate DIV
34633deb3ec6SMatthias Ringwald     setup->sm_local_div = setup->sm_local_y ^ setup->sm_local_ediv;
34643deb3ec6SMatthias Ringwald     log_info_hex16("ediv", setup->sm_local_ediv);
34653deb3ec6SMatthias Ringwald     // PH3B4 - calculate LTK         - enc
34663deb3ec6SMatthias Ringwald     // LTK = d1(ER, DIV, 0))
3467d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 0, sm_aes128_plaintext);
346804678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3469f3582630SMatthias 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);
34703deb3ec6SMatthias Ringwald }
34712a526f21SMatthias Ringwald #endif
3472d1a1f6a4SMatthias Ringwald 
3473d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3474d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_ltk(void *arg){
3475f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
347604678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
347704678764SMatthias Ringwald 
3478f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3479f3582630SMatthias Ringwald     if (connection == NULL) return;
3480f3582630SMatthias Ringwald 
34818314c363SMatthias Ringwald     log_info_key("ltk", setup->sm_ltk);
34823deb3ec6SMatthias Ringwald     // calc CSRK next
3483d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 1, sm_aes128_plaintext);
348404678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3485f3582630SMatthias 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);
3486d1a1f6a4SMatthias Ringwald }
3487d1a1f6a4SMatthias Ringwald 
3488d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_csrk(void *arg){
3489f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
349004678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
349104678764SMatthias Ringwald 
3492f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3493f3582630SMatthias Ringwald     if (connection == NULL) return;
3494f3582630SMatthias Ringwald 
3495d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
34968314c363SMatthias Ringwald     log_info_key("csrk", setup->sm_local_csrk);
3497*1d80f1e6SMatthias Ringwald     if (setup->sm_key_distribution_send_set != 0u){
34983deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
34993deb3ec6SMatthias Ringwald     } else {
35003deb3ec6SMatthias Ringwald         // no keys to send, just continue
350142134bc6SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
350261d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
3503c5a72e35SMatthias Ringwald                 sm_key_distribution_handle_all_received(connection);
3504c5a72e35SMatthias Ringwald                 sm_key_distribution_complete_responder(connection);
3505c5a72e35SMatthias Ringwald             } else {
35063deb3ec6SMatthias Ringwald                 // slave -> receive master keys
35073deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
3508c5a72e35SMatthias Ringwald             }
35093deb3ec6SMatthias Ringwald         } else {
3510af7ef9d1SMatthias Ringwald             sm_key_distribution_complete_initiator(connection);
35113deb3ec6SMatthias Ringwald         }
35122bacf595SMatthias Ringwald     }
351370b44dd4SMatthias Ringwald     sm_trigger_run();
3514d1a1f6a4SMatthias Ringwald }
3515d1a1f6a4SMatthias Ringwald 
351642134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
3517d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_ltk(void *arg){
3518f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
351904678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
352004678764SMatthias Ringwald 
3521f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3522f3582630SMatthias Ringwald     if (connection == NULL) return;
3523f3582630SMatthias Ringwald 
35243deb3ec6SMatthias Ringwald     sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
35258314c363SMatthias Ringwald     log_info_key("ltk", setup->sm_ltk);
3526d7471931SMatthias Ringwald     connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
352770b44dd4SMatthias Ringwald     sm_trigger_run();
3528d1a1f6a4SMatthias Ringwald }
3529d1a1f6a4SMatthias Ringwald #endif
3530d1a1f6a4SMatthias Ringwald 
3531d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_address_resolution(void *arg){
3532d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3533d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
353404678764SMatthias Ringwald 
3535d1a1f6a4SMatthias Ringwald     // compare calulated address against connecting device
3536d1a1f6a4SMatthias Ringwald     uint8_t * hash = &sm_aes128_ciphertext[13];
3537d1a1f6a4SMatthias Ringwald     if (memcmp(&sm_address_resolution_address[3], hash, 3) == 0){
3538d1a1f6a4SMatthias Ringwald         log_info("LE Device Lookup: matched resolvable private address");
3539a66b030fSMatthias Ringwald         sm_address_resolution_handle_event(ADDRESS_RESOLUTION_SUCCEEDED);
354070b44dd4SMatthias Ringwald         sm_trigger_run();
35413deb3ec6SMatthias Ringwald         return;
35423deb3ec6SMatthias Ringwald     }
3543d1a1f6a4SMatthias Ringwald     // no match, try next
3544d1a1f6a4SMatthias Ringwald     sm_address_resolution_test++;
354570b44dd4SMatthias Ringwald     sm_trigger_run();
35463deb3ec6SMatthias Ringwald }
35473deb3ec6SMatthias Ringwald 
3548d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_irk(void *arg){
3549d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3550d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
355104678764SMatthias Ringwald 
3552d1a1f6a4SMatthias Ringwald     log_info_key("irk", sm_persistent_irk);
3553d1a1f6a4SMatthias Ringwald     dkg_state = DKG_CALC_DHK;
355470b44dd4SMatthias Ringwald     sm_trigger_run();
35557df18c15SMatthias Ringwald }
3556d1a1f6a4SMatthias Ringwald 
3557d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_dhk(void *arg){
3558d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3559d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
356004678764SMatthias Ringwald 
3561d1a1f6a4SMatthias Ringwald     log_info_key("dhk", sm_persistent_dhk);
3562d1a1f6a4SMatthias Ringwald     dkg_state = DKG_READY;
356370b44dd4SMatthias Ringwald     sm_trigger_run();
35647df18c15SMatthias Ringwald }
3565d1a1f6a4SMatthias Ringwald 
3566d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_rau(void *arg){
3567d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3568d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
356904678764SMatthias Ringwald 
35706535961aSMatthias Ringwald     (void)memcpy(&sm_random_address[3], &sm_aes128_ciphertext[13], 3);
3571e91ddb40SMatthias Ringwald     rau_state = RAU_IDLE;
3572e91ddb40SMatthias Ringwald     hci_le_random_address_set(sm_random_address);
3573e91ddb40SMatthias Ringwald 
357470b44dd4SMatthias Ringwald     sm_trigger_run();
357551fa0b28SMatthias Ringwald }
35767df18c15SMatthias Ringwald 
3577d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_rau(void * arg){
3578d1a1f6a4SMatthias Ringwald     UNUSED(arg);
35793deb3ec6SMatthias Ringwald     // non-resolvable vs. resolvable
35803deb3ec6SMatthias Ringwald     switch (gap_random_adress_type){
35813deb3ec6SMatthias Ringwald         case GAP_RANDOM_ADDRESS_RESOLVABLE:
35823deb3ec6SMatthias Ringwald             // resolvable: use random as prand and calc address hash
35833deb3ec6SMatthias Ringwald             // "The two most significant bits of prand shall be equal to ‘0’ and ‘1"
35844ea43905SMatthias Ringwald             sm_random_address[0u] &= 0x3fu;
35854ea43905SMatthias Ringwald             sm_random_address[0u] |= 0x40u;
35863deb3ec6SMatthias Ringwald             rau_state = RAU_GET_ENC;
35873deb3ec6SMatthias Ringwald             break;
35883deb3ec6SMatthias Ringwald         case GAP_RANDOM_ADDRESS_NON_RESOLVABLE:
35893deb3ec6SMatthias Ringwald         default:
35903deb3ec6SMatthias Ringwald             // "The two most significant bits of the address shall be equal to ‘0’""
35914ea43905SMatthias Ringwald             sm_random_address[0u] &= 0x3fu;
35922954e6c6SMatthias Ringwald             rau_state = RAU_IDLE;
3593e91ddb40SMatthias Ringwald             hci_le_random_address_set(sm_random_address);
35943deb3ec6SMatthias Ringwald             break;
35953deb3ec6SMatthias Ringwald     }
359670b44dd4SMatthias Ringwald     sm_trigger_run();
35973deb3ec6SMatthias Ringwald }
35983deb3ec6SMatthias Ringwald 
3599c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
36006ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_send_pairing_random(void * arg){
3601f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3602f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3603f3582630SMatthias Ringwald     if (connection == NULL) return;
3604c59d0c92SMatthias Ringwald 
360565a9a04eSMatthias Ringwald     connection->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
360670b44dd4SMatthias Ringwald     sm_trigger_run();
360765a9a04eSMatthias Ringwald }
3608d1a1f6a4SMatthias Ringwald 
36096ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_w2_cmac_for_confirmation(void * arg){
36106ca80073SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
36116ca80073SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
36126ca80073SMatthias Ringwald     if (connection == NULL) return;
36136ca80073SMatthias Ringwald 
3614b35a3de2SMatthias Ringwald     connection->sm_engine_state = SM_SC_W2_CMAC_FOR_CONFIRMATION;
361570b44dd4SMatthias Ringwald     sm_trigger_run();
3616d1a1f6a4SMatthias Ringwald }
3617f1c1783eSMatthias Ringwald #endif
3618f1c1783eSMatthias Ringwald 
3619d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_random(void * arg){
3620f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3621f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3622f3582630SMatthias Ringwald     if (connection == NULL) return;
3623f3582630SMatthias Ringwald 
3624d1a1f6a4SMatthias Ringwald     connection->sm_engine_state = SM_PH2_C1_GET_ENC_A;
362570b44dd4SMatthias Ringwald     sm_trigger_run();
3626d1a1f6a4SMatthias Ringwald }
3627d1a1f6a4SMatthias Ringwald 
3628d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_tk(void * arg){
3629f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3630f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3631f3582630SMatthias Ringwald     if (connection == NULL) return;
3632f3582630SMatthias Ringwald 
3633caf15bf3SMatthias Ringwald     sm_reset_tk();
3634caf15bf3SMatthias Ringwald     uint32_t tk;
36355ce1359eSMatthias Ringwald     if (sm_fixed_passkey_in_display_role == 0xffffffffU){
36363deb3ec6SMatthias Ringwald         // map random to 0-999999 without speding much cycles on a modulus operation
3637d1a1f6a4SMatthias Ringwald         tk = little_endian_read_32(sm_random_data,0);
36383deb3ec6SMatthias Ringwald         tk = tk & 0xfffff;  // 1048575
36394ea43905SMatthias Ringwald         if (tk >= 999999u){
36404ea43905SMatthias Ringwald             tk = tk - 999999u;
36413deb3ec6SMatthias Ringwald         }
3642caf15bf3SMatthias Ringwald     } else {
3643caf15bf3SMatthias Ringwald         // override with pre-defined passkey
36444b8c611fSMatthias Ringwald         tk = sm_fixed_passkey_in_display_role;
3645caf15bf3SMatthias Ringwald     }
3646f8fbdce0SMatthias Ringwald     big_endian_store_32(setup->sm_tk, 12, tk);
364742134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
36483deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
36493deb3ec6SMatthias Ringwald     } else {
3650b41539d5SMatthias Ringwald         if (setup->sm_use_secure_connections){
3651b41539d5SMatthias Ringwald             connection->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
3652b41539d5SMatthias Ringwald         } else {
36533deb3ec6SMatthias Ringwald             connection->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
36543deb3ec6SMatthias Ringwald             sm_trigger_user_response(connection);
36553deb3ec6SMatthias Ringwald             // response_idle == nothing <--> sm_trigger_user_response() did not require response
36563deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
3657f3582630SMatthias 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);
36583deb3ec6SMatthias Ringwald             }
36593deb3ec6SMatthias Ringwald         }
3660b41539d5SMatthias Ringwald     }
366170b44dd4SMatthias Ringwald     sm_trigger_run();
36623deb3ec6SMatthias Ringwald }
3663d1a1f6a4SMatthias Ringwald 
3664d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph3_div(void * arg){
3665f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3666f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3667f3582630SMatthias Ringwald     if (connection == NULL) return;
3668f3582630SMatthias Ringwald 
3669d1a1f6a4SMatthias Ringwald     // use 16 bit from random value as div
3670d1a1f6a4SMatthias Ringwald     setup->sm_local_div = big_endian_read_16(sm_random_data, 0);
3671d1a1f6a4SMatthias Ringwald     log_info_hex16("div", setup->sm_local_div);
3672d1a1f6a4SMatthias Ringwald     connection->sm_engine_state = SM_PH3_Y_GET_ENC;
367370b44dd4SMatthias Ringwald     sm_trigger_run();
3674d1a1f6a4SMatthias Ringwald }
3675d1a1f6a4SMatthias Ringwald 
3676d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph3_random(void * arg){
3677f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3678f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3679f3582630SMatthias Ringwald     if (connection == NULL) return;
3680f3582630SMatthias Ringwald 
3681d1a1f6a4SMatthias Ringwald     reverse_64(sm_random_data, setup->sm_local_rand);
36823deb3ec6SMatthias Ringwald     // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
36834ea43905SMatthias Ringwald     setup->sm_local_rand[7u] = (setup->sm_local_rand[7u] & 0xf0u) + (connection->sm_actual_encryption_key_size - 1u);
36843deb3ec6SMatthias Ringwald     // no db for authenticated flag hack: store flag in bit 4 of LSB
36854ea43905SMatthias Ringwald     setup->sm_local_rand[7u] = (setup->sm_local_rand[7u] & 0xefu) + (connection->sm_connection_authenticated << 4u);
36868b3ffec5SMatthias 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);
36873deb3ec6SMatthias Ringwald }
3688899e6e02SMatthias Ringwald static void sm_validate_er_ir(void){
3689899e6e02SMatthias Ringwald     // warn about default ER/IR
36901979f09cSMatthias Ringwald     bool warning = false;
3691899e6e02SMatthias Ringwald     if (sm_ir_is_default()){
36921979f09cSMatthias Ringwald         warning = true;
3693899e6e02SMatthias Ringwald         log_error("Persistent IR not set with sm_set_ir. Use of private addresses will cause pairing issues");
3694899e6e02SMatthias Ringwald     }
3695899e6e02SMatthias Ringwald     if (sm_er_is_default()){
36961979f09cSMatthias Ringwald         warning = true;
3697899e6e02SMatthias Ringwald         log_error("Persistent ER not set with sm_set_er. Legacy Pairing LTK is not secure");
3698899e6e02SMatthias Ringwald     }
369921045273SMatthias Ringwald     if (warning) {
3700899e6e02SMatthias Ringwald         log_error("Please configure btstack_tlv to let BTstack setup ER and IR keys");
3701899e6e02SMatthias Ringwald     }
370221045273SMatthias Ringwald }
3703899e6e02SMatthias Ringwald 
3704899e6e02SMatthias Ringwald static void sm_handle_random_result_ir(void *arg){
37051979f09cSMatthias Ringwald     sm_persistent_keys_random_active = false;
37069305033eSMatthias Ringwald     if (arg != NULL){
3707899e6e02SMatthias Ringwald         // key generated, store in tlv
37084ea43905SMatthias Ringwald         int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16u);
3709899e6e02SMatthias Ringwald         log_info("Generated IR key. Store in TLV status: %d", status);
3710e0d13a19SMilanka Ringwald         UNUSED(status);
3711899e6e02SMatthias Ringwald     }
3712899e6e02SMatthias Ringwald     log_info_key("IR", sm_persistent_ir);
37138d9b6072SMatthias Ringwald     dkg_state = DKG_CALC_IRK;
3714841468bbSMatthias Ringwald 
3715841468bbSMatthias Ringwald     if (test_use_fixed_local_irk){
3716841468bbSMatthias Ringwald         log_info_key("IRK", sm_persistent_irk);
3717841468bbSMatthias Ringwald         dkg_state = DKG_CALC_DHK;
3718841468bbSMatthias Ringwald     }
3719841468bbSMatthias Ringwald 
372070b44dd4SMatthias Ringwald     sm_trigger_run();
3721899e6e02SMatthias Ringwald }
3722899e6e02SMatthias Ringwald 
3723899e6e02SMatthias Ringwald static void sm_handle_random_result_er(void *arg){
37241979f09cSMatthias Ringwald     sm_persistent_keys_random_active = false;
37259305033eSMatthias Ringwald     if (arg != 0){
3726899e6e02SMatthias Ringwald         // key generated, store in tlv
37274ea43905SMatthias Ringwald         int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16u);
3728899e6e02SMatthias Ringwald         log_info("Generated ER key. Store in TLV status: %d", status);
3729e0d13a19SMilanka Ringwald         UNUSED(status);
3730899e6e02SMatthias Ringwald     }
3731899e6e02SMatthias Ringwald     log_info_key("ER", sm_persistent_er);
3732899e6e02SMatthias Ringwald 
3733899e6e02SMatthias Ringwald     // try load ir
37344ea43905SMatthias Ringwald     int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16u);
3735899e6e02SMatthias Ringwald     if (key_size == 16){
3736899e6e02SMatthias Ringwald         // ok, let's continue
3737899e6e02SMatthias Ringwald         log_info("IR from TLV");
3738899e6e02SMatthias Ringwald         sm_handle_random_result_ir( NULL );
3739899e6e02SMatthias Ringwald     } else {
3740899e6e02SMatthias Ringwald         // invalid, generate new random one
37411979f09cSMatthias Ringwald         sm_persistent_keys_random_active = true;
3742899e6e02SMatthias Ringwald         btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_ir, 16, &sm_handle_random_result_ir, &sm_persistent_ir);
3743899e6e02SMatthias Ringwald     }
3744899e6e02SMatthias Ringwald }
37453deb3ec6SMatthias Ringwald 
3746f664b5e8SMatthias Ringwald static void sm_connection_init(sm_connection_t * sm_conn, hci_con_handle_t con_handle, uint8_t role, uint8_t addr_type, bd_addr_t address){
3747f664b5e8SMatthias Ringwald 
3748f664b5e8SMatthias Ringwald     // connection info
3749f664b5e8SMatthias Ringwald     sm_conn->sm_handle = con_handle;
3750f664b5e8SMatthias Ringwald     sm_conn->sm_role = role;
3751f664b5e8SMatthias Ringwald     sm_conn->sm_peer_addr_type = addr_type;
3752f664b5e8SMatthias Ringwald     memcpy(sm_conn->sm_peer_address, address, 6);
3753f664b5e8SMatthias Ringwald 
3754f664b5e8SMatthias Ringwald     // security properties
3755f664b5e8SMatthias Ringwald     sm_conn->sm_connection_encrypted = 0;
3756f664b5e8SMatthias Ringwald     sm_conn->sm_connection_authenticated = 0;
3757f664b5e8SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_UNKNOWN;
3758f664b5e8SMatthias Ringwald     sm_conn->sm_le_db_index = -1;
3759f664b5e8SMatthias Ringwald     sm_conn->sm_reencryption_active = false;
3760f664b5e8SMatthias Ringwald 
3761f664b5e8SMatthias Ringwald     // prepare CSRK lookup (does not involve setup)
3762f664b5e8SMatthias Ringwald     sm_conn->sm_irk_lookup_state = IRK_LOOKUP_W4_READY;
3763f664b5e8SMatthias Ringwald 
3764f664b5e8SMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_IDLE;
3765f664b5e8SMatthias Ringwald }
3766f664b5e8SMatthias Ringwald 
3767599e89daSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3768599e89daSMatthias Ringwald static void sm_event_handle_classic_encryption_event(sm_connection_t * sm_conn, hci_con_handle_t con_handle){
3769599e89daSMatthias Ringwald     // CTKD requires BR/EDR Secure Connection
3770599e89daSMatthias Ringwald     if (sm_conn->sm_connection_encrypted != 2) return;
3771599e89daSMatthias Ringwald     // prepare for pairing request
3772599e89daSMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
3773599e89daSMatthias Ringwald         sm_conn->sm_engine_state = SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST;
3774599e89daSMatthias Ringwald     } else if (sm_conn->sm_pairing_requested){
3775599e89daSMatthias Ringwald         // check if remote supports fixed channels
3776599e89daSMatthias Ringwald         bool defer = true;
3777599e89daSMatthias Ringwald         const hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
3778599e89daSMatthias Ringwald         if (hci_connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_DONE){
3779599e89daSMatthias Ringwald             // check if remote supports SMP over BR/EDR
3780599e89daSMatthias Ringwald             if ((hci_connection->l2cap_state.fixed_channels_supported & (1 << L2CAP_CID_BR_EDR_SECURITY_MANAGER)) != 0){
3781599e89daSMatthias Ringwald                 log_info("CTKD: SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST");
3782599e89daSMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST;
3783599e89daSMatthias Ringwald             } else {
3784599e89daSMatthias Ringwald                 defer = false;
3785599e89daSMatthias Ringwald             }
3786599e89daSMatthias Ringwald         } else {
3787599e89daSMatthias Ringwald             // wait for fixed channel info
3788599e89daSMatthias Ringwald             log_info("CTKD: SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK");
3789599e89daSMatthias Ringwald             sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK;
3790599e89daSMatthias Ringwald         }
3791599e89daSMatthias Ringwald         if (defer){
3792599e89daSMatthias Ringwald             hci_dedicated_bonding_defer_disconnect(con_handle, true);
3793599e89daSMatthias Ringwald         }
3794599e89daSMatthias Ringwald     }
3795599e89daSMatthias Ringwald }
3796599e89daSMatthias Ringwald #endif
3797599e89daSMatthias Ringwald 
3798d9a7306aSMatthias Ringwald static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
37993deb3ec6SMatthias Ringwald 
3800cbdfe9f7SMatthias Ringwald     UNUSED(channel);    // ok: there is no channel
3801cbdfe9f7SMatthias Ringwald     UNUSED(size);       // ok: fixed format HCI events
38029ec2630cSMatthias Ringwald 
38033deb3ec6SMatthias Ringwald     sm_connection_t * sm_conn;
3804711e6c80SMatthias Ringwald     hci_con_handle_t  con_handle;
3805fbe050beSMatthias Ringwald     uint8_t           status;
3806f664b5e8SMatthias Ringwald     bd_addr_t         addr;
3807f664b5e8SMatthias Ringwald 
38083deb3ec6SMatthias Ringwald     switch (packet_type) {
38093deb3ec6SMatthias Ringwald 
38103deb3ec6SMatthias Ringwald 		case HCI_EVENT_PACKET:
38110e2df43fSMatthias Ringwald 			switch (hci_event_packet_get_type(packet)) {
38123deb3ec6SMatthias Ringwald 
38133deb3ec6SMatthias Ringwald                 case BTSTACK_EVENT_STATE:
3814745015f6SMatthias Ringwald                     switch (btstack_event_state_get_state(packet)){
3815745015f6SMatthias Ringwald                         case HCI_STATE_WORKING:
38163deb3ec6SMatthias Ringwald                             log_info("HCI Working!");
3817899e6e02SMatthias Ringwald                             // setup IR/ER with TLV
3818899e6e02SMatthias Ringwald                             btstack_tlv_get_instance(&sm_tlv_impl, &sm_tlv_context);
38199305033eSMatthias Ringwald                             if (sm_tlv_impl != NULL){
38204ea43905SMatthias Ringwald                                 int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16u);
3821899e6e02SMatthias Ringwald                                 if (key_size == 16){
3822899e6e02SMatthias Ringwald                                     // ok, let's continue
3823899e6e02SMatthias Ringwald                                     log_info("ER from TLV");
3824899e6e02SMatthias Ringwald                                     sm_handle_random_result_er( NULL );
3825899e6e02SMatthias Ringwald                                 } else {
3826899e6e02SMatthias Ringwald                                     // invalid, generate random one
38271979f09cSMatthias Ringwald                                     sm_persistent_keys_random_active = true;
3828899e6e02SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_er, 16, &sm_handle_random_result_er, &sm_persistent_er);
3829899e6e02SMatthias Ringwald                                 }
3830899e6e02SMatthias Ringwald                             } else {
3831899e6e02SMatthias Ringwald                                 sm_validate_er_ir();
38328d9b6072SMatthias Ringwald                                 dkg_state = DKG_CALC_IRK;
3833841468bbSMatthias Ringwald 
3834841468bbSMatthias Ringwald                                 if (test_use_fixed_local_irk){
3835841468bbSMatthias Ringwald                                     log_info_key("IRK", sm_persistent_irk);
3836841468bbSMatthias Ringwald                                     dkg_state = DKG_CALC_DHK;
3837841468bbSMatthias Ringwald                                 }
3838899e6e02SMatthias Ringwald                             }
38391bf086daSMatthias Ringwald 
384015211b85SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
384115211b85SMatthias Ringwald                             // trigger ECC key generation
384215211b85SMatthias Ringwald                             if (ec_key_generation_state == EC_KEY_GENERATION_IDLE){
384315211b85SMatthias Ringwald                                 sm_ec_generate_new_key();
384415211b85SMatthias Ringwald                             }
384515211b85SMatthias Ringwald #endif
384615211b85SMatthias Ringwald 
38471bf086daSMatthias Ringwald                             // restart random address updates after power cycle
38484a688bd1SMatthias Ringwald                             if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_STATIC){
38494a688bd1SMatthias Ringwald                                 gap_random_address_set(sm_random_address);
38504a688bd1SMatthias Ringwald                             } else {
38511bf086daSMatthias Ringwald                                 gap_random_address_set_mode(gap_random_adress_type);
38524a688bd1SMatthias Ringwald                             }
3853745015f6SMatthias Ringwald                             break;
3854745015f6SMatthias Ringwald 
3855745015f6SMatthias Ringwald                         case HCI_STATE_OFF:
38567f775357SMatthias Ringwald                         case HCI_STATE_HALTING:
3857cbdd51cfSMatthias Ringwald                             log_info("SM: reset state");
3858745015f6SMatthias Ringwald                             // stop random address update
3859745015f6SMatthias Ringwald                             gap_random_address_update_stop();
3860cbdd51cfSMatthias Ringwald                             // reset state
3861cbdd51cfSMatthias Ringwald                             sm_state_reset();
3862745015f6SMatthias Ringwald                             break;
3863745015f6SMatthias Ringwald 
3864745015f6SMatthias Ringwald                         default:
3865745015f6SMatthias Ringwald                             break;
38663deb3ec6SMatthias Ringwald                     }
38673deb3ec6SMatthias Ringwald 					break;
3868c18be159SMatthias Ringwald 
38692d095694SMatthias Ringwald #ifdef ENABLE_CLASSIC
38702d095694SMatthias Ringwald 			    case HCI_EVENT_CONNECTION_COMPLETE:
38712d095694SMatthias Ringwald 			        // ignore if connection failed
38722d095694SMatthias Ringwald 			        if (hci_event_connection_complete_get_status(packet)) return;
38733deb3ec6SMatthias Ringwald 
38742d095694SMatthias Ringwald 			        con_handle = hci_event_connection_complete_get_connection_handle(packet);
38752d095694SMatthias Ringwald 			        sm_conn = sm_get_connection_for_handle(con_handle);
38762d095694SMatthias Ringwald 			        if (!sm_conn) break;
38772d095694SMatthias Ringwald 
38782d095694SMatthias Ringwald                     hci_event_connection_complete_get_bd_addr(packet, addr);
38792d095694SMatthias Ringwald 			        sm_connection_init(sm_conn,
38802d095694SMatthias Ringwald                                        con_handle,
38812d095694SMatthias Ringwald                                        (uint8_t) gap_get_role(con_handle),
3882f72f7944SMatthias Ringwald                                        BD_ADDR_TYPE_LE_PUBLIC,
38832d095694SMatthias Ringwald                                        addr);
38842d095694SMatthias Ringwald 			        // classic connection corresponds to public le address
38852d095694SMatthias Ringwald 			        sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_PUBLIC;
38862d095694SMatthias Ringwald                     gap_local_bd_addr(sm_conn->sm_own_address);
38872d095694SMatthias Ringwald                     sm_conn->sm_cid = L2CAP_CID_BR_EDR_SECURITY_MANAGER;
3888c18be159SMatthias Ringwald                     sm_conn->sm_engine_state = SM_BR_EDR_W4_ENCRYPTION_COMPLETE;
38892d095694SMatthias Ringwald 			        break;
38902d095694SMatthias Ringwald #endif
3891c18be159SMatthias Ringwald 
3892c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3893c18be159SMatthias Ringwald 			    case HCI_EVENT_SIMPLE_PAIRING_COMPLETE:
3894c18be159SMatthias Ringwald 			        if (hci_event_simple_pairing_complete_get_status(packet) != ERROR_CODE_SUCCESS) break;
3895c18be159SMatthias Ringwald                     hci_event_simple_pairing_complete_get_bd_addr(packet, addr);
3896c18be159SMatthias Ringwald                     sm_conn = sm_get_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL);
3897c18be159SMatthias Ringwald                     if (sm_conn == NULL) break;
3898c18be159SMatthias Ringwald                     sm_conn->sm_pairing_requested = 1;
3899c18be159SMatthias Ringwald 			        break;
3900c18be159SMatthias Ringwald #endif
3901c18be159SMatthias Ringwald 
39029d1eff91SMatthias Ringwald 			    case HCI_EVENT_META_GAP:
39039d1eff91SMatthias Ringwald 			        switch (hci_event_gap_meta_get_subevent_code(packet)) {
39049d1eff91SMatthias Ringwald 			            case GAP_SUBEVENT_LE_CONNECTION_COMPLETE:
3905f664b5e8SMatthias Ringwald 			                // ignore if connection failed
39069d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_status(packet) != ERROR_CODE_SUCCESS) break;
39073deb3ec6SMatthias Ringwald 
39089d1eff91SMatthias Ringwald 			                con_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
3909711e6c80SMatthias Ringwald 			                sm_conn = sm_get_connection_for_handle(con_handle);
39103deb3ec6SMatthias Ringwald 			                if (!sm_conn) break;
39113deb3ec6SMatthias Ringwald 
39129d1eff91SMatthias Ringwald 			                gap_subevent_le_connection_complete_get_peer_address(packet, addr);
3913f664b5e8SMatthias Ringwald 			                sm_connection_init(sm_conn,
3914f664b5e8SMatthias Ringwald                                                con_handle,
39159d1eff91SMatthias Ringwald                                                gap_subevent_le_connection_complete_get_role(packet),
39169d1eff91SMatthias Ringwald                                                gap_subevent_le_connection_complete_get_peer_address_type(packet),
3917f664b5e8SMatthias Ringwald                                                addr);
3918687a03c8SMatthias Ringwald 			                sm_conn->sm_cid = L2CAP_CID_SECURITY_MANAGER_PROTOCOL;
3919f664b5e8SMatthias Ringwald 
3920f664b5e8SMatthias Ringwald 			                // track our addr used for this connection and set state
3921b6f39a74SMatthias Ringwald     #ifdef ENABLE_LE_PERIPHERAL
39229d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_role(packet) != 0){
3923ba9fc867SMatthias Ringwald 			                    // responder - use own address from advertisements
3924ba9fc867SMatthias Ringwald 			                    gap_le_get_own_advertisements_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address);
3925f664b5e8SMatthias Ringwald 			                    sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
3926b892db1cSMatthias Ringwald 			                }
3927b892db1cSMatthias Ringwald     #endif
3928b892db1cSMatthias Ringwald     #ifdef ENABLE_LE_CENTRAL
39299d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_role(packet) == 0){
3930ba9fc867SMatthias Ringwald 			                    // initiator - use own address from create connection
3931ba9fc867SMatthias Ringwald 			                    gap_le_get_own_connection_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address);
39323deb3ec6SMatthias Ringwald 			                    sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
39333deb3ec6SMatthias Ringwald 			                }
3934b892db1cSMatthias Ringwald     #endif
39353deb3ec6SMatthias Ringwald 			                break;
39369d1eff91SMatthias Ringwald 			            default:
39379d1eff91SMatthias Ringwald 			                break;
39389d1eff91SMatthias Ringwald 			        }
39399d1eff91SMatthias Ringwald 			        break;
39409d1eff91SMatthias Ringwald                 case HCI_EVENT_LE_META:
39419d1eff91SMatthias Ringwald                     switch (hci_event_le_meta_get_subevent_code(packet)) {
39423deb3ec6SMatthias Ringwald                         case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST:
39439d1eff91SMatthias Ringwald                             con_handle = hci_subevent_le_long_term_key_request_get_connection_handle(packet);
3944711e6c80SMatthias Ringwald                             sm_conn = sm_get_connection_for_handle(con_handle);
39453deb3ec6SMatthias Ringwald                             if (!sm_conn) break;
39463deb3ec6SMatthias Ringwald 
39473deb3ec6SMatthias Ringwald                             log_info("LTK Request: state %u", sm_conn->sm_engine_state);
39483deb3ec6SMatthias Ringwald                             if (sm_conn->sm_engine_state == SM_RESPONDER_PH2_W4_LTK_REQUEST){
39493deb3ec6SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_PH2_CALC_STK;
39503deb3ec6SMatthias Ringwald                                 break;
39513deb3ec6SMatthias Ringwald                             }
3952c6b7cbd9SMatthias Ringwald                             if (sm_conn->sm_engine_state == SM_SC_W4_LTK_REQUEST_SC){
3953778b6aadSMatthias Ringwald                                 // PH2 SEND LTK as we need to exchange keys in PH3
3954778b6aadSMatthias Ringwald                                 sm_conn->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
3955e53be891SMatthias Ringwald                                 break;
3956e53be891SMatthias Ringwald                             }
39573deb3ec6SMatthias Ringwald 
39583deb3ec6SMatthias Ringwald                             // store rand and ediv
39599c80e4ccSMatthias Ringwald                             reverse_64(&packet[5], sm_conn->sm_local_rand);
39609d1eff91SMatthias Ringwald                             sm_conn->sm_local_ediv = hci_subevent_le_long_term_key_request_get_encryption_diversifier(packet);
3961549ad5d2SMatthias Ringwald 
3962549ad5d2SMatthias Ringwald                             // For Legacy Pairing (<=> EDIV != 0 || RAND != NULL), we need to recalculated our LTK as a
3963549ad5d2SMatthias Ringwald                             // potentially stored LTK is from the master
39644ea43905SMatthias Ringwald                             if ((sm_conn->sm_local_ediv != 0u) || !sm_is_null_random(sm_conn->sm_local_rand)){
39656c39055aSMatthias Ringwald                                 if (sm_reconstruct_ltk_without_le_device_db_entry){
396606cd539fSMatthias Ringwald                                     sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
3967549ad5d2SMatthias Ringwald                                     break;
3968549ad5d2SMatthias Ringwald                                 }
39696c39055aSMatthias Ringwald                                 // additionally check if remote is in LE Device DB if requested
39706c39055aSMatthias Ringwald                                 switch(sm_conn->sm_irk_lookup_state){
39716c39055aSMatthias Ringwald                                     case IRK_LOOKUP_FAILED:
39726c39055aSMatthias Ringwald                                         log_info("LTK Request: device not in device db");
39736c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
39746c39055aSMatthias Ringwald                                         break;
39756c39055aSMatthias Ringwald                                     case IRK_LOOKUP_SUCCEEDED:
39766c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
39776c39055aSMatthias Ringwald                                         break;
39786c39055aSMatthias Ringwald                                     default:
39796c39055aSMatthias Ringwald                                         // wait for irk look doen
39806c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK;
39816c39055aSMatthias Ringwald                                         break;
39826c39055aSMatthias Ringwald                                 }
39836c39055aSMatthias Ringwald                                 break;
39846c39055aSMatthias Ringwald                             }
3985549ad5d2SMatthias Ringwald 
3986549ad5d2SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
398706cd539fSMatthias Ringwald                             sm_conn->sm_engine_state = SM_SC_RECEIVED_LTK_REQUEST;
3988549ad5d2SMatthias Ringwald #else
3989549ad5d2SMatthias Ringwald                             log_info("LTK Request: ediv & random are empty, but LE Secure Connections not supported");
3990549ad5d2SMatthias Ringwald                             sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
3991549ad5d2SMatthias Ringwald #endif
39923deb3ec6SMatthias Ringwald                             break;
3993804d3e67SMatthias Ringwald 
39943deb3ec6SMatthias Ringwald                         default:
39953deb3ec6SMatthias Ringwald                             break;
39963deb3ec6SMatthias Ringwald                     }
39973deb3ec6SMatthias Ringwald                     break;
39983deb3ec6SMatthias Ringwald 
39993deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE:
40008601e696SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE_V2:
40013b7fd749SMatthias Ringwald                 	con_handle = hci_event_encryption_change_get_connection_handle(packet);
4002711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
40033deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
40043deb3ec6SMatthias Ringwald 
40053b7fd749SMatthias Ringwald                     sm_conn->sm_connection_encrypted = hci_event_encryption_change_get_encryption_enabled(packet);
40063deb3ec6SMatthias Ringwald                     log_info("Encryption state change: %u, key size %u", sm_conn->sm_connection_encrypted,
40073deb3ec6SMatthias Ringwald                         sm_conn->sm_actual_encryption_key_size);
40083deb3ec6SMatthias Ringwald                     log_info("event handler, state %u", sm_conn->sm_engine_state);
400903a9359aSMatthias Ringwald 
4010fbe050beSMatthias Ringwald                     switch (sm_conn->sm_engine_state){
4011fbe050beSMatthias Ringwald 
40125567aa60SMatthias Ringwald                         case SM_PH4_W4_CONNECTION_ENCRYPTED:
401303a9359aSMatthias Ringwald                             // encryption change event concludes re-encryption for bonded devices (even if it fails)
4014*1d80f1e6SMatthias Ringwald                             if (sm_conn->sm_connection_encrypted != 0u) {
4015fbe050beSMatthias Ringwald                                 status = ERROR_CODE_SUCCESS;
4016*1d80f1e6SMatthias Ringwald                                 if (IS_RESPONDER(sm_conn->sm_role)){
40178d4eef95SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
40188d4eef95SMatthias Ringwald                                 } else {
401903a9359aSMatthias Ringwald                                     sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
40208d4eef95SMatthias Ringwald                                 }
4021fbe050beSMatthias Ringwald                             } else {
4022e28291c1SMatthias Ringwald                                 status = hci_event_encryption_change_get_status(packet);
4023cb6d7eb0SMatthias Ringwald                                 // set state to 'RE-ENCRYPTION FAILED' to allow pairing but prevent other interactions
40243b7fd749SMatthias Ringwald                                 // also, gap_reconnect_security_setup_active will return true
4025cb6d7eb0SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_GENERAL_REENCRYPTION_FAILED;
40263b7fd749SMatthias Ringwald                             }
4027fbe050beSMatthias Ringwald 
4028fbe050beSMatthias Ringwald                             // emit re-encryption complete
402973102768SMatthias Ringwald                             sm_reencryption_complete(sm_conn, status);
4030fbe050beSMatthias Ringwald 
4031c245ca32SMatthias Ringwald                             // notify client, if pairing was requested before
4032c245ca32SMatthias Ringwald                             if (sm_conn->sm_pairing_requested){
4033c245ca32SMatthias Ringwald                                 sm_conn->sm_pairing_requested = 0;
40340ccf6c9cSMatthias Ringwald                                 sm_pairing_complete(sm_conn, status, 0);
403503a9359aSMatthias Ringwald                             }
403603a9359aSMatthias Ringwald 
40373deb3ec6SMatthias Ringwald                             sm_done_for_handle(sm_conn->sm_handle);
40383deb3ec6SMatthias Ringwald                             break;
4039fbe050beSMatthias Ringwald 
40403deb3ec6SMatthias Ringwald                         case SM_PH2_W4_CONNECTION_ENCRYPTED:
4041fbe050beSMatthias Ringwald                             if (!sm_conn->sm_connection_encrypted) break;
404257ff4745SMatthias Ringwald                             // handler for HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE
404357ff4745SMatthias Ringwald                             // contains the same code for this state
4044dd583d9fSMatthias Ringwald                             sm_conn->sm_connection_sc = setup->sm_use_secure_connections;
404542134bc6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
40463deb3ec6SMatthias Ringwald                                 // slave
404757ff4745SMatthias Ringwald                                 if (sm_conn->sm_connection_sc){
4048bbf8db22SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
4049bbf8db22SMatthias Ringwald                                 } else {
4050f3582630SMatthias 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);
4051bbf8db22SMatthias Ringwald                                 }
40523deb3ec6SMatthias Ringwald                             } else {
40533deb3ec6SMatthias Ringwald                                 // master
405461d1a45eSMatthias Ringwald                                 if (sm_key_distribution_all_received()){
40553deb3ec6SMatthias Ringwald                                     // skip receiving keys as there are none
40563deb3ec6SMatthias Ringwald                                     sm_key_distribution_handle_all_received(sm_conn);
4057f3582630SMatthias 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);
40583deb3ec6SMatthias Ringwald                                 } else {
40593deb3ec6SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
40603deb3ec6SMatthias Ringwald                                 }
40613deb3ec6SMatthias Ringwald                             }
40623deb3ec6SMatthias Ringwald                             break;
4063c18be159SMatthias Ringwald 
4064c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4065c18be159SMatthias Ringwald                         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
4066599e89daSMatthias Ringwald                             sm_event_handle_classic_encryption_event(sm_conn, con_handle);
4067c18be159SMatthias Ringwald                             break;
4068c18be159SMatthias Ringwald #endif
40693deb3ec6SMatthias Ringwald                         default:
40703deb3ec6SMatthias Ringwald                             break;
40713deb3ec6SMatthias Ringwald                     }
40723deb3ec6SMatthias Ringwald                     break;
40733deb3ec6SMatthias Ringwald 
40743deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE:
4075711e6c80SMatthias Ringwald                     con_handle = little_endian_read_16(packet, 3);
4076711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
40773deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
40783deb3ec6SMatthias Ringwald 
40793deb3ec6SMatthias Ringwald                     log_info("Encryption key refresh complete, key size %u", sm_conn->sm_actual_encryption_key_size);
40803deb3ec6SMatthias Ringwald                     log_info("event handler, state %u", sm_conn->sm_engine_state);
40813deb3ec6SMatthias Ringwald                     // continue if part of initial pairing
40823deb3ec6SMatthias Ringwald                     switch (sm_conn->sm_engine_state){
40835567aa60SMatthias Ringwald                         case SM_PH4_W4_CONNECTION_ENCRYPTED:
4084*1d80f1e6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
40855567aa60SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
40865567aa60SMatthias Ringwald                             } else {
40873deb3ec6SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
40885567aa60SMatthias Ringwald                             }
40893deb3ec6SMatthias Ringwald                             sm_done_for_handle(sm_conn->sm_handle);
40903deb3ec6SMatthias Ringwald                             break;
40913deb3ec6SMatthias Ringwald                         case SM_PH2_W4_CONNECTION_ENCRYPTED:
409257ff4745SMatthias Ringwald                             // handler for HCI_EVENT_ENCRYPTION_CHANGE
409357ff4745SMatthias Ringwald                             // contains the same code for this state
409457ff4745SMatthias Ringwald                             sm_conn->sm_connection_sc = setup->sm_use_secure_connections;
409542134bc6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
40963deb3ec6SMatthias Ringwald                                 // slave
409757ff4745SMatthias Ringwald                                 if (sm_conn->sm_connection_sc){
409857ff4745SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
409957ff4745SMatthias Ringwald                                 } else {
4100f3582630SMatthias 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);
410157ff4745SMatthias Ringwald                                 }
41023deb3ec6SMatthias Ringwald                             } else {
41033deb3ec6SMatthias Ringwald                                 // master
410457ff4745SMatthias Ringwald                                 if (sm_key_distribution_all_received()){
410557ff4745SMatthias Ringwald                                     // skip receiving keys as there are none
410657ff4745SMatthias Ringwald                                     sm_key_distribution_handle_all_received(sm_conn);
410757ff4745SMatthias 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);
410857ff4745SMatthias Ringwald                                 } else {
41093deb3ec6SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
41103deb3ec6SMatthias Ringwald                                 }
411157ff4745SMatthias Ringwald                             }
41123deb3ec6SMatthias Ringwald                             break;
411394219034SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
411494219034SMatthias Ringwald                         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
411594219034SMatthias Ringwald                             sm_event_handle_classic_encryption_event(sm_conn, con_handle);
411694219034SMatthias Ringwald                             break;
411794219034SMatthias Ringwald #endif
41183deb3ec6SMatthias Ringwald                         default:
41193deb3ec6SMatthias Ringwald                             break;
41203deb3ec6SMatthias Ringwald                     }
41213deb3ec6SMatthias Ringwald                     break;
41223deb3ec6SMatthias Ringwald 
41233deb3ec6SMatthias Ringwald 
41243deb3ec6SMatthias Ringwald                 case HCI_EVENT_DISCONNECTION_COMPLETE:
4125711e6c80SMatthias Ringwald                     con_handle = little_endian_read_16(packet, 3);
4126711e6c80SMatthias Ringwald                     sm_done_for_handle(con_handle);
4127711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
41283deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
41293deb3ec6SMatthias Ringwald 
413003f736b1SMatthias Ringwald                     // pairing failed, if it was ongoing
41317f3f442dSMatthias Ringwald                     switch (sm_conn->sm_engine_state){
41327f3f442dSMatthias Ringwald                         case SM_GENERAL_IDLE:
41337f3f442dSMatthias Ringwald                         case SM_INITIATOR_CONNECTED:
41347f3f442dSMatthias Ringwald                         case SM_RESPONDER_IDLE:
41357f3f442dSMatthias Ringwald                             break;
41367f3f442dSMatthias Ringwald                         default:
413768a18fb9SMatthias Ringwald                             sm_reencryption_complete(sm_conn, ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION);
41380ccf6c9cSMatthias Ringwald                             sm_pairing_complete(sm_conn, ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION, 0);
41397f3f442dSMatthias Ringwald                             break;
414003f736b1SMatthias Ringwald                     }
4141accbde80SMatthias Ringwald 
41423deb3ec6SMatthias Ringwald                     sm_conn->sm_engine_state = SM_GENERAL_IDLE;
41433deb3ec6SMatthias Ringwald                     sm_conn->sm_handle = 0;
41443deb3ec6SMatthias Ringwald                     break;
41453deb3ec6SMatthias Ringwald 
41463deb3ec6SMatthias Ringwald                 case HCI_EVENT_COMMAND_COMPLETE:
4147f7811256SMatthias Ringwald                     if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_BD_ADDR) {
41489091c5f5SMatthias Ringwald                         // set local addr for le device db
414933373e40SMatthias Ringwald                         reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1], addr);
41500c130b19SMatthias Ringwald                         le_device_db_set_local_bd_addr(addr);
415133373e40SMatthias Ringwald                     }
415265b44ffdSMatthias Ringwald                     break;
4153a036ae12SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4154a036ae12SMatthias Ringwald                 case L2CAP_EVENT_INFORMATION_RESPONSE:
4155a036ae12SMatthias Ringwald                     con_handle = l2cap_event_information_response_get_con_handle(packet);
4156a036ae12SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
4157a036ae12SMatthias Ringwald                     if (!sm_conn) break;
4158a036ae12SMatthias Ringwald                     if (sm_conn->sm_engine_state == SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK){
4159a036ae12SMatthias Ringwald                         // check if remote supports SMP over BR/EDR
4160a036ae12SMatthias Ringwald                         const hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
4161a036ae12SMatthias Ringwald                         if ((hci_connection->l2cap_state.fixed_channels_supported & (1 << L2CAP_CID_BR_EDR_SECURITY_MANAGER)) != 0){
4162a036ae12SMatthias Ringwald                             sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST;
4163a036ae12SMatthias Ringwald                         } else {
4164a036ae12SMatthias Ringwald                             sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
4165f82b8f4bSMatthias Ringwald                             hci_dedicated_bonding_defer_disconnect(con_handle, false);
4166a036ae12SMatthias Ringwald                         }
4167a036ae12SMatthias Ringwald                     }
4168a036ae12SMatthias Ringwald                     break;
4169a036ae12SMatthias Ringwald #endif
417065b44ffdSMatthias Ringwald                 default:
417165b44ffdSMatthias Ringwald                     break;
41723deb3ec6SMatthias Ringwald 			}
417365b44ffdSMatthias Ringwald             break;
417465b44ffdSMatthias Ringwald         default:
417565b44ffdSMatthias Ringwald             break;
41763deb3ec6SMatthias Ringwald 	}
41773deb3ec6SMatthias Ringwald 
41783deb3ec6SMatthias Ringwald     sm_run();
41793deb3ec6SMatthias Ringwald }
41803deb3ec6SMatthias Ringwald 
41813deb3ec6SMatthias Ringwald static inline int sm_calc_actual_encryption_key_size(int other){
41823deb3ec6SMatthias Ringwald     if (other < sm_min_encryption_key_size) return 0;
41833deb3ec6SMatthias Ringwald     if (other < sm_max_encryption_key_size) return other;
41843deb3ec6SMatthias Ringwald     return sm_max_encryption_key_size;
41853deb3ec6SMatthias Ringwald }
41863deb3ec6SMatthias Ringwald 
4187945888f5SMatthias Ringwald 
418831c09488SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4189*1d80f1e6SMatthias Ringwald static bool sm_just_works_or_numeric_comparison(stk_generation_method_t method){
4190945888f5SMatthias Ringwald     switch (method){
4191945888f5SMatthias Ringwald         case JUST_WORKS:
419247fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
4193*1d80f1e6SMatthias Ringwald             return true;
4194945888f5SMatthias Ringwald         default:
4195*1d80f1e6SMatthias Ringwald             return false;
4196945888f5SMatthias Ringwald     }
4197945888f5SMatthias Ringwald }
419807036a04SMatthias Ringwald // responder
4199945888f5SMatthias Ringwald 
4200*1d80f1e6SMatthias Ringwald static bool sm_passkey_used(stk_generation_method_t method){
4201688a08f9SMatthias Ringwald     switch (method){
4202688a08f9SMatthias Ringwald         case PK_RESP_INPUT:
4203*1d80f1e6SMatthias Ringwald             return true;
4204688a08f9SMatthias Ringwald         default:
4205688a08f9SMatthias Ringwald             return 0;
4206688a08f9SMatthias Ringwald     }
4207688a08f9SMatthias Ringwald }
420840c5d850SMatthias Ringwald 
42096777d8fdSMatthias Ringwald static bool sm_passkey_entry(stk_generation_method_t method){
421040c5d850SMatthias Ringwald     switch (method){
421140c5d850SMatthias Ringwald         case PK_RESP_INPUT:
421240c5d850SMatthias Ringwald         case PK_INIT_INPUT:
421347fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
42146777d8fdSMatthias Ringwald             return true;
421540c5d850SMatthias Ringwald         default:
42166777d8fdSMatthias Ringwald             return false;
421740c5d850SMatthias Ringwald     }
421840c5d850SMatthias Ringwald }
421940c5d850SMatthias Ringwald 
422031c09488SMatthias Ringwald #endif
4221688a08f9SMatthias Ringwald 
42223deb3ec6SMatthias Ringwald /**
42233deb3ec6SMatthias Ringwald  * @return ok
42243deb3ec6SMatthias Ringwald  */
42253deb3ec6SMatthias Ringwald static int sm_validate_stk_generation_method(void){
42263deb3ec6SMatthias Ringwald     // check if STK generation method is acceptable by client
42273deb3ec6SMatthias Ringwald     switch (setup->sm_stk_generation_method){
42283deb3ec6SMatthias Ringwald         case JUST_WORKS:
42294ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_JUST_WORKS) != 0u;
42303deb3ec6SMatthias Ringwald         case PK_RESP_INPUT:
42313deb3ec6SMatthias Ringwald         case PK_INIT_INPUT:
423247fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
42334ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_PASSKEY) != 0u;
42343deb3ec6SMatthias Ringwald         case OOB:
42354ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_OOB) != 0u;
423647fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
42374ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON) != 0u;
42383deb3ec6SMatthias Ringwald         default:
42393deb3ec6SMatthias Ringwald             return 0;
42403deb3ec6SMatthias Ringwald     }
42413deb3ec6SMatthias Ringwald }
42423deb3ec6SMatthias Ringwald 
424336f0defaSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
424436f0defaSMatthias Ringwald static void sm_initiator_connected_handle_security_request(sm_connection_t * sm_conn, const uint8_t *packet){
424536f0defaSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
424636f0defaSMatthias Ringwald     if (sm_sc_only_mode){
424736f0defaSMatthias Ringwald         uint8_t auth_req = packet[1];
424836f0defaSMatthias Ringwald         if ((auth_req & SM_AUTHREQ_SECURE_CONNECTION) == 0){
424936f0defaSMatthias Ringwald             sm_pairing_error(sm_conn, SM_REASON_AUTHENTHICATION_REQUIREMENTS);
425036f0defaSMatthias Ringwald             return;
425136f0defaSMatthias Ringwald         }
425236f0defaSMatthias Ringwald     }
425336f0defaSMatthias Ringwald #else
425436f0defaSMatthias Ringwald     UNUSED(packet);
425536f0defaSMatthias Ringwald #endif
425636f0defaSMatthias Ringwald 
425736f0defaSMatthias Ringwald     int have_ltk;
425836f0defaSMatthias Ringwald     uint8_t ltk[16];
425936f0defaSMatthias Ringwald 
426036f0defaSMatthias Ringwald     // IRK complete?
426136f0defaSMatthias Ringwald     switch (sm_conn->sm_irk_lookup_state){
426236f0defaSMatthias Ringwald         case IRK_LOOKUP_FAILED:
426336f0defaSMatthias Ringwald             // start pairing
426436f0defaSMatthias Ringwald             sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
426536f0defaSMatthias Ringwald             break;
426636f0defaSMatthias Ringwald         case IRK_LOOKUP_SUCCEEDED:
426736f0defaSMatthias Ringwald             le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
426836f0defaSMatthias Ringwald             have_ltk = !sm_is_null_key(ltk);
426936f0defaSMatthias Ringwald             log_info("central: security request - have_ltk %u, encryption %u", have_ltk, sm_conn->sm_connection_encrypted);
427036f0defaSMatthias Ringwald             if (have_ltk && (sm_conn->sm_connection_encrypted == 0)){
427136f0defaSMatthias Ringwald                 // start re-encrypt if we have LTK and the connection is not already encrypted
427236f0defaSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
427336f0defaSMatthias Ringwald             } else {
427436f0defaSMatthias Ringwald                 // start pairing
427536f0defaSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
427636f0defaSMatthias Ringwald             }
427736f0defaSMatthias Ringwald             break;
427836f0defaSMatthias Ringwald         default:
427936f0defaSMatthias Ringwald             // otherwise, store security request
428036f0defaSMatthias Ringwald             sm_conn->sm_security_request_received = 1;
428136f0defaSMatthias Ringwald             break;
428236f0defaSMatthias Ringwald     }
428336f0defaSMatthias Ringwald }
428436f0defaSMatthias Ringwald #endif
428536f0defaSMatthias Ringwald 
4286f9bda154SMatthias Ringwald static uint8_t sm_pdu_validate_and_get_opcode(uint8_t packet_type, const uint8_t *packet, uint16_t size){
42878334d3d8SMatthias Ringwald 
42884c1d1092SMatthias Ringwald     // size of complete sm_pdu used to validate input
42894c1d1092SMatthias Ringwald     static const uint8_t sm_pdu_size[] = {
42904c1d1092SMatthias Ringwald             0,  // 0x00 invalid opcode
42914c1d1092SMatthias Ringwald             7,  // 0x01 pairing request
42924c1d1092SMatthias Ringwald             7,  // 0x02 pairing response
42934c1d1092SMatthias Ringwald             17, // 0x03 pairing confirm
42944c1d1092SMatthias Ringwald             17, // 0x04 pairing random
42954c1d1092SMatthias Ringwald             2,  // 0x05 pairing failed
42964c1d1092SMatthias Ringwald             17, // 0x06 encryption information
42977a2e6387SMatthias Ringwald             11, // 0x07 master identification
42984c1d1092SMatthias Ringwald             17, // 0x08 identification information
42994c1d1092SMatthias Ringwald             8,  // 0x09 identify address information
43004c1d1092SMatthias Ringwald             17, // 0x0a signing information
43014c1d1092SMatthias Ringwald             2,  // 0x0b security request
43024c1d1092SMatthias Ringwald             65, // 0x0c pairing public key
43034c1d1092SMatthias Ringwald             17, // 0x0d pairing dhk check
43044c1d1092SMatthias Ringwald             2,  // 0x0e keypress notification
43054c1d1092SMatthias Ringwald     };
43063deb3ec6SMatthias Ringwald 
4307f9bda154SMatthias Ringwald     if (packet_type != SM_DATA_PACKET) return 0;
4308f9bda154SMatthias Ringwald     if (size == 0u) return 0;
43094c1d1092SMatthias Ringwald 
43104c1d1092SMatthias Ringwald     uint8_t sm_pdu_code = packet[0];
43114c1d1092SMatthias Ringwald 
43124c1d1092SMatthias Ringwald     // validate pdu size
4313f9bda154SMatthias Ringwald     if (sm_pdu_code >= sizeof(sm_pdu_size)) return 0;
4314f9bda154SMatthias Ringwald     if (sm_pdu_size[sm_pdu_code] != size)   return 0;
4315f9bda154SMatthias Ringwald 
4316f9bda154SMatthias Ringwald     return sm_pdu_code;
4317f9bda154SMatthias Ringwald }
4318f9bda154SMatthias Ringwald 
4319f9bda154SMatthias Ringwald static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uint8_t *packet, uint16_t size){
4320f9bda154SMatthias Ringwald 
4321f9bda154SMatthias Ringwald     if ((packet_type == HCI_EVENT_PACKET) && (packet[0] == L2CAP_EVENT_CAN_SEND_NOW)){
4322f9bda154SMatthias Ringwald         sm_run();
4323f9bda154SMatthias Ringwald     }
4324f9bda154SMatthias Ringwald 
4325f9bda154SMatthias Ringwald     uint8_t sm_pdu_code = sm_pdu_validate_and_get_opcode(packet_type, packet, size);
4326f9bda154SMatthias Ringwald     if (sm_pdu_code == 0) return;
43273deb3ec6SMatthias Ringwald 
4328711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
43293deb3ec6SMatthias Ringwald     if (!sm_conn) return;
43303deb3ec6SMatthias Ringwald 
43314c1d1092SMatthias Ringwald     if (sm_pdu_code == SM_CODE_PAIRING_FAILED){
433268a18fb9SMatthias Ringwald         sm_reencryption_complete(sm_conn, ERROR_CODE_AUTHENTICATION_FAILURE);
43330ccf6c9cSMatthias Ringwald         sm_pairing_complete(sm_conn, ERROR_CODE_AUTHENTICATION_FAILURE, packet[1]);
4334accbde80SMatthias Ringwald         sm_done_for_handle(con_handle);
43353deb3ec6SMatthias Ringwald         sm_conn->sm_engine_state = sm_conn->sm_role ? SM_RESPONDER_IDLE : SM_INITIATOR_CONNECTED;
43363deb3ec6SMatthias Ringwald         return;
43373deb3ec6SMatthias Ringwald     }
43383deb3ec6SMatthias Ringwald 
43394c1d1092SMatthias Ringwald     log_debug("sm_pdu_handler: state %u, pdu 0x%02x", sm_conn->sm_engine_state, sm_pdu_code);
43403deb3ec6SMatthias Ringwald 
43413deb3ec6SMatthias Ringwald     int err;
434242134bc6SMatthias Ringwald     UNUSED(err);
43433deb3ec6SMatthias Ringwald 
43444c1d1092SMatthias Ringwald     if (sm_pdu_code == SM_CODE_KEYPRESS_NOTIFICATION){
43453d7fe1e9SMatthias Ringwald         uint8_t buffer[5];
43463d7fe1e9SMatthias Ringwald         buffer[0] = SM_EVENT_KEYPRESS_NOTIFICATION;
43473d7fe1e9SMatthias Ringwald         buffer[1] = 3;
43483d7fe1e9SMatthias Ringwald         little_endian_store_16(buffer, 2, con_handle);
43493d7fe1e9SMatthias Ringwald         buffer[4] = packet[1];
43503d7fe1e9SMatthias Ringwald         sm_dispatch_event(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer));
43513d7fe1e9SMatthias Ringwald         return;
43523d7fe1e9SMatthias Ringwald     }
43533d7fe1e9SMatthias Ringwald 
43543deb3ec6SMatthias Ringwald     switch (sm_conn->sm_engine_state){
43553deb3ec6SMatthias Ringwald 
4356c8d0ff33SMatthias Ringwald         // a sm timeout requires a new physical connection
43573deb3ec6SMatthias Ringwald         case SM_GENERAL_TIMEOUT:
43583deb3ec6SMatthias Ringwald             return;
43593deb3ec6SMatthias Ringwald 
436042134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
436142134bc6SMatthias Ringwald 
43623deb3ec6SMatthias Ringwald         // Initiator
43633deb3ec6SMatthias Ringwald         case SM_INITIATOR_CONNECTED:
43644c1d1092SMatthias Ringwald             if ((sm_pdu_code != SM_CODE_SECURITY_REQUEST) || (sm_conn->sm_role)){
43653deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
43663deb3ec6SMatthias Ringwald                 break;
43673deb3ec6SMatthias Ringwald             }
436836f0defaSMatthias Ringwald             sm_initiator_connected_handle_security_request(sm_conn, packet);
4369dc8ca372SMatthias Ringwald             break;
43703deb3ec6SMatthias Ringwald 
43713deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH1_W4_PAIRING_RESPONSE:
4372aacfafc3SMatthias Ringwald             // Core 5, Vol 3, Part H, 2.4.6:
4373aacfafc3SMatthias Ringwald             // "The master shall ignore the slave’s Security Request if the master has sent a Pairing Request
4374aacfafc3SMatthias Ringwald             //  without receiving a Pairing Response from the slave or if the master has initiated encryption mode setup."
4375aacfafc3SMatthias Ringwald             if (sm_pdu_code == SM_CODE_SECURITY_REQUEST){
4376aacfafc3SMatthias Ringwald                 log_info("Ignoring Security Request");
4377aacfafc3SMatthias Ringwald                 break;
4378aacfafc3SMatthias Ringwald             }
4379aacfafc3SMatthias Ringwald 
4380aacfafc3SMatthias Ringwald             // all other pdus are incorrect
43814c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RESPONSE){
43823deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
43833deb3ec6SMatthias Ringwald                 break;
43843deb3ec6SMatthias Ringwald             }
43850af429c6SMatthias Ringwald 
43863deb3ec6SMatthias Ringwald             // store pairing request
43876535961aSMatthias Ringwald             (void)memcpy(&setup->sm_s_pres, packet,
43886535961aSMatthias Ringwald                          sizeof(sm_pairing_packet_t));
43893deb3ec6SMatthias Ringwald             err = sm_stk_generation_init(sm_conn);
43900af429c6SMatthias Ringwald 
43910af429c6SMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
43920af429c6SMatthias Ringwald             if (0 < test_pairing_failure && test_pairing_failure < SM_REASON_DHKEY_CHECK_FAILED){
43930af429c6SMatthias Ringwald                 log_info("testing_support: abort with pairing failure %u", test_pairing_failure);
43940af429c6SMatthias Ringwald                 err = test_pairing_failure;
43950af429c6SMatthias Ringwald             }
43960af429c6SMatthias Ringwald #endif
43970af429c6SMatthias Ringwald 
43989305033eSMatthias Ringwald             if (err != 0){
4399f4935286SMatthias Ringwald                 sm_pairing_error(sm_conn, err);
44003deb3ec6SMatthias Ringwald                 break;
44013deb3ec6SMatthias Ringwald             }
4402b41539d5SMatthias Ringwald 
4403b41539d5SMatthias Ringwald             // generate random number first, if we need to show passkey
4404b41539d5SMatthias Ringwald             if (setup->sm_stk_generation_method == PK_RESP_INPUT){
4405f3582630SMatthias 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);
4406b41539d5SMatthias Ringwald                 break;
4407b41539d5SMatthias Ringwald             }
4408b41539d5SMatthias Ringwald 
4409136d331aSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4410136d331aSMatthias Ringwald             if (setup->sm_use_secure_connections){
44118cba5ca3SMatthias Ringwald                 // SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
44128cba5ca3SMatthias Ringwald                 if (setup->sm_stk_generation_method == JUST_WORKS){
4413136d331aSMatthias Ringwald                     sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
4414136d331aSMatthias Ringwald                     sm_trigger_user_response(sm_conn);
4415136d331aSMatthias Ringwald                     if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
4416c6b7cbd9SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
4417136d331aSMatthias Ringwald                     }
44188cba5ca3SMatthias Ringwald                 } else {
4419c6b7cbd9SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
44208cba5ca3SMatthias Ringwald                 }
4421136d331aSMatthias Ringwald                 break;
4422136d331aSMatthias Ringwald             }
4423136d331aSMatthias Ringwald #endif
44243deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
44253deb3ec6SMatthias Ringwald             sm_trigger_user_response(sm_conn);
44263deb3ec6SMatthias Ringwald             // response_idle == nothing <--> sm_trigger_user_response() did not require response
44273deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
4428f3582630SMatthias 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);
44293deb3ec6SMatthias Ringwald             }
44303deb3ec6SMatthias Ringwald             break;
44313deb3ec6SMatthias Ringwald 
44323deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH2_W4_PAIRING_CONFIRM:
44334c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
44343deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44353deb3ec6SMatthias Ringwald                 break;
44363deb3ec6SMatthias Ringwald             }
44373deb3ec6SMatthias Ringwald 
44383deb3ec6SMatthias Ringwald             // store s_confirm
44399c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
4440192365feSMatthias Ringwald 
4441aa9b34e5SMatthias Ringwald             // abort if s_confirm matches m_confirm
4442aa9b34e5SMatthias Ringwald             if (memcmp(setup->sm_local_confirm, setup->sm_peer_confirm, 16) == 0){
4443aa9b34e5SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4444aa9b34e5SMatthias Ringwald                 break;
4445aa9b34e5SMatthias Ringwald             }
4446aa9b34e5SMatthias Ringwald 
4447192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4448192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4449192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4450192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4451192365feSMatthias Ringwald             }
4452192365feSMatthias Ringwald #endif
44533deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
44543deb3ec6SMatthias Ringwald             break;
44553deb3ec6SMatthias Ringwald 
44563deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH2_W4_PAIRING_RANDOM:
44574c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
44583deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44593deb3ec6SMatthias Ringwald                 break;;
44603deb3ec6SMatthias Ringwald             }
44613deb3ec6SMatthias Ringwald 
44623deb3ec6SMatthias Ringwald             // received random value
44639c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_random);
44643deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
44653deb3ec6SMatthias Ringwald             break;
4466dc542de1SMatthias Ringwald 
4467dc542de1SMatthias Ringwald         case SM_PH4_W4_CONNECTION_ENCRYPTED:
4468dc542de1SMatthias Ringwald             // ignore Security Request, see SM_INITIATOR_PH1_W4_PAIRING_RESPONSE above
4469dc542de1SMatthias Ringwald             if (sm_pdu_code != SM_CODE_SECURITY_REQUEST){
4470dc542de1SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4471dc542de1SMatthias Ringwald             }
4472dc542de1SMatthias Ringwald             break;
447342134bc6SMatthias Ringwald #endif
44743deb3ec6SMatthias Ringwald 
447542134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
44763deb3ec6SMatthias Ringwald         // Responder
44773deb3ec6SMatthias Ringwald         case SM_RESPONDER_IDLE:
44783deb3ec6SMatthias Ringwald         case SM_RESPONDER_SEND_SECURITY_REQUEST:
44793deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
44804c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
44813deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44823deb3ec6SMatthias Ringwald                 break;;
44833deb3ec6SMatthias Ringwald             }
44843deb3ec6SMatthias Ringwald 
44853deb3ec6SMatthias Ringwald             // store pairing request
4486212d735eSMatthias Ringwald             (void)memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
4487212d735eSMatthias Ringwald 
4488212d735eSMatthias Ringwald             // check if IRK completed
4489212d735eSMatthias Ringwald             switch (sm_conn->sm_irk_lookup_state){
4490212d735eSMatthias Ringwald                 case IRK_LOOKUP_SUCCEEDED:
4491212d735eSMatthias Ringwald                 case IRK_LOOKUP_FAILED:
44923deb3ec6SMatthias Ringwald                     sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
44933deb3ec6SMatthias Ringwald                     break;
4494212d735eSMatthias Ringwald                 default:
4495212d735eSMatthias Ringwald                     sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK;
4496212d735eSMatthias Ringwald                     break;
4497212d735eSMatthias Ringwald             }
4498212d735eSMatthias Ringwald             break;
449942134bc6SMatthias Ringwald #endif
45003deb3ec6SMatthias Ringwald 
450127c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4502c6b7cbd9SMatthias Ringwald         case SM_SC_W4_PUBLIC_KEY_COMMAND:
45034c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_PUBLIC_KEY){
450427c32905SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
450527c32905SMatthias Ringwald                 break;
450627c32905SMatthias Ringwald             }
4507bccf5e67SMatthias Ringwald 
4508e53be891SMatthias Ringwald             // store public key for DH Key calculation
4509fc5bff5fSMatthias Ringwald             reverse_256(&packet[01], &setup->sm_peer_q[0]);
4510fc5bff5fSMatthias Ringwald             reverse_256(&packet[33], &setup->sm_peer_q[32]);
4511bccf5e67SMatthias Ringwald 
451202658749SMatthias Ringwald             // CVE-2020-26558: abort pairing if remote uses the same public key
451302658749SMatthias Ringwald             if (memcmp(&setup->sm_peer_q, ec_q, 64) == 0){
451402658749SMatthias Ringwald                 log_info("Remote PK matches ours");
451502658749SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
451602658749SMatthias Ringwald                 break;
451702658749SMatthias Ringwald             }
451802658749SMatthias Ringwald 
4519d1a1f6a4SMatthias Ringwald             // validate public key
4520d1a1f6a4SMatthias Ringwald             err = btstack_crypto_ecc_p256_validate_public_key(setup->sm_peer_q);
45219305033eSMatthias Ringwald             if (err != 0){
452202658749SMatthias Ringwald                 log_info("sm: peer public key invalid %x", err);
4523349d0adbSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
4524bccf5e67SMatthias Ringwald                 break;
4525bccf5e67SMatthias Ringwald             }
4526891bb64aSMatthias Ringwald 
4527d1a1f6a4SMatthias Ringwald             // start calculating dhkey
4528f3582630SMatthias 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);
45293cf37b8cSMatthias Ringwald 
453065a9a04eSMatthias Ringwald 
453165a9a04eSMatthias Ringwald             log_info("public key received, generation method %u", setup->sm_stk_generation_method);
453242134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
4533136d331aSMatthias Ringwald                 // responder
4534c6b7cbd9SMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
4535136d331aSMatthias Ringwald             } else {
4536136d331aSMatthias Ringwald                 // initiator
4537a1e31e9cSMatthias Ringwald                 // stk generation method
4538a1e31e9cSMatthias Ringwald                 // passkey entry: notify app to show passkey or to request passkey
4539a1e31e9cSMatthias Ringwald                 switch (setup->sm_stk_generation_method){
4540a1e31e9cSMatthias Ringwald                     case JUST_WORKS:
454147fb4255SMatthias Ringwald                     case NUMERIC_COMPARISON:
4542c6b7cbd9SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_W4_CONFIRMATION;
4543a1e31e9cSMatthias Ringwald                         break;
4544a1e31e9cSMatthias Ringwald                     case PK_RESP_INPUT:
454507036a04SMatthias Ringwald                         sm_sc_start_calculating_local_confirm(sm_conn);
454607036a04SMatthias Ringwald                         break;
454707036a04SMatthias Ringwald                     case PK_INIT_INPUT:
454847fb4255SMatthias Ringwald                     case PK_BOTH_INPUT:
454907036a04SMatthias Ringwald                         if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
455007036a04SMatthias Ringwald                             sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
455107036a04SMatthias Ringwald                             break;
455207036a04SMatthias Ringwald                         }
4553b35a3de2SMatthias Ringwald                         sm_sc_start_calculating_local_confirm(sm_conn);
4554a1e31e9cSMatthias Ringwald                         break;
4555a1e31e9cSMatthias Ringwald                     case OOB:
4556d1a1f6a4SMatthias Ringwald                         // generate Nx
45574acf7b7bSMatthias Ringwald                         log_info("Generate Na");
45586ca80073SMatthias 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);
4559a1e31e9cSMatthias Ringwald                         break;
45607bbeb3adSMilanka Ringwald                     default:
45617bbeb3adSMilanka Ringwald                         btstack_assert(false);
45627bbeb3adSMilanka Ringwald                         break;
4563a1e31e9cSMatthias Ringwald                 }
4564136d331aSMatthias Ringwald             }
456527c32905SMatthias Ringwald             break;
4566e53be891SMatthias Ringwald 
4567c6b7cbd9SMatthias Ringwald         case SM_SC_W4_CONFIRMATION:
45684c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
456945a61d50SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
457045a61d50SMatthias Ringwald                 break;
457145a61d50SMatthias Ringwald             }
457245a61d50SMatthias Ringwald             // received confirm value
457345a61d50SMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
457445a61d50SMatthias Ringwald 
4575192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4576192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4577192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4578192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4579192365feSMatthias Ringwald             }
4580192365feSMatthias Ringwald #endif
458142134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
458245a61d50SMatthias Ringwald                 // responder
458307036a04SMatthias Ringwald                 if (sm_passkey_used(setup->sm_stk_generation_method)){
458407036a04SMatthias Ringwald                     if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
458507036a04SMatthias Ringwald                         // still waiting for passkey
458607036a04SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
458707036a04SMatthias Ringwald                         break;
458807036a04SMatthias Ringwald                     }
458907036a04SMatthias Ringwald                 }
4590b35a3de2SMatthias Ringwald                 sm_sc_start_calculating_local_confirm(sm_conn);
459145a61d50SMatthias Ringwald             } else {
459245a61d50SMatthias Ringwald                 // initiator
4593945888f5SMatthias Ringwald                 if (sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method)){
45946ca80073SMatthias 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);
4595f1c1783eSMatthias Ringwald                 } else {
4596c6b7cbd9SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
459745a61d50SMatthias Ringwald                 }
4598f1c1783eSMatthias Ringwald             }
459945a61d50SMatthias Ringwald             break;
460045a61d50SMatthias Ringwald 
4601c6b7cbd9SMatthias Ringwald         case SM_SC_W4_PAIRING_RANDOM:
46024c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
4603e53be891SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4604136d331aSMatthias Ringwald                 break;
4605e53be891SMatthias Ringwald             }
4606e53be891SMatthias Ringwald 
4607e53be891SMatthias Ringwald             // received random value
4608e53be891SMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_nonce);
4609e53be891SMatthias Ringwald 
46105a293e6eSMatthias Ringwald             // validate confirm value if Cb = f4(Pkb, Pka, Nb, z)
4611ae451ec5SMatthias Ringwald             // only check for JUST WORK/NC in initiator role OR passkey entry
4612d686b2d0SMatthias Ringwald             log_info("SM_SC_W4_PAIRING_RANDOM, responder: %u, just works: %u, passkey used %u, passkey entry %u",
4613d686b2d0SMatthias Ringwald                      IS_RESPONDER(sm_conn->sm_role), sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method),
4614d686b2d0SMatthias Ringwald                      sm_passkey_used(setup->sm_stk_generation_method), sm_passkey_entry(setup->sm_stk_generation_method));
461565a9a04eSMatthias Ringwald             if ( (!IS_RESPONDER(sm_conn->sm_role) && sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method))
4616d686b2d0SMatthias Ringwald             ||   (sm_passkey_entry(setup->sm_stk_generation_method)) ) {
4617688a08f9SMatthias Ringwald                  sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
4618ae451ec5SMatthias Ringwald                  break;
46195a293e6eSMatthias Ringwald             }
46206f52a196SMatthias Ringwald 
46214acf7b7bSMatthias Ringwald             // OOB
46224acf7b7bSMatthias Ringwald             if (setup->sm_stk_generation_method == OOB){
46234acf7b7bSMatthias Ringwald 
46244acf7b7bSMatthias Ringwald                 // setup local random, set to zero if remote did not receive our data
46254acf7b7bSMatthias Ringwald                 log_info("Received nonce, setup local random ra/rb for dhkey check");
46264acf7b7bSMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
46274ea43905SMatthias Ringwald                     if (sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq) == 0u){
46284acf7b7bSMatthias Ringwald                         log_info("Reset rb as A does not have OOB data");
46294acf7b7bSMatthias Ringwald                         memset(setup->sm_rb, 0, 16);
46304acf7b7bSMatthias Ringwald                     } else {
46316535961aSMatthias Ringwald                         (void)memcpy(setup->sm_rb, sm_sc_oob_random, 16);
46324acf7b7bSMatthias Ringwald                         log_info("Use stored rb");
46334acf7b7bSMatthias Ringwald                         log_info_hexdump(setup->sm_rb, 16);
46344acf7b7bSMatthias Ringwald                     }
46354acf7b7bSMatthias Ringwald                 }  else {
46364ea43905SMatthias Ringwald                     if (sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres) == 0u){
46374acf7b7bSMatthias Ringwald                         log_info("Reset ra as B does not have OOB data");
46384acf7b7bSMatthias Ringwald                         memset(setup->sm_ra, 0, 16);
46394acf7b7bSMatthias Ringwald                     } else {
46406535961aSMatthias Ringwald                         (void)memcpy(setup->sm_ra, sm_sc_oob_random, 16);
46414acf7b7bSMatthias Ringwald                         log_info("Use stored ra");
46424acf7b7bSMatthias Ringwald                         log_info_hexdump(setup->sm_ra, 16);
46434acf7b7bSMatthias Ringwald                     }
46444acf7b7bSMatthias Ringwald                 }
46454acf7b7bSMatthias Ringwald 
4646a680ba6bSMatthias Ringwald                 // validate confirm value if Cb = f4(PKb, Pkb, rb, 0) for OOB if data received
46474acf7b7bSMatthias Ringwald                 if (setup->sm_have_oob_data){
4648a680ba6bSMatthias Ringwald                      sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
4649a680ba6bSMatthias Ringwald                      break;
4650a680ba6bSMatthias Ringwald                 }
46514acf7b7bSMatthias Ringwald             }
4652a680ba6bSMatthias Ringwald 
4653a680ba6bSMatthias Ringwald             // TODO: we only get here for Responder role with JW/NC
4654688a08f9SMatthias Ringwald             sm_sc_state_after_receiving_random(sm_conn);
4655e53be891SMatthias Ringwald             break;
4656e53be891SMatthias Ringwald 
4657901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_G2:
4658901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_G2:
46593cf37b8cSMatthias Ringwald         case SM_SC_W4_CALCULATE_DHKEY:
4660901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_SALT:
4661901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_SALT:
4662901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_MACKEY:
4663901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_MACKEY:
4664901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_LTK:
4665901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_LTK:
4666901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK:
4667c6b7cbd9SMatthias Ringwald         case SM_SC_W4_DHKEY_CHECK_COMMAND:
4668901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
4669d08147dfSMatthias Ringwald         case SM_SC_W4_USER_RESPONSE:
46704c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_DHKEY_CHECK){
4671e53be891SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4672e53be891SMatthias Ringwald                 break;
4673e53be891SMatthias Ringwald             }
4674e53be891SMatthias Ringwald             // store DHKey Check
4675901c000fSMatthias Ringwald             setup->sm_state_vars |= SM_STATE_VAR_DHKEY_COMMAND_RECEIVED;
4676e53be891SMatthias Ringwald             reverse_128(&packet[01], setup->sm_peer_dhkey_check);
4677446a8c36SMatthias Ringwald 
4678901c000fSMatthias Ringwald             // have we been only waiting for dhkey check command?
4679901c000fSMatthias Ringwald             if (sm_conn->sm_engine_state == SM_SC_W4_DHKEY_CHECK_COMMAND){
4680019005a0SMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
4681bd57ffebSMatthias Ringwald             }
4682bd57ffebSMatthias Ringwald             break;
468327c32905SMatthias Ringwald #endif
468427c32905SMatthias Ringwald 
468542134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
46863deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH1_W4_PAIRING_CONFIRM:
46874c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
46883deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
468927c32905SMatthias Ringwald                 break;
46903deb3ec6SMatthias Ringwald             }
46913deb3ec6SMatthias Ringwald 
46923deb3ec6SMatthias Ringwald             // received confirm value
46939c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
46943deb3ec6SMatthias Ringwald 
4695192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4696192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4697192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4698192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4699192365feSMatthias Ringwald             }
4700192365feSMatthias Ringwald #endif
47013deb3ec6SMatthias Ringwald             // notify client to hide shown passkey
47023deb3ec6SMatthias Ringwald             if (setup->sm_stk_generation_method == PK_INIT_INPUT){
47035611a760SMatthias 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);
47043deb3ec6SMatthias Ringwald             }
47053deb3ec6SMatthias Ringwald 
47063deb3ec6SMatthias Ringwald             // handle user cancel pairing?
47073deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_DECLINE){
4708f4935286SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_PASSKEY_ENTRY_FAILED);
47093deb3ec6SMatthias Ringwald                 break;
47103deb3ec6SMatthias Ringwald             }
47113deb3ec6SMatthias Ringwald 
47123deb3ec6SMatthias Ringwald             // wait for user action?
47133deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_PENDING){
47143deb3ec6SMatthias Ringwald                 sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
47153deb3ec6SMatthias Ringwald                 break;
47163deb3ec6SMatthias Ringwald             }
47173deb3ec6SMatthias Ringwald 
47183deb3ec6SMatthias Ringwald             // calculate and send local_confirm
4719f3582630SMatthias 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);
47203deb3ec6SMatthias Ringwald             break;
47213deb3ec6SMatthias Ringwald 
47223deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH2_W4_PAIRING_RANDOM:
47234c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
47243deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
47253deb3ec6SMatthias Ringwald                 break;;
47263deb3ec6SMatthias Ringwald             }
47273deb3ec6SMatthias Ringwald 
47283deb3ec6SMatthias Ringwald             // received random value
47299c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_random);
47303deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
47313deb3ec6SMatthias Ringwald             break;
473242134bc6SMatthias Ringwald #endif
47333deb3ec6SMatthias Ringwald 
4734672dc582SMatthias Ringwald         case SM_PH2_W4_CONNECTION_ENCRYPTED:
47353deb3ec6SMatthias Ringwald         case SM_PH3_RECEIVE_KEYS:
47364c1d1092SMatthias Ringwald             switch(sm_pdu_code){
47373deb3ec6SMatthias Ringwald                 case SM_CODE_ENCRYPTION_INFORMATION:
47383deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
47399c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_ltk);
47403deb3ec6SMatthias Ringwald                     break;
47413deb3ec6SMatthias Ringwald 
47423deb3ec6SMatthias Ringwald                 case SM_CODE_MASTER_IDENTIFICATION:
47433deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
4744f8fbdce0SMatthias Ringwald                     setup->sm_peer_ediv = little_endian_read_16(packet, 1);
47459c80e4ccSMatthias Ringwald                     reverse_64(&packet[3], setup->sm_peer_rand);
47463deb3ec6SMatthias Ringwald                     break;
47473deb3ec6SMatthias Ringwald 
47483deb3ec6SMatthias Ringwald                 case SM_CODE_IDENTITY_INFORMATION:
47493deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
47509c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_irk);
47513deb3ec6SMatthias Ringwald                     break;
47523deb3ec6SMatthias Ringwald 
47533deb3ec6SMatthias Ringwald                 case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
47543deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
47553deb3ec6SMatthias Ringwald                     setup->sm_peer_addr_type = packet[1];
4756724d70a2SMatthias Ringwald                     reverse_bd_addr(&packet[2], setup->sm_peer_address);
47573deb3ec6SMatthias Ringwald                     break;
47583deb3ec6SMatthias Ringwald 
47593deb3ec6SMatthias Ringwald                 case SM_CODE_SIGNING_INFORMATION:
47603deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
47619c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_csrk);
47623deb3ec6SMatthias Ringwald                     break;
47633deb3ec6SMatthias Ringwald                 default:
47643deb3ec6SMatthias Ringwald                     // Unexpected PDU
47653deb3ec6SMatthias Ringwald                     log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
47663deb3ec6SMatthias Ringwald                     break;
47673deb3ec6SMatthias Ringwald             }
47683deb3ec6SMatthias Ringwald             // done with key distribution?
476961d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
47703deb3ec6SMatthias Ringwald 
47713deb3ec6SMatthias Ringwald                 sm_key_distribution_handle_all_received(sm_conn);
47723deb3ec6SMatthias Ringwald 
477342134bc6SMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
47746f7422f1SMatthias Ringwald                     sm_key_distribution_complete_responder(sm_conn);
47753deb3ec6SMatthias Ringwald                 } else {
4776625f00b2SMatthias Ringwald                     if (setup->sm_use_secure_connections){
4777625f00b2SMatthias Ringwald                         sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
4778bbf8db22SMatthias Ringwald                     } else {
4779f3582630SMatthias 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);
4780625f00b2SMatthias Ringwald                     }
47813deb3ec6SMatthias Ringwald                 }
47823deb3ec6SMatthias Ringwald             }
47833deb3ec6SMatthias Ringwald             break;
4784c18be159SMatthias Ringwald 
4785c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4786b322498eSMatthias Ringwald 
4787b322498eSMatthias Ringwald         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
4788b322498eSMatthias Ringwald             // GAP/DM/LEP/BI-02-C - reject CTKD if P-192 encryption is used
4789b322498eSMatthias Ringwald             if (sm_pdu_code == SM_CODE_PAIRING_REQUEST){
4790b322498eSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED);
4791b322498eSMatthias Ringwald             }
4792b322498eSMatthias Ringwald             break;
4793b322498eSMatthias Ringwald 
4794c18be159SMatthias Ringwald         case SM_BR_EDR_INITIATOR_W4_PAIRING_RESPONSE:
4795553c9408SMatthias Ringwald 
4796553c9408SMatthias Ringwald             // dedicated bonding complete
4797f82b8f4bSMatthias Ringwald             hci_dedicated_bonding_defer_disconnect(sm_conn->sm_handle, false);
4798553c9408SMatthias Ringwald 
4799c18be159SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RESPONSE){
4800c18be159SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4801c18be159SMatthias Ringwald                 break;
4802c18be159SMatthias Ringwald             }
4803c18be159SMatthias Ringwald             // store pairing response
4804c18be159SMatthias Ringwald             (void)memcpy(&setup->sm_s_pres, packet, sizeof(sm_pairing_packet_t));
4805c18be159SMatthias Ringwald 
4806c18be159SMatthias Ringwald             // validate encryption key size
4807c18be159SMatthias Ringwald             sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(sm_pairing_packet_get_max_encryption_key_size(setup->sm_s_pres));
4808c18be159SMatthias Ringwald             // SC Only mandates 128 bit key size
4809c18be159SMatthias Ringwald             if (sm_sc_only_mode && (sm_conn->sm_actual_encryption_key_size < 16)) {
4810c18be159SMatthias Ringwald                 sm_conn->sm_actual_encryption_key_size  = 0;
4811c18be159SMatthias Ringwald             }
4812c18be159SMatthias Ringwald             if (sm_conn->sm_actual_encryption_key_size == 0){
4813c18be159SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_ENCRYPTION_KEY_SIZE);
4814c18be159SMatthias Ringwald                 break;
4815c18be159SMatthias Ringwald             }
4816c18be159SMatthias Ringwald 
4817c18be159SMatthias Ringwald             // prepare key exchange, LTK is derived locally
4818c18be159SMatthias Ringwald             sm_setup_key_distribution(sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres) & ~SM_KEYDIST_ENC_KEY,
4819c18be159SMatthias Ringwald                                       sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres) & ~SM_KEYDIST_ENC_KEY);
4820c18be159SMatthias Ringwald 
4821c18be159SMatthias Ringwald             // skip receive if there are none
482261d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
4823c18be159SMatthias Ringwald                 // distribute keys in run handles 'no keys to send'
4824c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
4825c18be159SMatthias Ringwald             } else {
4826c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_RECEIVE_KEYS;
4827c18be159SMatthias Ringwald             }
4828c18be159SMatthias Ringwald             break;
4829c18be159SMatthias Ringwald 
4830c18be159SMatthias Ringwald         case SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST:
4831c18be159SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
4832c18be159SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4833c18be159SMatthias Ringwald                 break;
4834c18be159SMatthias Ringwald             }
4835c18be159SMatthias Ringwald             // store pairing request
4836c18be159SMatthias Ringwald             (void)memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
4837c18be159SMatthias Ringwald             // validate encryption key size
4838c18be159SMatthias Ringwald             sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(sm_pairing_packet_get_max_encryption_key_size(sm_conn->sm_m_preq));
4839c18be159SMatthias Ringwald             // SC Only mandates 128 bit key size
4840c18be159SMatthias Ringwald             if (sm_sc_only_mode && (sm_conn->sm_actual_encryption_key_size < 16)) {
4841c18be159SMatthias Ringwald                 sm_conn->sm_actual_encryption_key_size  = 0;
4842c18be159SMatthias Ringwald             }
4843c18be159SMatthias Ringwald             if (sm_conn->sm_actual_encryption_key_size == 0){
4844c18be159SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_ENCRYPTION_KEY_SIZE);
4845c18be159SMatthias Ringwald                 break;
4846c18be159SMatthias Ringwald             }
4847c18be159SMatthias Ringwald             // trigger response
48486a718a5eSMatthias Ringwald             if (sm_ctkd_from_classic(sm_conn)){
4849c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED;
48506a718a5eSMatthias Ringwald             } else {
48516a718a5eSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED);
48526a718a5eSMatthias Ringwald             }
4853c18be159SMatthias Ringwald             break;
4854c18be159SMatthias Ringwald 
4855c18be159SMatthias Ringwald         case SM_BR_EDR_RECEIVE_KEYS:
4856c18be159SMatthias Ringwald             switch(sm_pdu_code){
4857c18be159SMatthias Ringwald                 case SM_CODE_IDENTITY_INFORMATION:
4858c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
4859c18be159SMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_irk);
4860c18be159SMatthias Ringwald                     break;
4861c18be159SMatthias Ringwald                 case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
4862c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
4863c18be159SMatthias Ringwald                     setup->sm_peer_addr_type = packet[1];
4864c18be159SMatthias Ringwald                     reverse_bd_addr(&packet[2], setup->sm_peer_address);
4865c18be159SMatthias Ringwald                     break;
4866c18be159SMatthias Ringwald                 case SM_CODE_SIGNING_INFORMATION:
4867c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
4868c18be159SMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_csrk);
4869c18be159SMatthias Ringwald                     break;
4870c18be159SMatthias Ringwald                 default:
4871c18be159SMatthias Ringwald                     // Unexpected PDU
4872c18be159SMatthias Ringwald                     log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
4873c18be159SMatthias Ringwald                     break;
4874c18be159SMatthias Ringwald             }
4875c18be159SMatthias Ringwald 
4876c18be159SMatthias Ringwald             // all keys received
487761d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
4878c18be159SMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
4879c18be159SMatthias Ringwald                     // responder -> keys exchanged, derive LE LTK
4880c18be159SMatthias Ringwald                     sm_ctkd_start_from_br_edr(sm_conn);
4881c18be159SMatthias Ringwald                 } else {
4882c18be159SMatthias Ringwald                     // initiator -> send our keys if any
4883c18be159SMatthias Ringwald                     sm_conn->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
4884c18be159SMatthias Ringwald                 }
4885c18be159SMatthias Ringwald             }
4886c18be159SMatthias Ringwald             break;
4887c18be159SMatthias Ringwald #endif
4888c18be159SMatthias Ringwald 
48893deb3ec6SMatthias Ringwald         default:
48903deb3ec6SMatthias Ringwald             // Unexpected PDU
48913deb3ec6SMatthias Ringwald             log_info("Unexpected PDU %u in state %u", packet[0], sm_conn->sm_engine_state);
48922d095694SMatthias Ringwald             sm_pdu_received_in_wrong_state(sm_conn);
48933deb3ec6SMatthias Ringwald             break;
48943deb3ec6SMatthias Ringwald     }
48953deb3ec6SMatthias Ringwald 
489670b44dd4SMatthias Ringwald     // try to send next pdu
489770b44dd4SMatthias Ringwald     sm_trigger_run();
48983deb3ec6SMatthias Ringwald }
48993deb3ec6SMatthias Ringwald 
49003deb3ec6SMatthias Ringwald // Security Manager Client API
4901a680ba6bSMatthias Ringwald void sm_register_oob_data_callback( int (*get_oob_data_callback)(uint8_t address_type, bd_addr_t addr, uint8_t * oob_data)){
49023deb3ec6SMatthias Ringwald     sm_get_oob_data = get_oob_data_callback;
49033deb3ec6SMatthias Ringwald }
49043deb3ec6SMatthias Ringwald 
49054acf7b7bSMatthias 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)){
4906a680ba6bSMatthias Ringwald     sm_get_sc_oob_data = get_sc_oob_data_callback;
4907a680ba6bSMatthias Ringwald }
4908a680ba6bSMatthias Ringwald 
4909b96d60a6SMatthias 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)){
4910b96d60a6SMatthias Ringwald     sm_get_ltk_callback = get_ltk_callback;
4911b96d60a6SMatthias Ringwald }
4912b96d60a6SMatthias Ringwald 
491389a78d34SMatthias Ringwald void sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler){
491489a78d34SMatthias Ringwald     btstack_linked_list_add_tail(&sm_event_handlers, (btstack_linked_item_t*) callback_handler);
491589a78d34SMatthias Ringwald }
491689a78d34SMatthias Ringwald 
491767f708e0SMatthias Ringwald void sm_remove_event_handler(btstack_packet_callback_registration_t * callback_handler){
491867f708e0SMatthias Ringwald     btstack_linked_list_remove(&sm_event_handlers, (btstack_linked_item_t*) callback_handler);
491967f708e0SMatthias Ringwald }
492067f708e0SMatthias Ringwald 
49213deb3ec6SMatthias Ringwald void sm_set_accepted_stk_generation_methods(uint8_t accepted_stk_generation_methods){
49223deb3ec6SMatthias Ringwald     sm_accepted_stk_generation_methods = accepted_stk_generation_methods;
49233deb3ec6SMatthias Ringwald }
49243deb3ec6SMatthias Ringwald 
49253deb3ec6SMatthias Ringwald void sm_set_encryption_key_size_range(uint8_t min_size, uint8_t max_size){
49263deb3ec6SMatthias Ringwald 	sm_min_encryption_key_size = min_size;
49273deb3ec6SMatthias Ringwald 	sm_max_encryption_key_size = max_size;
49283deb3ec6SMatthias Ringwald }
49293deb3ec6SMatthias Ringwald 
49303deb3ec6SMatthias Ringwald void sm_set_authentication_requirements(uint8_t auth_req){
493198d95509SMatthias Ringwald #ifndef ENABLE_LE_SECURE_CONNECTIONS
493298d95509SMatthias Ringwald     if (auth_req & SM_AUTHREQ_SECURE_CONNECTION){
493398d95509SMatthias Ringwald         log_error("ENABLE_LE_SECURE_CONNECTIONS not defined, but requested by app. Dropping SC flag");
493498d95509SMatthias Ringwald         auth_req &= ~SM_AUTHREQ_SECURE_CONNECTION;
493598d95509SMatthias Ringwald     }
493698d95509SMatthias Ringwald #endif
49373deb3ec6SMatthias Ringwald     sm_auth_req = auth_req;
49383deb3ec6SMatthias Ringwald }
49393deb3ec6SMatthias Ringwald 
49403deb3ec6SMatthias Ringwald void sm_set_io_capabilities(io_capability_t io_capability){
49413deb3ec6SMatthias Ringwald     sm_io_capabilities = io_capability;
49423deb3ec6SMatthias Ringwald }
49433deb3ec6SMatthias Ringwald 
494442134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
49453deb3ec6SMatthias Ringwald void sm_set_request_security(int enable){
49463deb3ec6SMatthias Ringwald     sm_slave_request_security = enable;
49473deb3ec6SMatthias Ringwald }
494842134bc6SMatthias Ringwald #endif
49493deb3ec6SMatthias Ringwald 
49503deb3ec6SMatthias Ringwald void sm_set_er(sm_key_t er){
49516535961aSMatthias Ringwald     (void)memcpy(sm_persistent_er, er, 16);
49523deb3ec6SMatthias Ringwald }
49533deb3ec6SMatthias Ringwald 
49543deb3ec6SMatthias Ringwald void sm_set_ir(sm_key_t ir){
49556535961aSMatthias Ringwald     (void)memcpy(sm_persistent_ir, ir, 16);
49563deb3ec6SMatthias Ringwald }
49573deb3ec6SMatthias Ringwald 
49583deb3ec6SMatthias Ringwald // Testing support only
49593deb3ec6SMatthias Ringwald void sm_test_set_irk(sm_key_t irk){
49606535961aSMatthias Ringwald     (void)memcpy(sm_persistent_irk, irk, 16);
4961103fa6b0SMatthias Ringwald     dkg_state = DKG_CALC_DHK;
4962841468bbSMatthias Ringwald     test_use_fixed_local_irk = true;
49633deb3ec6SMatthias Ringwald }
49643deb3ec6SMatthias Ringwald 
49653deb3ec6SMatthias Ringwald void sm_test_use_fixed_local_csrk(void){
4966841468bbSMatthias Ringwald     test_use_fixed_local_csrk = true;
49673deb3ec6SMatthias Ringwald }
49683deb3ec6SMatthias Ringwald 
4969d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4970d1a1f6a4SMatthias Ringwald static void sm_ec_generated(void * arg){
4971d1a1f6a4SMatthias Ringwald     UNUSED(arg);
4972d1a1f6a4SMatthias Ringwald     ec_key_generation_state = EC_KEY_GENERATION_DONE;
497334b6528fSMatthias Ringwald     // trigger pairing if pending for ec key
497470b44dd4SMatthias Ringwald     sm_trigger_run();
4975d1a1f6a4SMatthias Ringwald }
4976674e5b4aSMatthias Ringwald static void sm_ec_generate_new_key(void) {
497734b6528fSMatthias Ringwald     log_info("sm: generate new ec key");
4978db88441fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS_DEBUG_KEY
4979db88441fSMatthias Ringwald     // LE Secure Connections Debug Key
4980db88441fSMatthias Ringwald     const uint8_t debug_key_public[64] = {
4981db88441fSMatthias Ringwald         0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c, 0x5e, 0x2c, 0x83, 0xa7, 0xe9, 0xf9, 0xa5, 0xb9,
4982db88441fSMatthias Ringwald         0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb, 0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6,
4983db88441fSMatthias Ringwald         0xdc, 0x80, 0x9c, 0x49, 0x65, 0x2a, 0xeb, 0x6d, 0x63, 0x32, 0x9a, 0xbf, 0x5a, 0x52, 0x15, 0x5c,
4984db88441fSMatthias Ringwald         0x76, 0x63, 0x45, 0xc2, 0x8f, 0xed, 0x30, 0x24, 0x74, 0x1c, 0x8e, 0xd0, 0x15, 0x89, 0xd2, 0x8b
4985db88441fSMatthias Ringwald     };
4986db88441fSMatthias Ringwald     const uint8_t debug_key_private[32] = {
4987db88441fSMatthias Ringwald         0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3, 0xe3, 0xd2, 0x10, 0x3f, 0x50,
4988db88441fSMatthias Ringwald         0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99, 0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd
4989db88441fSMatthias Ringwald     };
4990db88441fSMatthias Ringwald     if (sm_sc_debug_keys_enabled) {
4991db88441fSMatthias Ringwald         memcpy(ec_q, debug_key_public, 64);
4992db88441fSMatthias Ringwald         btstack_crypto_ecc_p256_set_key(debug_key_public, debug_key_private);
4993db88441fSMatthias Ringwald         ec_key_generation_state = EC_KEY_GENERATION_DONE;
4994db88441fSMatthias Ringwald     } else
4995db88441fSMatthias Ringwald #endif
4996db88441fSMatthias Ringwald     {
4997674e5b4aSMatthias Ringwald         ec_key_generation_state = EC_KEY_GENERATION_ACTIVE;
4998674e5b4aSMatthias Ringwald         btstack_crypto_ecc_p256_generate_key(&sm_crypto_ecc_p256_request, ec_q, &sm_ec_generated, NULL);
4999674e5b4aSMatthias Ringwald     }
5000db88441fSMatthias Ringwald }
5001d1a1f6a4SMatthias Ringwald #endif
5002d1a1f6a4SMatthias Ringwald 
5003192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
5004192365feSMatthias Ringwald void sm_test_set_pairing_failure(int reason){
5005192365feSMatthias Ringwald     test_pairing_failure = reason;
5006192365feSMatthias Ringwald }
5007192365feSMatthias Ringwald #endif
5008192365feSMatthias Ringwald 
50097887cd92SMatthias Ringwald static void sm_state_reset(void) {
50107f775357SMatthias Ringwald #ifdef USE_CMAC_ENGINE
50117f775357SMatthias Ringwald     sm_cmac_active  = 0;
50127f775357SMatthias Ringwald #endif
50137f775357SMatthias Ringwald     dkg_state = DKG_W4_WORKING;
50147f775357SMatthias Ringwald     rau_state = RAU_IDLE;
50157f775357SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
50167f775357SMatthias Ringwald     sm_address_resolution_test = -1;    // no private address to resolve yet
50177f775357SMatthias Ringwald     sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
50187f775357SMatthias Ringwald     sm_address_resolution_general_queue = NULL;
50197f775357SMatthias Ringwald     sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
5020cbdd51cfSMatthias Ringwald     sm_persistent_keys_random_active = false;
50217f775357SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
502215211b85SMatthias Ringwald     ec_key_generation_state = EC_KEY_GENERATION_IDLE;
50237f775357SMatthias Ringwald #endif
50247f775357SMatthias Ringwald }
50257f775357SMatthias Ringwald 
50263deb3ec6SMatthias Ringwald void sm_init(void){
50272d2d4d3cSMatthias Ringwald 
50282d2d4d3cSMatthias Ringwald     if (sm_initialized) return;
50292d2d4d3cSMatthias Ringwald 
5030899e6e02SMatthias Ringwald     // set default ER and IR values (should be unique - set by app or sm later using TLV)
5031899e6e02SMatthias Ringwald     sm_er_ir_set_default();
5032899e6e02SMatthias Ringwald 
50333deb3ec6SMatthias Ringwald     // defaults
50343deb3ec6SMatthias Ringwald     sm_accepted_stk_generation_methods = SM_STK_GENERATION_METHOD_JUST_WORKS
50353deb3ec6SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_OOB
5036b4343428SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_PASSKEY
5037b4343428SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON;
5038b4343428SMatthias Ringwald 
50393deb3ec6SMatthias Ringwald     sm_max_encryption_key_size = 16;
50403deb3ec6SMatthias Ringwald     sm_min_encryption_key_size = 7;
50413deb3ec6SMatthias Ringwald 
50425ce1359eSMatthias Ringwald     sm_fixed_passkey_in_display_role = 0xffffffffU;
50431979f09cSMatthias Ringwald     sm_reconstruct_ltk_without_le_device_db_entry = true;
5044caf15bf3SMatthias Ringwald 
50453deb3ec6SMatthias Ringwald     gap_random_adress_update_period = 15 * 60 * 1000L;
50463deb3ec6SMatthias Ringwald 
5047841468bbSMatthias Ringwald     test_use_fixed_local_csrk = false;
50483deb3ec6SMatthias Ringwald 
50497f775357SMatthias Ringwald     // other
505084c0c5c7SMatthias Ringwald     btstack_run_loop_set_timer_handler(&sm_run_timer, &sm_run_timer_handler);
505184c0c5c7SMatthias Ringwald 
5052a036ae12SMatthias Ringwald     // register for HCI Events
5053e03e489aSMatthias Ringwald     hci_event_callback_registration.callback = &sm_event_packet_handler;
5054e03e489aSMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
5055e03e489aSMatthias Ringwald 
5056bad51150SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
5057a036ae12SMatthias Ringwald     // register for L2CAP events
5058a036ae12SMatthias Ringwald     l2cap_event_callback_registration.callback = &sm_event_packet_handler;
5059a036ae12SMatthias Ringwald     l2cap_add_event_handler(&l2cap_event_callback_registration);
5060bad51150SMatthias Ringwald #endif
5061a036ae12SMatthias Ringwald 
5062d1a1f6a4SMatthias Ringwald     //
5063d1a1f6a4SMatthias Ringwald     btstack_crypto_init();
5064d1a1f6a4SMatthias Ringwald 
506551bd74d1SMatthias Ringwald     // init le_device_db
506651bd74d1SMatthias Ringwald     le_device_db_init();
506751bd74d1SMatthias Ringwald 
5068b170b20fSMatthias Ringwald     // and L2CAP PDUs + L2CAP_EVENT_CAN_SEND_NOW
5069e03e489aSMatthias Ringwald     l2cap_register_fixed_channel(sm_pdu_handler, L2CAP_CID_SECURITY_MANAGER_PROTOCOL);
5070384eabd3SMatthias Ringwald #ifdef ENABLE_CLASSIC
5071384eabd3SMatthias Ringwald     l2cap_register_fixed_channel(sm_pdu_handler, L2CAP_CID_BR_EDR_SECURITY_MANAGER);
5072384eabd3SMatthias Ringwald #endif
507327c32905SMatthias Ringwald 
50747f775357SMatthias Ringwald     // state
50757f775357SMatthias Ringwald     sm_state_reset();
50762d2d4d3cSMatthias Ringwald 
50772d2d4d3cSMatthias Ringwald     sm_initialized = true;
50783deb3ec6SMatthias Ringwald }
50793deb3ec6SMatthias Ringwald 
508015537ea4SMatthias Ringwald void sm_deinit(void){
508115537ea4SMatthias Ringwald     sm_initialized = false;
508215537ea4SMatthias Ringwald     btstack_run_loop_remove_timer(&sm_run_timer);
508392f8d6b6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined (ENABLE_LE_SECURE_CONNECTION_DEBUG_KEY)
5084db88441fSMatthias Ringwald     sm_sc_debug_keys_enabled = false;
5085db88441fSMatthias Ringwald #endif
508615537ea4SMatthias Ringwald }
508715537ea4SMatthias Ringwald 
50884b8c611fSMatthias Ringwald void sm_use_fixed_passkey_in_display_role(uint32_t passkey){
50894b8c611fSMatthias Ringwald     sm_fixed_passkey_in_display_role = passkey;
5090caf15bf3SMatthias Ringwald }
5091caf15bf3SMatthias Ringwald 
50926c39055aSMatthias Ringwald void sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow){
50931979f09cSMatthias Ringwald     sm_reconstruct_ltk_without_le_device_db_entry = allow != 0;
50946c39055aSMatthias Ringwald }
50956c39055aSMatthias Ringwald 
5096711e6c80SMatthias Ringwald static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle){
5097711e6c80SMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(con_handle);
50983deb3ec6SMatthias Ringwald     if (!hci_con) return NULL;
50993deb3ec6SMatthias Ringwald     return &hci_con->sm_connection;
51003deb3ec6SMatthias Ringwald }
51013deb3ec6SMatthias Ringwald 
5102916ea5b2SMatthias Ringwald static void sm_cache_ltk(sm_connection_t * connection, const sm_key_t ltk){
5103916ea5b2SMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(connection->sm_handle);
5104916ea5b2SMatthias Ringwald     btstack_assert(hci_con != NULL);
5105916ea5b2SMatthias Ringwald     memcpy(hci_con->link_key, ltk, 16);
5106916ea5b2SMatthias Ringwald     hci_con->link_key_type = 1;
5107916ea5b2SMatthias Ringwald }
5108916ea5b2SMatthias Ringwald 
510977e2e5edSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
511077e2e5edSMatthias Ringwald static sm_connection_t * sm_get_connection_for_bd_addr_and_type(bd_addr_t address, bd_addr_type_t addr_type){
511177e2e5edSMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_bd_addr_and_type(address, addr_type);
511277e2e5edSMatthias Ringwald     if (!hci_con) return NULL;
511377e2e5edSMatthias Ringwald     return &hci_con->sm_connection;
511477e2e5edSMatthias Ringwald }
511577e2e5edSMatthias Ringwald #endif
511677e2e5edSMatthias Ringwald 
51176bc3aba4SMatthias Ringwald // @deprecated: map onto sm_request_pairing
5118711e6c80SMatthias Ringwald void sm_send_security_request(hci_con_handle_t con_handle){
5119711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
51203deb3ec6SMatthias Ringwald     if (!sm_conn) return;
51216bc3aba4SMatthias Ringwald     if (!IS_RESPONDER(sm_conn->sm_role)) return;
51226bc3aba4SMatthias Ringwald     sm_request_pairing(con_handle);
51233deb3ec6SMatthias Ringwald }
51243deb3ec6SMatthias Ringwald 
51253deb3ec6SMatthias Ringwald // request pairing
5126711e6c80SMatthias Ringwald void sm_request_pairing(hci_con_handle_t con_handle){
5127711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
51283deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
51293deb3ec6SMatthias Ringwald 
51307af5dcd5SMatthias Ringwald     bool have_ltk;
51317af5dcd5SMatthias Ringwald     uint8_t ltk[16];
51322d68601cSMatthias Ringwald     bool auth_required;
51332d68601cSMatthias Ringwald     int authenticated;
51342d68601cSMatthias Ringwald     bool trigger_reencryption;
51353deb3ec6SMatthias Ringwald     log_info("sm_request_pairing in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state);
513642134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
513724c20dc4SMatthias Ringwald         switch (sm_conn->sm_engine_state){
513824c20dc4SMatthias Ringwald             case SM_GENERAL_IDLE:
513924c20dc4SMatthias Ringwald             case SM_RESPONDER_IDLE:
51407af5dcd5SMatthias Ringwald                 switch (sm_conn->sm_irk_lookup_state){
51417af5dcd5SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
51427af5dcd5SMatthias Ringwald                         le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
51437af5dcd5SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
51447af5dcd5SMatthias Ringwald                         log_info("have ltk %u", have_ltk);
51457af5dcd5SMatthias Ringwald                         if (have_ltk){
51467af5dcd5SMatthias Ringwald                             sm_conn->sm_pairing_requested = 1;
514724c20dc4SMatthias Ringwald                             sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
51487af5dcd5SMatthias Ringwald                             sm_reencryption_started(sm_conn);
51497af5dcd5SMatthias Ringwald                             break;
51507af5dcd5SMatthias Ringwald                         }
51517af5dcd5SMatthias Ringwald                         /* fall through */
51527af5dcd5SMatthias Ringwald 
51537af5dcd5SMatthias Ringwald                     case IRK_LOOKUP_FAILED:
51547af5dcd5SMatthias Ringwald                         sm_conn->sm_pairing_requested = 1;
51557af5dcd5SMatthias Ringwald                         sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
51567af5dcd5SMatthias Ringwald                         sm_pairing_started(sm_conn);
51577af5dcd5SMatthias Ringwald                         break;
51587af5dcd5SMatthias Ringwald                     default:
51597af5dcd5SMatthias Ringwald                         log_info("irk lookup pending");
51607af5dcd5SMatthias Ringwald                         sm_conn->sm_pairing_requested = 1;
51617af5dcd5SMatthias Ringwald                         break;
51627af5dcd5SMatthias Ringwald                 }
516324c20dc4SMatthias Ringwald                 break;
516424c20dc4SMatthias Ringwald             default:
516524c20dc4SMatthias Ringwald                 break;
516624c20dc4SMatthias Ringwald         }
51673deb3ec6SMatthias Ringwald     } else {
51683deb3ec6SMatthias Ringwald         // used as a trigger to start central/master/initiator security procedures
5169175b7faaSMatthias Ringwald         switch (sm_conn->sm_engine_state){
5170175b7faaSMatthias Ringwald             case SM_INITIATOR_CONNECTED:
51713deb3ec6SMatthias Ringwald                 switch (sm_conn->sm_irk_lookup_state){
51723deb3ec6SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
51732d68601cSMatthias Ringwald                         le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, &authenticated, NULL, NULL);
5174f53ec649SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
51752d68601cSMatthias Ringwald                         auth_required = sm_auth_req & SM_AUTHREQ_MITM_PROTECTION;
51762d68601cSMatthias Ringwald                         // re-encrypt is sufficient if we have ltk and that is either already authenticated or we don't require authentication
51772d68601cSMatthias Ringwald                         trigger_reencryption = have_ltk && ((authenticated != 0) || (auth_required == false));
51782d68601cSMatthias Ringwald                         log_info("have ltk %u, authenticated %u, auth required %u => reencrypt %u", have_ltk, authenticated, auth_required, trigger_reencryption);
51792d68601cSMatthias Ringwald                         if (trigger_reencryption){
5180c245ca32SMatthias Ringwald                             sm_conn->sm_pairing_requested = 1;
51815567aa60SMatthias Ringwald                             sm_conn->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
5182c245ca32SMatthias Ringwald                             break;
5183f53ec649SMatthias Ringwald                         }
5184cf373d3aSMatthias Ringwald                         /* fall through */
5185c245ca32SMatthias Ringwald 
518634c39fbdSMatthias Ringwald                     case IRK_LOOKUP_FAILED:
51873deb3ec6SMatthias Ringwald                         sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
51883deb3ec6SMatthias Ringwald                         break;
51893deb3ec6SMatthias Ringwald                     default:
5190d1a1f6a4SMatthias Ringwald                         log_info("irk lookup pending");
519109ea1b62SMatthias Ringwald                         sm_conn->sm_pairing_requested = 1;
51923deb3ec6SMatthias Ringwald                         break;
51933deb3ec6SMatthias Ringwald                 }
5194175b7faaSMatthias Ringwald                 break;
5195cb6d7eb0SMatthias Ringwald             case SM_GENERAL_REENCRYPTION_FAILED:
5196cb6d7eb0SMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
5197cb6d7eb0SMatthias Ringwald                 break;
5198175b7faaSMatthias Ringwald             case SM_GENERAL_IDLE:
519909ea1b62SMatthias Ringwald                 sm_conn->sm_pairing_requested = 1;
5200175b7faaSMatthias Ringwald                 break;
5201175b7faaSMatthias Ringwald             default:
5202175b7faaSMatthias Ringwald                 break;
52033deb3ec6SMatthias Ringwald         }
52043deb3ec6SMatthias Ringwald     }
520570b44dd4SMatthias Ringwald     sm_trigger_run();
52063deb3ec6SMatthias Ringwald }
52073deb3ec6SMatthias Ringwald 
52083deb3ec6SMatthias Ringwald // called by client app on authorization request
5209711e6c80SMatthias Ringwald void sm_authorization_decline(hci_con_handle_t con_handle){
5210711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52113deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52123deb3ec6SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_DECLINED;
5213589f5a99SMatthias 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);
52143deb3ec6SMatthias Ringwald }
52153deb3ec6SMatthias Ringwald 
5216711e6c80SMatthias Ringwald void sm_authorization_grant(hci_con_handle_t con_handle){
5217711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52183deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52193deb3ec6SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_GRANTED;
5220589f5a99SMatthias 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);
52213deb3ec6SMatthias Ringwald }
52223deb3ec6SMatthias Ringwald 
52233deb3ec6SMatthias Ringwald // GAP Bonding API
52243deb3ec6SMatthias Ringwald 
5225711e6c80SMatthias Ringwald void sm_bonding_decline(hci_con_handle_t con_handle){
5226711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52273deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52283deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_DECLINE;
52290af429c6SMatthias Ringwald     log_info("decline, state %u", sm_conn->sm_engine_state);
52300af429c6SMatthias Ringwald     switch(sm_conn->sm_engine_state){
52310af429c6SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
52320af429c6SMatthias Ringwald         case SM_SC_W4_USER_RESPONSE:
52330af429c6SMatthias Ringwald         case SM_SC_W4_CONFIRMATION:
52340af429c6SMatthias Ringwald         case SM_SC_W4_PUBLIC_KEY_COMMAND:
52350af429c6SMatthias Ringwald #endif
52360af429c6SMatthias Ringwald         case SM_PH1_W4_USER_RESPONSE:
5237de2fd182SMatthias Ringwald             switch (setup->sm_stk_generation_method){
5238de2fd182SMatthias Ringwald                 case PK_RESP_INPUT:
5239de2fd182SMatthias Ringwald                 case PK_INIT_INPUT:
524047fb4255SMatthias Ringwald                 case PK_BOTH_INPUT:
52410af429c6SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_PASSKEY_ENTRY_FAILED);
5242de2fd182SMatthias Ringwald                     break;
524347fb4255SMatthias Ringwald                 case NUMERIC_COMPARISON:
5244de2fd182SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_NUMERIC_COMPARISON_FAILED);
5245de2fd182SMatthias Ringwald                     break;
5246de2fd182SMatthias Ringwald                 case JUST_WORKS:
5247de2fd182SMatthias Ringwald                 case OOB:
5248de2fd182SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_UNSPECIFIED_REASON);
5249de2fd182SMatthias Ringwald                     break;
52507bbeb3adSMilanka Ringwald                 default:
52517bbeb3adSMilanka Ringwald                     btstack_assert(false);
52527bbeb3adSMilanka Ringwald                     break;
5253de2fd182SMatthias Ringwald             }
52540af429c6SMatthias Ringwald             break;
52550af429c6SMatthias Ringwald         default:
52560af429c6SMatthias Ringwald             break;
52573deb3ec6SMatthias Ringwald     }
525870b44dd4SMatthias Ringwald     sm_trigger_run();
52593deb3ec6SMatthias Ringwald }
52603deb3ec6SMatthias Ringwald 
5261711e6c80SMatthias Ringwald void sm_just_works_confirm(hci_con_handle_t con_handle){
5262711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52633deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52643deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_CONFIRM;
52653deb3ec6SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_PH1_W4_USER_RESPONSE){
5266136d331aSMatthias Ringwald         if (setup->sm_use_secure_connections){
5267c6b7cbd9SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
5268bbf8db22SMatthias Ringwald         } else {
5269f3582630SMatthias 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);
5270136d331aSMatthias Ringwald         }
52713deb3ec6SMatthias Ringwald     }
52720346c37cSMatthias Ringwald 
52730346c37cSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
5274c6b7cbd9SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_USER_RESPONSE){
5275dc300847SMatthias Ringwald         sm_sc_prepare_dhkey_check(sm_conn);
5276446a8c36SMatthias Ringwald     }
52770346c37cSMatthias Ringwald #endif
52780346c37cSMatthias Ringwald 
527970b44dd4SMatthias Ringwald     sm_trigger_run();
52803deb3ec6SMatthias Ringwald }
52813deb3ec6SMatthias Ringwald 
5282c8c46d51SMatthias Ringwald void sm_numeric_comparison_confirm(hci_con_handle_t con_handle){
5283c8c46d51SMatthias Ringwald     // for now, it's the same
5284c8c46d51SMatthias Ringwald     sm_just_works_confirm(con_handle);
5285c8c46d51SMatthias Ringwald }
5286c8c46d51SMatthias Ringwald 
5287711e6c80SMatthias Ringwald void sm_passkey_input(hci_con_handle_t con_handle, uint32_t passkey){
5288711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52893deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52903deb3ec6SMatthias Ringwald     sm_reset_tk();
5291f8fbdce0SMatthias Ringwald     big_endian_store_32(setup->sm_tk, 12, passkey);
52923deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_PASSKEY;
52933deb3ec6SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_PH1_W4_USER_RESPONSE){
5294f3582630SMatthias 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);
52953deb3ec6SMatthias Ringwald     }
52961c516d8fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
52976535961aSMatthias Ringwald     (void)memcpy(setup->sm_ra, setup->sm_tk, 16);
52986535961aSMatthias Ringwald     (void)memcpy(setup->sm_rb, setup->sm_tk, 16);
529907036a04SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_USER_RESPONSE){
530007036a04SMatthias Ringwald         sm_sc_start_calculating_local_confirm(sm_conn);
530107036a04SMatthias Ringwald     }
53021c516d8fSMatthias Ringwald #endif
530370b44dd4SMatthias Ringwald     sm_trigger_run();
53043deb3ec6SMatthias Ringwald }
53053deb3ec6SMatthias Ringwald 
53063d7fe1e9SMatthias Ringwald void sm_keypress_notification(hci_con_handle_t con_handle, uint8_t action){
53073d7fe1e9SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53083d7fe1e9SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53093d7fe1e9SMatthias Ringwald     if (action > SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED) return;
5310dd4a08fbSMatthias Ringwald     uint8_t num_actions = setup->sm_keypress_notification >> 5;
53114ea43905SMatthias Ringwald     uint8_t flags = setup->sm_keypress_notification & 0x1fu;
5312dd4a08fbSMatthias Ringwald     switch (action){
5313dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_ENTRY_STARTED:
5314dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED:
53154ea43905SMatthias Ringwald             flags |= (1u << action);
5316dd4a08fbSMatthias Ringwald             break;
5317dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_CLEARED:
5318dd4a08fbSMatthias Ringwald             // clear counter, keypress & erased flags + set passkey cleared
53194ea43905SMatthias Ringwald             flags = (flags & 0x19u) | (1u << SM_KEYPRESS_PASSKEY_CLEARED);
5320dd4a08fbSMatthias Ringwald             break;
5321dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_DIGIT_ENTERED:
5322*1d80f1e6SMatthias Ringwald             if ((flags & (1u << SM_KEYPRESS_PASSKEY_DIGIT_ERASED)) != 0u){
5323dd4a08fbSMatthias Ringwald                 // erase actions queued
5324dd4a08fbSMatthias Ringwald                 num_actions--;
53254ea43905SMatthias Ringwald                 if (num_actions == 0u){
5326dd4a08fbSMatthias Ringwald                     // clear counter, keypress & erased flags
53274ea43905SMatthias Ringwald                     flags &= 0x19u;
5328dd4a08fbSMatthias Ringwald                 }
5329dd4a08fbSMatthias Ringwald                 break;
5330dd4a08fbSMatthias Ringwald             }
5331dd4a08fbSMatthias Ringwald             num_actions++;
53324ea43905SMatthias Ringwald             flags |= (1u << SM_KEYPRESS_PASSKEY_DIGIT_ENTERED);
5333dd4a08fbSMatthias Ringwald             break;
5334dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_DIGIT_ERASED:
5335*1d80f1e6SMatthias Ringwald             if ((flags & (1u << SM_KEYPRESS_PASSKEY_DIGIT_ENTERED)) != 0u){
5336dd4a08fbSMatthias Ringwald                 // enter actions queued
5337dd4a08fbSMatthias Ringwald                 num_actions--;
53384ea43905SMatthias Ringwald                 if (num_actions == 0u){
5339dd4a08fbSMatthias Ringwald                     // clear counter, keypress & erased flags
53404ea43905SMatthias Ringwald                     flags &= 0x19u;
5341dd4a08fbSMatthias Ringwald                 }
5342dd4a08fbSMatthias Ringwald                 break;
5343dd4a08fbSMatthias Ringwald             }
5344dd4a08fbSMatthias Ringwald             num_actions++;
53454ea43905SMatthias Ringwald             flags |= (1u << SM_KEYPRESS_PASSKEY_DIGIT_ERASED);
5346dd4a08fbSMatthias Ringwald             break;
5347dd4a08fbSMatthias Ringwald         default:
5348dd4a08fbSMatthias Ringwald             break;
5349dd4a08fbSMatthias Ringwald     }
5350dd4a08fbSMatthias Ringwald     setup->sm_keypress_notification = (num_actions << 5) | flags;
535170b44dd4SMatthias Ringwald     sm_trigger_run();
53523d7fe1e9SMatthias Ringwald }
53533d7fe1e9SMatthias Ringwald 
5354c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
5355d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_oob(void * arg){
5356d1a1f6a4SMatthias Ringwald     UNUSED(arg);
5357d1a1f6a4SMatthias Ringwald     sm_sc_oob_state = SM_SC_OOB_W2_CALC_CONFIRM;
535870b44dd4SMatthias Ringwald     sm_trigger_run();
5359d1a1f6a4SMatthias Ringwald }
5360c59d0c92SMatthias Ringwald uint8_t sm_generate_sc_oob_data(void (*callback)(const uint8_t * confirm_value, const uint8_t * random_value)){
53618334d3d8SMatthias Ringwald 
53628334d3d8SMatthias Ringwald     static btstack_crypto_random_t   sm_crypto_random_oob_request;
53638334d3d8SMatthias Ringwald 
5364c59d0c92SMatthias Ringwald     if (sm_sc_oob_state != SM_SC_OOB_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
5365c59d0c92SMatthias Ringwald     sm_sc_oob_callback = callback;
5366d1a1f6a4SMatthias Ringwald     sm_sc_oob_state = SM_SC_OOB_W4_RANDOM;
5367d1a1f6a4SMatthias Ringwald     btstack_crypto_random_generate(&sm_crypto_random_oob_request, sm_sc_oob_random, 16, &sm_handle_random_result_oob, NULL);
5368c59d0c92SMatthias Ringwald     return 0;
5369c59d0c92SMatthias Ringwald }
5370c59d0c92SMatthias Ringwald #endif
5371c59d0c92SMatthias Ringwald 
53723deb3ec6SMatthias Ringwald /**
5373ba394633SMatthias Ringwald  * @brief Get Identity Resolving state
5374ba394633SMatthias Ringwald  * @param con_handle
5375ba394633SMatthias Ringwald  * @return irk_lookup_state_t
5376ba394633SMatthias Ringwald  */
5377ba394633SMatthias Ringwald irk_lookup_state_t sm_identity_resolving_state(hci_con_handle_t con_handle){
5378ba394633SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
5379ba394633SMatthias Ringwald     if (!sm_conn) return IRK_LOOKUP_IDLE;
5380ba394633SMatthias Ringwald     return sm_conn->sm_irk_lookup_state;
5381ba394633SMatthias Ringwald }
5382ba394633SMatthias Ringwald 
5383ba394633SMatthias Ringwald /**
53843deb3ec6SMatthias Ringwald  * @brief Identify device in LE Device DB
53853deb3ec6SMatthias Ringwald  * @param handle
53866b65794dSMilanka Ringwald  * @return index from le_device_db or -1 if not found/identified
53873deb3ec6SMatthias Ringwald  */
5388711e6c80SMatthias Ringwald int sm_le_device_index(hci_con_handle_t con_handle ){
5389711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53903deb3ec6SMatthias Ringwald     if (!sm_conn) return -1;
53913deb3ec6SMatthias Ringwald     return sm_conn->sm_le_db_index;
53923deb3ec6SMatthias Ringwald }
53933deb3ec6SMatthias Ringwald 
5394916ea5b2SMatthias Ringwald uint8_t sm_get_ltk(hci_con_handle_t con_handle, sm_key_t ltk){
5395916ea5b2SMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
5396916ea5b2SMatthias Ringwald     if (hci_connection == NULL){
5397916ea5b2SMatthias Ringwald         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
5398916ea5b2SMatthias Ringwald     }
5399916ea5b2SMatthias Ringwald     if (hci_connection->link_key_type == 0){
5400916ea5b2SMatthias Ringwald         return ERROR_CODE_PIN_OR_KEY_MISSING;
5401916ea5b2SMatthias Ringwald     }
5402916ea5b2SMatthias Ringwald     memcpy(ltk, hci_connection->link_key, 16);
5403916ea5b2SMatthias Ringwald     return ERROR_CODE_SUCCESS;
5404916ea5b2SMatthias Ringwald }
5405916ea5b2SMatthias Ringwald 
54068f57b085SMatthias Ringwald static int gap_random_address_type_requires_updates(void){
540747ba4de1SMatthias Ringwald     switch (gap_random_adress_type){
540847ba4de1SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_OFF:
540947ba4de1SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_STATIC:
541047ba4de1SMatthias Ringwald             return 0;
541147ba4de1SMatthias Ringwald         default:
54128f57b085SMatthias Ringwald             return 1;
54138f57b085SMatthias Ringwald     }
541447ba4de1SMatthias Ringwald }
5415d70217a2SMatthias Ringwald 
541633373e40SMatthias Ringwald static uint8_t own_address_type(void){
5417b95a5a35SMatthias Ringwald     switch (gap_random_adress_type){
5418b95a5a35SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_OFF:
5419b95a5a35SMatthias Ringwald             return BD_ADDR_TYPE_LE_PUBLIC;
5420b95a5a35SMatthias Ringwald         default:
5421b95a5a35SMatthias Ringwald             return BD_ADDR_TYPE_LE_RANDOM;
5422b95a5a35SMatthias Ringwald     }
542333373e40SMatthias Ringwald }
54248f57b085SMatthias Ringwald 
54253deb3ec6SMatthias Ringwald // GAP LE API
54263deb3ec6SMatthias Ringwald void gap_random_address_set_mode(gap_random_address_type_t random_address_type){
54273deb3ec6SMatthias Ringwald     gap_random_address_update_stop();
54283deb3ec6SMatthias Ringwald     gap_random_adress_type = random_address_type;
5429b95a5a35SMatthias Ringwald     hci_le_set_own_address_type(own_address_type());
54308f57b085SMatthias Ringwald     if (!gap_random_address_type_requires_updates()) return;
54313deb3ec6SMatthias Ringwald     gap_random_address_update_start();
54323deb3ec6SMatthias Ringwald     gap_random_address_trigger();
54333deb3ec6SMatthias Ringwald }
54343deb3ec6SMatthias Ringwald 
54353deb3ec6SMatthias Ringwald gap_random_address_type_t gap_random_address_get_mode(void){
54363deb3ec6SMatthias Ringwald     return gap_random_adress_type;
54373deb3ec6SMatthias Ringwald }
54383deb3ec6SMatthias Ringwald 
54393deb3ec6SMatthias Ringwald void gap_random_address_set_update_period(int period_ms){
54403deb3ec6SMatthias Ringwald     gap_random_adress_update_period = period_ms;
54418f57b085SMatthias Ringwald     if (!gap_random_address_type_requires_updates()) return;
54423deb3ec6SMatthias Ringwald     gap_random_address_update_stop();
54433deb3ec6SMatthias Ringwald     gap_random_address_update_start();
54443deb3ec6SMatthias Ringwald }
54453deb3ec6SMatthias Ringwald 
5446667ba9d1SMatthias Ringwald void gap_random_address_set(const bd_addr_t addr){
54478f57b085SMatthias Ringwald     gap_random_address_set_mode(GAP_RANDOM_ADDRESS_TYPE_STATIC);
54486535961aSMatthias Ringwald     (void)memcpy(sm_random_address, addr, 6);
544963d302e8SMatthias Ringwald     // assert msb bits are set to '11'
545063d302e8SMatthias Ringwald     sm_random_address[0] |= 0xc0;
545163d302e8SMatthias Ringwald     hci_le_random_address_set(sm_random_address);
54527e252622SMatthias Ringwald }
54537e252622SMatthias Ringwald 
5454d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
54553deb3ec6SMatthias Ringwald /*
54563deb3ec6SMatthias Ringwald  * @brief Set Advertisement Paramters
54573deb3ec6SMatthias Ringwald  * @param adv_int_min
54583deb3ec6SMatthias Ringwald  * @param adv_int_max
54593deb3ec6SMatthias Ringwald  * @param adv_type
54603deb3ec6SMatthias Ringwald  * @param direct_address_type
54613deb3ec6SMatthias Ringwald  * @param direct_address
54623deb3ec6SMatthias Ringwald  * @param channel_map
54633deb3ec6SMatthias Ringwald  * @param filter_policy
54643deb3ec6SMatthias Ringwald  *
54653deb3ec6SMatthias Ringwald  * @note own_address_type is used from gap_random_address_set_mode
54663deb3ec6SMatthias Ringwald  */
54673deb3ec6SMatthias Ringwald void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
54683deb3ec6SMatthias Ringwald     uint8_t direct_address_typ, bd_addr_t direct_address, uint8_t channel_map, uint8_t filter_policy){
5469b95a5a35SMatthias Ringwald     hci_le_advertisements_set_params(adv_int_min, adv_int_max, adv_type,
54703deb3ec6SMatthias Ringwald         direct_address_typ, direct_address, channel_map, filter_policy);
54713deb3ec6SMatthias Ringwald }
5472d70217a2SMatthias Ringwald #endif
5473dcd6c9b5SMatthias Ringwald 
5474c7ceba59SMatthias Ringwald bool gap_reconnect_security_setup_active(hci_con_handle_t con_handle){
5475dcd6c9b5SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
5476dcd6c9b5SMatthias Ringwald      // wrong connection
5477c7ceba59SMatthias Ringwald     if (!sm_conn) return false;
5478dcd6c9b5SMatthias Ringwald     // already encrypted
5479c7ceba59SMatthias Ringwald     if (sm_conn->sm_connection_encrypted) return false;
5480dcd6c9b5SMatthias Ringwald     // irk status?
5481dcd6c9b5SMatthias Ringwald     switch(sm_conn->sm_irk_lookup_state){
5482dcd6c9b5SMatthias Ringwald         case IRK_LOOKUP_FAILED:
5483dcd6c9b5SMatthias Ringwald             // done, cannot setup encryption
5484c7ceba59SMatthias Ringwald             return false;
5485dcd6c9b5SMatthias Ringwald         case IRK_LOOKUP_SUCCEEDED:
5486dcd6c9b5SMatthias Ringwald             break;
5487dcd6c9b5SMatthias Ringwald         default:
5488dcd6c9b5SMatthias Ringwald             // IR Lookup pending
5489c7ceba59SMatthias Ringwald             return true;
5490dcd6c9b5SMatthias Ringwald     }
5491f0674e22SMatthias Ringwald     // IRK Lookup Succeeded, re-encryption should be initiated. When done, state gets reset or indicates failure
5492c7ceba59SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_GENERAL_REENCRYPTION_FAILED) return false;
5493c7ceba59SMatthias Ringwald     if (sm_conn->sm_role != 0){
5494b15d5ceaSMatthias Ringwald         return sm_conn->sm_engine_state != SM_RESPONDER_IDLE;
5495b15d5ceaSMatthias Ringwald     } else {
5496dcd6c9b5SMatthias Ringwald         return sm_conn->sm_engine_state != SM_INITIATOR_CONNECTED;
5497dcd6c9b5SMatthias Ringwald     }
5498b15d5ceaSMatthias Ringwald }
54993cdbe9dbSMatthias Ringwald 
55003cdbe9dbSMatthias Ringwald void sm_set_secure_connections_only_mode(bool enable){
55013cdbe9dbSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
55023cdbe9dbSMatthias Ringwald     sm_sc_only_mode = enable;
55033cdbe9dbSMatthias Ringwald #else
55043cdbe9dbSMatthias Ringwald     // SC Only mode not possible without support for SC
55053cdbe9dbSMatthias Ringwald     btstack_assert(enable == false);
55063cdbe9dbSMatthias Ringwald #endif
55073cdbe9dbSMatthias Ringwald }
5508052bbdc5SMatthias Ringwald 
550992f8d6b6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined (ENABLE_LE_SECURE_CONNECTION_DEBUG_KEY)
5510db88441fSMatthias Ringwald void sm_test_enable_secure_connections_debug_keys(void) {
5511db88441fSMatthias Ringwald     log_info("Enable LE Secure Connection Debug Keys for testing");
5512db88441fSMatthias Ringwald     sm_sc_debug_keys_enabled = true;
5513db88441fSMatthias Ringwald     // set debug key
5514db88441fSMatthias Ringwald     sm_ec_generate_new_key();
5515db88441fSMatthias Ringwald }
5516db88441fSMatthias Ringwald #endif
5517db88441fSMatthias Ringwald 
5518052bbdc5SMatthias Ringwald const uint8_t * gap_get_persistent_irk(void){
5519052bbdc5SMatthias Ringwald     return sm_persistent_irk;
5520052bbdc5SMatthias Ringwald }
55214f384501SMatthias Ringwald 
55224f384501SMatthias Ringwald void gap_delete_bonding(bd_addr_type_t address_type, bd_addr_t address){
552322cb578bSMatthias Ringwald     int index = sm_le_device_db_index_lookup(address_type, address);
552422cb578bSMatthias Ringwald     if (index >= 0){
552522cb578bSMatthias Ringwald         sm_remove_le_device_db_entry(index);
55264f384501SMatthias Ringwald     }
55274f384501SMatthias Ringwald }
5528