xref: /btstack/src/ble/sm.c (revision 6e46ecced6a46032a8636fbb068dc852a372496e)
13deb3ec6SMatthias Ringwald /*
23deb3ec6SMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
33deb3ec6SMatthias Ringwald  *
43deb3ec6SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
53deb3ec6SMatthias Ringwald  * modification, are permitted provided that the following conditions
63deb3ec6SMatthias Ringwald  * are met:
73deb3ec6SMatthias Ringwald  *
83deb3ec6SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
93deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
103deb3ec6SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
113deb3ec6SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
123deb3ec6SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
133deb3ec6SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
143deb3ec6SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
153deb3ec6SMatthias Ringwald  *    from this software without specific prior written permission.
163deb3ec6SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
173deb3ec6SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
183deb3ec6SMatthias Ringwald  *    monetary gain.
193deb3ec6SMatthias Ringwald  *
203deb3ec6SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
213deb3ec6SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
223deb3ec6SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
232fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
242fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
253deb3ec6SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
263deb3ec6SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
273deb3ec6SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
283deb3ec6SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
293deb3ec6SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
303deb3ec6SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313deb3ec6SMatthias Ringwald  * SUCH DAMAGE.
323deb3ec6SMatthias Ringwald  *
333deb3ec6SMatthias Ringwald  * Please inquire about commercial licensing options at
343deb3ec6SMatthias Ringwald  * [email protected]
353deb3ec6SMatthias Ringwald  *
363deb3ec6SMatthias Ringwald  */
37ab2c6ae4SMatthias Ringwald 
38e501bae0SMatthias Ringwald #define BTSTACK_FILE__ "sm.c"
393deb3ec6SMatthias Ringwald 
403deb3ec6SMatthias Ringwald #include <string.h>
413deb3ec6SMatthias Ringwald #include <inttypes.h>
423deb3ec6SMatthias Ringwald 
433edc84c5SMatthias Ringwald #include "ble/le_device_db.h"
4459c6af15SMatthias Ringwald #include "ble/core.h"
453edc84c5SMatthias Ringwald #include "ble/sm.h"
4661f37892SMatthias Ringwald #include "bluetooth_company_id.h"
47d7f1c72eSMatthias Ringwald #include "btstack_bool.h"
48d1a1f6a4SMatthias Ringwald #include "btstack_crypto.h"
490e2df43fSMatthias Ringwald #include "btstack_debug.h"
500e2df43fSMatthias Ringwald #include "btstack_event.h"
510e2df43fSMatthias Ringwald #include "btstack_linked_list.h"
520e2df43fSMatthias Ringwald #include "btstack_memory.h"
53899e6e02SMatthias Ringwald #include "btstack_tlv.h"
54f7a05cdaSMatthias Ringwald #include "gap.h"
550e2df43fSMatthias Ringwald #include "hci.h"
5613377825SMatthias Ringwald #include "hci_dump.h"
570e2df43fSMatthias Ringwald #include "l2cap.h"
583deb3ec6SMatthias Ringwald 
591a682202SMatthias Ringwald #if !defined(ENABLE_LE_PERIPHERAL) && !defined(ENABLE_LE_CENTRAL)
601a682202SMatthias Ringwald #error "LE Security Manager used, but neither ENABLE_LE_PERIPHERAL nor ENABLE_LE_CENTRAL defined. Please add at least one to btstack_config.h."
611a682202SMatthias Ringwald #endif
621a682202SMatthias Ringwald 
637ece0eaaSMatthias Ringwald #if defined(ENABLE_CROSS_TRANSPORT_KEY_DERIVATION) && (!defined(ENABLE_CLASSIC) || !defined(ENABLE_LE_SECURE_CONNECTIONS))
647ece0eaaSMatthias Ringwald #error "Cross Transport Key Derivation requires support for LE Secure Connections and BR/EDR (Classic)"
656857ad8fSMatthias Ringwald #endif
666857ad8fSMatthias Ringwald 
67d1a1f6a4SMatthias Ringwald // assert SM Public Key can be sent/received
68d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
69d1a1f6a4SMatthias Ringwald #if HCI_ACL_PAYLOAD_SIZE < 69
70d1a1f6a4SMatthias Ringwald #error "HCI_ACL_PAYLOAD_SIZE must be at least 69 bytes when using LE Secure Conection. Please increase HCI_ACL_PAYLOAD_SIZE or disable ENABLE_LE_SECURE_CONNECTIONS"
71d1a1f6a4SMatthias Ringwald #endif
72d1a1f6a4SMatthias Ringwald #endif
73d1a1f6a4SMatthias Ringwald 
7442134bc6SMatthias Ringwald #if defined(ENABLE_LE_PERIPHERAL) && defined(ENABLE_LE_CENTRAL)
75cd1176f5SMatthias Ringwald #define IS_RESPONDER(role) ((role) == HCI_ROLE_SLAVE)
7642134bc6SMatthias Ringwald #else
7742134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
7842134bc6SMatthias Ringwald // only central - never responder (avoid 'unused variable' warnings)
79cd1176f5SMatthias Ringwald #define IS_RESPONDER(role) (0 && ((role) == HCI_ROLE_SLAVE))
8042134bc6SMatthias Ringwald #else
8142134bc6SMatthias Ringwald // only peripheral - always responder (avoid 'unused variable' warnings)
82cd1176f5SMatthias Ringwald #define IS_RESPONDER(role) (1 || ((role) == HCI_ROLE_SLAVE))
8342134bc6SMatthias Ringwald #endif
8442134bc6SMatthias Ringwald #endif
8542134bc6SMatthias Ringwald 
867a766ebfSMatthias Ringwald #if defined(ENABLE_LE_SIGNED_WRITE) || defined(ENABLE_LE_SECURE_CONNECTIONS)
87d1a1f6a4SMatthias Ringwald #define USE_CMAC_ENGINE
887a766ebfSMatthias Ringwald #endif
897a766ebfSMatthias Ringwald 
906857ad8fSMatthias Ringwald 
91968b2eafSMatthias Ringwald #define BTSTACK_TAG32(A,B,C,D) (((A) << 24) | ((B) << 16) | ((C) << 8) | (D))
92899e6e02SMatthias Ringwald 
933deb3ec6SMatthias Ringwald //
943deb3ec6SMatthias Ringwald // SM internal types and globals
953deb3ec6SMatthias Ringwald //
963deb3ec6SMatthias Ringwald 
973deb3ec6SMatthias Ringwald typedef enum {
983deb3ec6SMatthias Ringwald     DKG_W4_WORKING,
993deb3ec6SMatthias Ringwald     DKG_CALC_IRK,
1003deb3ec6SMatthias Ringwald     DKG_CALC_DHK,
1013deb3ec6SMatthias Ringwald     DKG_READY
1023deb3ec6SMatthias Ringwald } derived_key_generation_t;
1033deb3ec6SMatthias Ringwald 
1043deb3ec6SMatthias Ringwald typedef enum {
1053deb3ec6SMatthias Ringwald     RAU_IDLE,
106fbd4e238SMatthias Ringwald     RAU_GET_RANDOM,
1073deb3ec6SMatthias Ringwald     RAU_W4_RANDOM,
1083deb3ec6SMatthias Ringwald     RAU_GET_ENC,
1093deb3ec6SMatthias Ringwald     RAU_W4_ENC,
1103deb3ec6SMatthias Ringwald } random_address_update_t;
1113deb3ec6SMatthias Ringwald 
1123deb3ec6SMatthias Ringwald typedef enum {
1133deb3ec6SMatthias Ringwald     CMAC_IDLE,
1143deb3ec6SMatthias Ringwald     CMAC_CALC_SUBKEYS,
1153deb3ec6SMatthias Ringwald     CMAC_W4_SUBKEYS,
1163deb3ec6SMatthias Ringwald     CMAC_CALC_MI,
1173deb3ec6SMatthias Ringwald     CMAC_W4_MI,
1183deb3ec6SMatthias Ringwald     CMAC_CALC_MLAST,
1193deb3ec6SMatthias Ringwald     CMAC_W4_MLAST
1203deb3ec6SMatthias Ringwald } cmac_state_t;
1213deb3ec6SMatthias Ringwald 
1223deb3ec6SMatthias Ringwald typedef enum {
1233deb3ec6SMatthias Ringwald     JUST_WORKS,
12427c32905SMatthias Ringwald     PK_RESP_INPUT,       // Initiator displays PK, responder inputs PK
12527c32905SMatthias Ringwald     PK_INIT_INPUT,       // Responder displays PK, initiator inputs PK
12647fb4255SMatthias Ringwald     PK_BOTH_INPUT,       // Only input on both, both input PK
12747fb4255SMatthias Ringwald     NUMERIC_COMPARISON,  // Only numerical compparison (yes/no) on on both sides
12847fb4255SMatthias Ringwald     OOB                  // OOB available on one (SC) or both sides (legacy)
1293deb3ec6SMatthias Ringwald } stk_generation_method_t;
1303deb3ec6SMatthias Ringwald 
1313deb3ec6SMatthias Ringwald typedef enum {
1323deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_IDLE,
1333deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_PENDING,
1343deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_CONFIRM,
1353deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_PASSKEY,
1363deb3ec6SMatthias Ringwald     SM_USER_RESPONSE_DECLINE
1373deb3ec6SMatthias Ringwald } sm_user_response_t;
1383deb3ec6SMatthias Ringwald 
1393deb3ec6SMatthias Ringwald typedef enum {
1403deb3ec6SMatthias Ringwald     SM_AES128_IDLE,
1413deb3ec6SMatthias Ringwald     SM_AES128_ACTIVE
1423deb3ec6SMatthias Ringwald } sm_aes128_state_t;
1433deb3ec6SMatthias Ringwald 
1443deb3ec6SMatthias Ringwald typedef enum {
1453deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_IDLE,
1463deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_GENERAL,
1473deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_FOR_CONNECTION,
1483deb3ec6SMatthias Ringwald } address_resolution_mode_t;
1493deb3ec6SMatthias Ringwald 
1503deb3ec6SMatthias Ringwald typedef enum {
151a66b030fSMatthias Ringwald     ADDRESS_RESOLUTION_SUCCEEDED,
1523deb3ec6SMatthias Ringwald     ADDRESS_RESOLUTION_FAILED,
1533deb3ec6SMatthias Ringwald } address_resolution_event_t;
154901c000fSMatthias Ringwald 
155901c000fSMatthias Ringwald typedef enum {
15634b6528fSMatthias Ringwald     EC_KEY_GENERATION_IDLE,
1577df18c15SMatthias Ringwald     EC_KEY_GENERATION_ACTIVE,
1587df18c15SMatthias Ringwald     EC_KEY_GENERATION_DONE,
1597df18c15SMatthias Ringwald } ec_key_generation_state_t;
1607df18c15SMatthias Ringwald 
1617df18c15SMatthias Ringwald typedef enum {
1623cf37b8cSMatthias Ringwald     SM_STATE_VAR_DHKEY_NEEDED = 1 << 0,
1633cf37b8cSMatthias Ringwald     SM_STATE_VAR_DHKEY_CALCULATED = 1 << 1,
1643cf37b8cSMatthias Ringwald     SM_STATE_VAR_DHKEY_COMMAND_RECEIVED = 1 << 2,
165901c000fSMatthias Ringwald } sm_state_var_t;
166901c000fSMatthias Ringwald 
167c59d0c92SMatthias Ringwald typedef enum {
168c59d0c92SMatthias Ringwald     SM_SC_OOB_IDLE,
169d1a1f6a4SMatthias Ringwald     SM_SC_OOB_W4_RANDOM,
170c59d0c92SMatthias Ringwald     SM_SC_OOB_W2_CALC_CONFIRM,
171c59d0c92SMatthias Ringwald     SM_SC_OOB_W4_CONFIRM,
172c59d0c92SMatthias Ringwald } sm_sc_oob_state_t;
173c59d0c92SMatthias Ringwald 
1746420f61eSMatthias Ringwald typedef uint8_t sm_key24_t[3];
1756420f61eSMatthias Ringwald typedef uint8_t sm_key56_t[7];
1766420f61eSMatthias Ringwald typedef uint8_t sm_key256_t[32];
1776420f61eSMatthias Ringwald 
1783deb3ec6SMatthias Ringwald //
1793deb3ec6SMatthias Ringwald // GLOBAL DATA
1803deb3ec6SMatthias Ringwald //
1813deb3ec6SMatthias Ringwald 
1822d2d4d3cSMatthias Ringwald static bool sm_initialized;
1832d2d4d3cSMatthias Ringwald 
184841468bbSMatthias Ringwald static bool test_use_fixed_local_csrk;
185841468bbSMatthias Ringwald static bool test_use_fixed_local_irk;
1863deb3ec6SMatthias Ringwald 
187192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
188192365feSMatthias Ringwald static uint8_t test_pairing_failure;
189192365feSMatthias Ringwald #endif
190192365feSMatthias Ringwald 
1913deb3ec6SMatthias Ringwald // configuration
1923deb3ec6SMatthias Ringwald static uint8_t sm_accepted_stk_generation_methods;
1933deb3ec6SMatthias Ringwald static uint8_t sm_max_encryption_key_size;
1943deb3ec6SMatthias Ringwald static uint8_t sm_min_encryption_key_size;
1953deb3ec6SMatthias Ringwald static uint8_t sm_auth_req = 0;
1963deb3ec6SMatthias Ringwald static uint8_t sm_io_capabilities = IO_CAPABILITY_NO_INPUT_NO_OUTPUT;
1974b8c611fSMatthias Ringwald static uint32_t sm_fixed_passkey_in_display_role;
1981979f09cSMatthias Ringwald static bool sm_reconstruct_ltk_without_le_device_db_entry;
1993deb3ec6SMatthias Ringwald 
200b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
201728f6757SMatthias Ringwald static bool sm_slave_request_security;
202b6f39a74SMatthias Ringwald #endif
203b6f39a74SMatthias Ringwald 
204c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
205c123d999SMatthias Ringwald static bool sm_sc_only_mode;
206c59d0c92SMatthias Ringwald static uint8_t sm_sc_oob_random[16];
207c59d0c92SMatthias Ringwald static void (*sm_sc_oob_callback)(const uint8_t * confirm_value, const uint8_t * random_value);
208c59d0c92SMatthias Ringwald static sm_sc_oob_state_t sm_sc_oob_state;
209db88441fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS_DEBUG_KEY
210db88441fSMatthias Ringwald static bool sm_sc_debug_keys_enabled;
211db88441fSMatthias Ringwald #endif
212c59d0c92SMatthias Ringwald #endif
213c59d0c92SMatthias Ringwald 
214899e6e02SMatthias Ringwald 
2151979f09cSMatthias Ringwald static bool                  sm_persistent_keys_random_active;
216899e6e02SMatthias Ringwald static const btstack_tlv_t * sm_tlv_impl;
217899e6e02SMatthias Ringwald static void *                sm_tlv_context;
218899e6e02SMatthias Ringwald 
2193deb3ec6SMatthias Ringwald // Security Manager Master Keys, please use sm_set_er(er) and sm_set_ir(ir) with your own 128 bit random values
2203deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_er;
2213deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_ir;
2223deb3ec6SMatthias Ringwald 
2233deb3ec6SMatthias Ringwald // derived from sm_persistent_ir
2243deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_dhk;
2253deb3ec6SMatthias Ringwald static sm_key_t sm_persistent_irk;
2263deb3ec6SMatthias Ringwald static derived_key_generation_t dkg_state;
2273deb3ec6SMatthias Ringwald 
2283deb3ec6SMatthias Ringwald // derived from sm_persistent_er
2293deb3ec6SMatthias Ringwald // ..
2303deb3ec6SMatthias Ringwald 
2313deb3ec6SMatthias Ringwald // random address update
2323deb3ec6SMatthias Ringwald static random_address_update_t rau_state;
2333deb3ec6SMatthias Ringwald static bd_addr_t sm_random_address;
2343deb3ec6SMatthias Ringwald 
235d1a1f6a4SMatthias Ringwald #ifdef USE_CMAC_ENGINE
236514d35fcSMatthias Ringwald // CMAC Calculation: General
237d1a1f6a4SMatthias Ringwald static btstack_crypto_aes128_cmac_t sm_cmac_request;
238d1a1f6a4SMatthias Ringwald static void (*sm_cmac_done_callback)(uint8_t hash[8]);
239d1a1f6a4SMatthias Ringwald static uint8_t sm_cmac_active;
240d1a1f6a4SMatthias Ringwald static uint8_t sm_cmac_hash[16];
2417a766ebfSMatthias Ringwald #endif
242514d35fcSMatthias Ringwald 
243514d35fcSMatthias Ringwald // CMAC for ATT Signed Writes
2447a766ebfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
245d1a1f6a4SMatthias Ringwald static uint16_t        sm_cmac_signed_write_message_len;
246d1a1f6a4SMatthias Ringwald static uint8_t         sm_cmac_signed_write_header[3];
247d1a1f6a4SMatthias Ringwald static const uint8_t * sm_cmac_signed_write_message;
248d1a1f6a4SMatthias Ringwald static uint8_t         sm_cmac_signed_write_sign_counter[4];
2497a766ebfSMatthias Ringwald #endif
250514d35fcSMatthias Ringwald 
251514d35fcSMatthias Ringwald // CMAC for Secure Connection functions
252514d35fcSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
253aec94140SMatthias Ringwald static sm_connection_t * sm_cmac_connection;
254514d35fcSMatthias Ringwald static uint8_t           sm_cmac_sc_buffer[80];
255514d35fcSMatthias Ringwald #endif
2563deb3ec6SMatthias Ringwald 
2573deb3ec6SMatthias Ringwald // resolvable private address lookup / CSRK calculation
2583deb3ec6SMatthias Ringwald static int       sm_address_resolution_test;
2593deb3ec6SMatthias Ringwald static uint8_t   sm_address_resolution_addr_type;
2603deb3ec6SMatthias Ringwald static bd_addr_t sm_address_resolution_address;
2613deb3ec6SMatthias Ringwald static void *    sm_address_resolution_context;
2623deb3ec6SMatthias Ringwald static address_resolution_mode_t sm_address_resolution_mode;
2638f2a52f4SMatthias Ringwald static btstack_linked_list_t sm_address_resolution_general_queue;
2643deb3ec6SMatthias Ringwald 
265d1a1f6a4SMatthias Ringwald // aes128 crypto engine.
2663deb3ec6SMatthias Ringwald static sm_aes128_state_t  sm_aes128_state;
2673deb3ec6SMatthias Ringwald 
268d1a1f6a4SMatthias Ringwald // crypto
269d1a1f6a4SMatthias Ringwald static btstack_crypto_random_t   sm_crypto_random_request;
270d1a1f6a4SMatthias Ringwald static btstack_crypto_aes128_t   sm_crypto_aes128_request;
271d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
272d1a1f6a4SMatthias Ringwald static btstack_crypto_ecc_p256_t sm_crypto_ecc_p256_request;
2737df1ef2fSMatthias Ringwald #endif
2747df1ef2fSMatthias Ringwald 
275d1a1f6a4SMatthias Ringwald // temp storage for random data
276d1a1f6a4SMatthias Ringwald static uint8_t sm_random_data[8];
277d1a1f6a4SMatthias Ringwald static uint8_t sm_aes128_key[16];
278d1a1f6a4SMatthias Ringwald static uint8_t sm_aes128_plaintext[16];
279d1a1f6a4SMatthias Ringwald static uint8_t sm_aes128_ciphertext[16];
2803deb3ec6SMatthias Ringwald 
281a036ae12SMatthias Ringwald // to receive events
282e03e489aSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
283c5b6ce22SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
284a036ae12SMatthias Ringwald static btstack_packet_callback_registration_t l2cap_event_callback_registration;
285c5b6ce22SMatthias Ringwald #endif
286e03e489aSMatthias Ringwald 
28789a78d34SMatthias Ringwald /* to dispatch sm event */
28889a78d34SMatthias Ringwald static btstack_linked_list_t sm_event_handlers;
28989a78d34SMatthias Ringwald 
290ece00d2dSMatthias Ringwald /* to schedule calls to sm_run */
291ece00d2dSMatthias Ringwald static btstack_timer_source_t sm_run_timer;
292ece00d2dSMatthias Ringwald 
29309e4d397SMatthias Ringwald // LE Secure Connections
29409e4d397SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
29509e4d397SMatthias Ringwald static ec_key_generation_state_t ec_key_generation_state;
296fc5bff5fSMatthias Ringwald static uint8_t ec_q[64];
29709e4d397SMatthias Ringwald #endif
298df86eb96SMatthias Ringwald 
2993deb3ec6SMatthias Ringwald //
3003deb3ec6SMatthias Ringwald // Volume 3, Part H, Chapter 24
3013deb3ec6SMatthias Ringwald // "Security shall be initiated by the Security Manager in the device in the master role.
3023deb3ec6SMatthias Ringwald // The device in the slave role shall be the responding device."
3033deb3ec6SMatthias Ringwald // -> master := initiator, slave := responder
3043deb3ec6SMatthias Ringwald //
3053deb3ec6SMatthias Ringwald 
3063deb3ec6SMatthias Ringwald // data needed for security setup
3073deb3ec6SMatthias Ringwald typedef struct sm_setup_context {
3083deb3ec6SMatthias Ringwald 
309ec820d77SMatthias Ringwald     btstack_timer_source_t sm_timeout;
3103deb3ec6SMatthias Ringwald 
3113deb3ec6SMatthias Ringwald     // user response, (Phase 1 and/or 2)
3123deb3ec6SMatthias Ringwald     uint8_t   sm_user_response;
313dd4a08fbSMatthias Ringwald     uint8_t   sm_keypress_notification; // bitmap: passkey started, digit entered, digit erased, passkey cleared, passkey complete, 3 bit count
3143deb3ec6SMatthias Ringwald 
3153deb3ec6SMatthias Ringwald     // defines which keys will be send after connection is encrypted - calculated during Phase 1, used Phase 3
316715a43d1SMatthias Ringwald     uint8_t   sm_key_distribution_send_set;
317715a43d1SMatthias Ringwald     uint8_t   sm_key_distribution_sent_set;
3189a90d41aSMatthias Ringwald     uint8_t   sm_key_distribution_expected_set;
319715a43d1SMatthias Ringwald     uint8_t   sm_key_distribution_received_set;
3203deb3ec6SMatthias Ringwald 
3213deb3ec6SMatthias Ringwald     // Phase 2 (Pairing over SMP)
3223deb3ec6SMatthias Ringwald     stk_generation_method_t sm_stk_generation_method;
3233deb3ec6SMatthias Ringwald     sm_key_t  sm_tk;
324a680ba6bSMatthias Ringwald     uint8_t   sm_have_oob_data;
3256777d8fdSMatthias Ringwald     bool      sm_use_secure_connections;
3263deb3ec6SMatthias Ringwald 
3273deb3ec6SMatthias Ringwald     sm_key_t  sm_c1_t3_value;   // c1 calculation
3283deb3ec6SMatthias Ringwald     sm_pairing_packet_t sm_m_preq; // pairing request - needed only for c1
3293deb3ec6SMatthias Ringwald     sm_pairing_packet_t sm_s_pres; // pairing response - needed only for c1
3303deb3ec6SMatthias Ringwald     sm_key_t  sm_local_random;
3313deb3ec6SMatthias Ringwald     sm_key_t  sm_local_confirm;
3323deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_random;
3333deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_confirm;
3343deb3ec6SMatthias Ringwald     uint8_t   sm_m_addr_type;   // address and type can be removed
3353deb3ec6SMatthias Ringwald     uint8_t   sm_s_addr_type;   //  ''
3363deb3ec6SMatthias Ringwald     bd_addr_t sm_m_address;     //  ''
3373deb3ec6SMatthias Ringwald     bd_addr_t sm_s_address;     //  ''
3383deb3ec6SMatthias Ringwald     sm_key_t  sm_ltk;
3393deb3ec6SMatthias Ringwald 
34068437d83SMatthias Ringwald     uint8_t   sm_state_vars;
341e53be891SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
342fc5bff5fSMatthias Ringwald     uint8_t   sm_peer_q[64];    // also stores random for EC key generation during init
343446a8c36SMatthias Ringwald     sm_key_t  sm_peer_nonce;    // might be combined with sm_peer_random
344446a8c36SMatthias Ringwald     sm_key_t  sm_local_nonce;   // might be combined with sm_local_random
345d08147dfSMatthias Ringwald     uint8_t   sm_dhkey[32];
346e53be891SMatthias Ringwald     sm_key_t  sm_peer_dhkey_check;
347e53be891SMatthias Ringwald     sm_key_t  sm_local_dhkey_check;
348446a8c36SMatthias Ringwald     sm_key_t  sm_ra;
349446a8c36SMatthias Ringwald     sm_key_t  sm_rb;
3502bacf595SMatthias Ringwald     sm_key_t  sm_t;             // used for f5 and h6
351a9f29768SMatthias Ringwald     sm_key_t  sm_mackey;
3527df18c15SMatthias Ringwald     uint8_t   sm_passkey_bit;   // also stores number of generated random bytes for EC key generation
353e53be891SMatthias Ringwald #endif
35427c32905SMatthias Ringwald 
3553deb3ec6SMatthias Ringwald     // Phase 3
3563deb3ec6SMatthias Ringwald 
3573deb3ec6SMatthias Ringwald     // key distribution, we generate
3583deb3ec6SMatthias Ringwald     uint16_t  sm_local_y;
3593deb3ec6SMatthias Ringwald     uint16_t  sm_local_div;
3603deb3ec6SMatthias Ringwald     uint16_t  sm_local_ediv;
3613deb3ec6SMatthias Ringwald     uint8_t   sm_local_rand[8];
3623deb3ec6SMatthias Ringwald     sm_key_t  sm_local_ltk;
3633deb3ec6SMatthias Ringwald     sm_key_t  sm_local_csrk;
3643deb3ec6SMatthias Ringwald     sm_key_t  sm_local_irk;
3653deb3ec6SMatthias Ringwald     // sm_local_address/addr_type not needed
3663deb3ec6SMatthias Ringwald 
3673deb3ec6SMatthias Ringwald     // key distribution, received from peer
3683deb3ec6SMatthias Ringwald     uint16_t  sm_peer_y;
3693deb3ec6SMatthias Ringwald     uint16_t  sm_peer_div;
3703deb3ec6SMatthias Ringwald     uint16_t  sm_peer_ediv;
3713deb3ec6SMatthias Ringwald     uint8_t   sm_peer_rand[8];
3723deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_ltk;
3733deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_irk;
3743deb3ec6SMatthias Ringwald     sm_key_t  sm_peer_csrk;
3753deb3ec6SMatthias Ringwald     uint8_t   sm_peer_addr_type;
3763deb3ec6SMatthias Ringwald     bd_addr_t sm_peer_address;
377715a43d1SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
378715a43d1SMatthias Ringwald     int       sm_le_device_index;
379715a43d1SMatthias Ringwald #endif
380e0a03c85SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
381e0a03c85SMatthias Ringwald     link_key_t sm_link_key;
382e0a03c85SMatthias Ringwald     link_key_type_t sm_link_key_type;
383e0a03c85SMatthias Ringwald #endif
3843deb3ec6SMatthias Ringwald } sm_setup_context_t;
3853deb3ec6SMatthias Ringwald 
3863deb3ec6SMatthias Ringwald //
3873deb3ec6SMatthias Ringwald static sm_setup_context_t the_setup;
3883deb3ec6SMatthias Ringwald static sm_setup_context_t * setup = &the_setup;
3893deb3ec6SMatthias Ringwald 
3903deb3ec6SMatthias Ringwald // active connection - the one for which the_setup is used for
3917149bde5SMatthias Ringwald static uint16_t sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
3923deb3ec6SMatthias Ringwald 
3936b65794dSMilanka Ringwald // @return 1 if oob data is available
3943deb3ec6SMatthias Ringwald // stores oob data in provided 16 byte buffer if not null
3953deb3ec6SMatthias Ringwald static int (*sm_get_oob_data)(uint8_t addres_type, bd_addr_t addr, uint8_t * oob_data) = NULL;
3964acf7b7bSMatthias Ringwald static int (*sm_get_sc_oob_data)(uint8_t addres_type, bd_addr_t addr, uint8_t * oob_sc_peer_confirm, uint8_t * oob_sc_peer_random);
397b96d60a6SMatthias Ringwald static bool (*sm_get_ltk_callback)(hci_con_handle_t con_handle, uint8_t addres_type, bd_addr_t addr, uint8_t * ltk);
3983deb3ec6SMatthias Ringwald 
3993deb3ec6SMatthias Ringwald static void sm_run(void);
4007887cd92SMatthias Ringwald static void sm_state_reset(void);
401711e6c80SMatthias Ringwald static void sm_done_for_handle(hci_con_handle_t con_handle);
402711e6c80SMatthias Ringwald static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle);
403916ea5b2SMatthias Ringwald static void sm_cache_ltk(sm_connection_t * connection, const sm_key_t ltk);
40477e2e5edSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
40577e2e5edSMatthias Ringwald static sm_connection_t * sm_get_connection_for_bd_addr_and_type(bd_addr_t address, bd_addr_type_t addr_type);
40677e2e5edSMatthias Ringwald #endif
4073deb3ec6SMatthias Ringwald static inline int sm_calc_actual_encryption_key_size(int other);
4083deb3ec6SMatthias Ringwald static int sm_validate_stk_generation_method(void);
409d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_address_resolution(void *arg);
410d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_dhk(void *arg);
411d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_irk(void *arg);
412d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_a(void *arg);
413d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_b(void *arg);
414d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_c(void *arg);
415d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_csrk(void *arg);
416d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_d(void * arg);
417d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_ltk(void *arg);
418d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_y(void *arg);
4192a526f21SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
420d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_ltk(void *arg);
421d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_y(void *arg);
4222a526f21SMatthias Ringwald #endif
423d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_stk(void *arg);
424d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_rau(void *arg);
425d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_tk(void * arg);
426d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_rau(void * arg);
427d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4286d80b495SMatthias Ringwald static void sm_cmac_message_start(const sm_key_t key, uint16_t message_len, const uint8_t * message, void (*done_callback)(uint8_t * hash));
42934b6528fSMatthias Ringwald static void sm_ec_generate_new_key(void);
4306ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_w2_cmac_for_confirmation(void * arg);
4316ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_send_pairing_random(void * arg);
4326777d8fdSMatthias Ringwald static bool sm_passkey_entry(stk_generation_method_t method);
433d1a1f6a4SMatthias Ringwald #endif
4340ccf6c9cSMatthias Ringwald static void sm_pairing_complete(sm_connection_t * sm_conn, uint8_t status, uint8_t reason);
4353deb3ec6SMatthias Ringwald 
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 
5421d80f1e6SMatthias Ringwald static bool sm_er_is_default(void){
543899e6e02SMatthias Ringwald     int i;
544899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
5451d80f1e6SMatthias Ringwald         if (sm_persistent_er[i] != (0x30+i)) return true;
546899e6e02SMatthias Ringwald     }
5471d80f1e6SMatthias Ringwald     return false;
548899e6e02SMatthias Ringwald }
549899e6e02SMatthias Ringwald 
5501d80f1e6SMatthias Ringwald static bool sm_ir_is_default(void){
551899e6e02SMatthias Ringwald     int i;
552899e6e02SMatthias Ringwald     for (i=0;i<16;i++){
5531d80f1e6SMatthias Ringwald         if (sm_persistent_ir[i] != (0x90+i)) return true;
554899e6e02SMatthias Ringwald     }
5551d80f1e6SMatthias 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
5629da9850bSMatthias Ringwald     hci_dump_btstack_event(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 
9421d80f1e6SMatthias 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
1131b2072c76SMatthias Ringwald         // LinkKey for CTKD requires SC and BR/EDR Support
1132b2072c76SMatthias Ringwald         if (hci_classic_supported() && ((sm_auth_req & SM_AUTHREQ_SECURE_CONNECTION) != 0)){
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 
12044361507fSMatthias Ringwald     log_info("our  address %s type %u", bd_addr_to_str(sm_conn->sm_own_address), sm_conn->sm_own_addr_type);
12054361507fSMatthias Ringwald     log_info("peer address %s type %u", bd_addr_to_str(sm_conn->sm_peer_address), sm_conn->sm_peer_addr_type);
12064361507fSMatthias Ringwald 
120757132f12SMatthias Ringwald     uint8_t auth_req = sm_auth_req & ~SM_AUTHREQ_CT2;
1208d0ea782aSMatthias Ringwald     uint8_t max_encryption_key_size = sm_max_encryption_key_size;
12092c041b42SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12102c041b42SMatthias Ringwald     // enable SC for SC only mode
12112c041b42SMatthias Ringwald     if (sm_sc_only_mode){
12122c041b42SMatthias Ringwald         auth_req |= SM_AUTHREQ_SECURE_CONNECTION;
1213d0ea782aSMatthias Ringwald         max_encryption_key_size = 16;
12142c041b42SMatthias Ringwald     }
12152c041b42SMatthias Ringwald #endif
121657132f12SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
121757132f12SMatthias Ringwald 	// set CT2 if SC + Bonding + CTKD
121857132f12SMatthias Ringwald 	const uint8_t auth_req_for_ct2 = SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING;
121957132f12SMatthias Ringwald 	if ((auth_req & auth_req_for_ct2) == auth_req_for_ct2){
122057132f12SMatthias Ringwald 		auth_req |= SM_AUTHREQ_CT2;
122157132f12SMatthias Ringwald 	}
122257132f12SMatthias Ringwald #endif
12231ad129beSMatthias Ringwald     sm_pairing_packet_set_io_capability(*local_packet, sm_io_capabilities);
1224a680ba6bSMatthias Ringwald     sm_pairing_packet_set_oob_data_flag(*local_packet, setup->sm_have_oob_data);
1225df86eb96SMatthias Ringwald     sm_pairing_packet_set_auth_req(*local_packet, auth_req);
1226d0ea782aSMatthias Ringwald     sm_pairing_packet_set_max_encryption_key_size(*local_packet, max_encryption_key_size);
12273deb3ec6SMatthias Ringwald }
12283deb3ec6SMatthias Ringwald 
12293deb3ec6SMatthias Ringwald static int sm_stk_generation_init(sm_connection_t * sm_conn){
12303deb3ec6SMatthias Ringwald 
12313deb3ec6SMatthias Ringwald     sm_pairing_packet_t * remote_packet;
12329a90d41aSMatthias Ringwald     uint8_t               keys_to_send;
12339a90d41aSMatthias Ringwald     uint8_t               keys_to_receive;
123442134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
123552f9cf63SMatthias Ringwald         // slave / responder
12363deb3ec6SMatthias Ringwald         remote_packet   = &setup->sm_m_preq;
12379a90d41aSMatthias Ringwald         keys_to_send    = sm_pairing_packet_get_responder_key_distribution(setup->sm_m_preq);
12389a90d41aSMatthias Ringwald         keys_to_receive = sm_pairing_packet_get_initiator_key_distribution(setup->sm_m_preq);
12393deb3ec6SMatthias Ringwald     } else {
12403deb3ec6SMatthias Ringwald         // master / initiator
12413deb3ec6SMatthias Ringwald         remote_packet   = &setup->sm_s_pres;
12429a90d41aSMatthias Ringwald         keys_to_send    = sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres);
12439a90d41aSMatthias Ringwald         keys_to_receive = sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres);
12443deb3ec6SMatthias Ringwald     }
12453deb3ec6SMatthias Ringwald 
12463deb3ec6SMatthias Ringwald     // check key size
12472c041b42SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12482c041b42SMatthias Ringwald     // SC Only mandates 128 bit key size
12492c041b42SMatthias Ringwald     if (sm_sc_only_mode && (sm_pairing_packet_get_max_encryption_key_size(*remote_packet) < 16)) {
12502c041b42SMatthias Ringwald         return SM_REASON_ENCRYPTION_KEY_SIZE;
12512c041b42SMatthias Ringwald     }
12522c041b42SMatthias Ringwald #endif
12531ad129beSMatthias Ringwald     sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(sm_pairing_packet_get_max_encryption_key_size(*remote_packet));
12544ea43905SMatthias Ringwald     if (sm_conn->sm_actual_encryption_key_size == 0u) return SM_REASON_ENCRYPTION_KEY_SIZE;
12553deb3ec6SMatthias Ringwald 
1256eddc894fSMatthias Ringwald     // decide on STK generation method / SC
12573deb3ec6SMatthias Ringwald     sm_setup_tk();
12583deb3ec6SMatthias Ringwald     log_info("SMP: generation method %u", setup->sm_stk_generation_method);
12593deb3ec6SMatthias Ringwald 
12603deb3ec6SMatthias Ringwald     // check if STK generation method is acceptable by client
12613deb3ec6SMatthias Ringwald     if (!sm_validate_stk_generation_method()) return SM_REASON_AUTHENTHICATION_REQUIREMENTS;
12623deb3ec6SMatthias Ringwald 
1263eddc894fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
12642c041b42SMatthias Ringwald     // Check LE SC Only mode
12653cdbe9dbSMatthias Ringwald     if (sm_sc_only_mode && (setup->sm_use_secure_connections == false)){
12663cdbe9dbSMatthias Ringwald         log_info("SC Only mode active but SC not possible");
12673cdbe9dbSMatthias Ringwald         return SM_REASON_AUTHENTHICATION_REQUIREMENTS;
12683cdbe9dbSMatthias Ringwald     }
12693cdbe9dbSMatthias Ringwald 
12709a90d41aSMatthias Ringwald     // LTK (= encryption information & master identification) only used exchanged for LE Legacy Connection
1271eddc894fSMatthias Ringwald     if (setup->sm_use_secure_connections){
12729a90d41aSMatthias Ringwald         keys_to_send &= ~SM_KEYDIST_ENC_KEY;
12739a90d41aSMatthias Ringwald         keys_to_receive  &= ~SM_KEYDIST_ENC_KEY;
1274eddc894fSMatthias Ringwald     }
1275eddc894fSMatthias Ringwald #endif
1276eddc894fSMatthias Ringwald 
127752f9cf63SMatthias Ringwald     // identical to responder
12789a90d41aSMatthias Ringwald     sm_setup_key_distribution(keys_to_send, keys_to_receive);
127952f9cf63SMatthias Ringwald 
12803deb3ec6SMatthias Ringwald     // JUST WORKS doens't provide authentication
1281c1ab6cc1SMatthias Ringwald     sm_conn->sm_connection_authenticated = (setup->sm_stk_generation_method == JUST_WORKS) ? 0 : 1;
12823deb3ec6SMatthias Ringwald 
12833deb3ec6SMatthias Ringwald     return 0;
12843deb3ec6SMatthias Ringwald }
12853deb3ec6SMatthias Ringwald 
12863deb3ec6SMatthias Ringwald static void sm_address_resolution_handle_event(address_resolution_event_t event){
12873deb3ec6SMatthias Ringwald 
12883deb3ec6SMatthias Ringwald     // cache and reset context
12893deb3ec6SMatthias Ringwald     int matched_device_id = sm_address_resolution_test;
12903deb3ec6SMatthias Ringwald     address_resolution_mode_t mode = sm_address_resolution_mode;
12913deb3ec6SMatthias Ringwald     void * context = sm_address_resolution_context;
12923deb3ec6SMatthias Ringwald 
12933deb3ec6SMatthias Ringwald     // reset context
12943deb3ec6SMatthias Ringwald     sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
12953deb3ec6SMatthias Ringwald     sm_address_resolution_context = NULL;
12963deb3ec6SMatthias Ringwald     sm_address_resolution_test = -1;
12973deb3ec6SMatthias Ringwald 
129845d80b08SMatthias Ringwald     hci_con_handle_t con_handle = HCI_CON_HANDLE_INVALID;
12993deb3ec6SMatthias Ringwald     sm_connection_t * sm_connection;
1300d2e90122SMatthias Ringwald     sm_key_t ltk;
13011979f09cSMatthias Ringwald     bool have_ltk;
130245d80b08SMatthias Ringwald     int authenticated;
13036c44b759SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
13041979f09cSMatthias Ringwald     bool trigger_pairing;
130542134bc6SMatthias Ringwald #endif
130645d80b08SMatthias Ringwald 
13073deb3ec6SMatthias Ringwald     switch (mode){
13083deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_GENERAL:
13093deb3ec6SMatthias Ringwald             break;
13103deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_FOR_CONNECTION:
13113deb3ec6SMatthias Ringwald             sm_connection = (sm_connection_t *) context;
1312711e6c80SMatthias Ringwald             con_handle = sm_connection->sm_handle;
13136c44b759SMatthias Ringwald 
13146c44b759SMatthias Ringwald             // have ltk -> start encryption / send security request
13156c44b759SMatthias Ringwald             // Core 5, Vol 3, Part C, 10.3.2 Initiating a Service Request
13166c44b759SMatthias Ringwald             // "When a bond has been created between two devices, any reconnection should result in the local device
13176c44b759SMatthias Ringwald             //  enabling or requesting encryption with the remote device before initiating any service request."
13186c44b759SMatthias Ringwald 
13193deb3ec6SMatthias Ringwald             switch (event){
1320a66b030fSMatthias Ringwald                 case ADDRESS_RESOLUTION_SUCCEEDED:
13213deb3ec6SMatthias Ringwald                     sm_connection->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
13223deb3ec6SMatthias Ringwald                     sm_connection->sm_le_db_index = matched_device_id;
1323a66b030fSMatthias Ringwald                     log_info("ADDRESS_RESOLUTION_SUCCEEDED, index %d", sm_connection->sm_le_db_index);
13246c44b759SMatthias Ringwald 
13252d68601cSMatthias Ringwald                     le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, &authenticated, NULL, NULL);
13266c44b759SMatthias Ringwald                     have_ltk = !sm_is_null_key(ltk);
13276c44b759SMatthias Ringwald 
1328f688bdb8SMatthias Ringwald                     if (IS_RESPONDER(sm_connection->sm_role)) {
13296c44b759SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
1330212d735eSMatthias Ringwald                         // IRK required before, continue
13316c39055aSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){
13326c39055aSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
13336c39055aSMatthias Ringwald                             break;
13346c39055aSMatthias Ringwald                         }
1335434260a1SMatthias Ringwald                         // Pairing request before, continue
1336212d735eSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK){
1337212d735eSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
1338212d735eSMatthias Ringwald                             break;
1339212d735eSMatthias Ringwald                         }
1340728f6757SMatthias Ringwald                         bool trigger_security_request = sm_connection->sm_pairing_requested || sm_slave_request_security;
13415f3874afSMatthias Ringwald                         sm_connection->sm_pairing_requested = false;
13426c44b759SMatthias Ringwald #ifdef ENABLE_LE_PROACTIVE_AUTHENTICATION
13437af5dcd5SMatthias Ringwald                         // trigger security request for Proactive Authentication if LTK available
13447af5dcd5SMatthias Ringwald                         trigger_security_request = trigger_security_request || have_ltk;
13456c44b759SMatthias Ringwald #endif
13467af5dcd5SMatthias Ringwald 
13477af5dcd5SMatthias Ringwald                         log_info("peripheral: pairing request local %u, have_ltk %u => trigger_security_request %u",
13485f3874afSMatthias Ringwald                                  (int) sm_connection->sm_pairing_requested, (int) have_ltk, trigger_security_request);
13497af5dcd5SMatthias Ringwald 
13507af5dcd5SMatthias Ringwald                         if (trigger_security_request){
13517af5dcd5SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
13527af5dcd5SMatthias Ringwald                             if (have_ltk){
13537af5dcd5SMatthias Ringwald                                 sm_reencryption_started(sm_connection);
13547af5dcd5SMatthias Ringwald                             } else {
13557af5dcd5SMatthias Ringwald                                 sm_pairing_started(sm_connection);
13567af5dcd5SMatthias Ringwald                             }
13577af5dcd5SMatthias Ringwald                             sm_trigger_run();
13586c44b759SMatthias Ringwald                         }
13596c44b759SMatthias Ringwald #endif
13606c44b759SMatthias Ringwald                     } else {
13616c44b759SMatthias Ringwald 
136242134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
13636c44b759SMatthias Ringwald                         // check if pairing already requested and reset requests
13646c44b759SMatthias Ringwald                         trigger_pairing = sm_connection->sm_pairing_requested || sm_connection->sm_security_request_received;
13652d68601cSMatthias Ringwald                         bool auth_required = sm_auth_req & SM_AUTHREQ_MITM_PROTECTION;
13662d68601cSMatthias Ringwald 
13676c44b759SMatthias Ringwald                         log_info("central: pairing request local %u, remote %u => trigger_pairing %u. have_ltk %u",
13685f3874afSMatthias Ringwald                                  (int) sm_connection->sm_pairing_requested, (int) sm_connection->sm_security_request_received, (int) trigger_pairing, (int) have_ltk);
13690dcaa15fSMatthias Ringwald                         sm_connection->sm_security_request_received = false;
13705f3874afSMatthias Ringwald                         sm_connection->sm_pairing_requested = false;
137132bc5d65SMatthias Ringwald                         bool trigger_reencryption = false;
1372c245ca32SMatthias Ringwald 
1373d4af1595SMatthias Ringwald                         if (have_ltk){
13742d68601cSMatthias Ringwald                             if (trigger_pairing){
13752d68601cSMatthias Ringwald                                 // if pairing is requested, re-encryption is sufficient, if ltk is already authenticated or we don't require authentication
13762d68601cSMatthias Ringwald                                 trigger_reencryption = (authenticated != 0) || (auth_required == false);
13772d68601cSMatthias Ringwald                             } else {
13786a43f611SMatthias Ringwald #ifdef ENABLE_LE_PROACTIVE_AUTHENTICATION
1379b187cc61SMatthias Ringwald                                 trigger_reencryption = true;
138032bc5d65SMatthias Ringwald #else
138132bc5d65SMatthias Ringwald                                 log_info("central: defer enabling encryption for bonded device");
138232bc5d65SMatthias Ringwald #endif
138332bc5d65SMatthias Ringwald                             }
13842d68601cSMatthias Ringwald                         }
138532bc5d65SMatthias Ringwald 
138632bc5d65SMatthias Ringwald                         if (trigger_reencryption){
13876c44b759SMatthias Ringwald                             log_info("central: enable encryption for bonded device");
13885567aa60SMatthias Ringwald                             sm_connection->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
1389d4af1595SMatthias Ringwald                             break;
1390d4af1595SMatthias Ringwald                         }
13916c44b759SMatthias Ringwald 
13926c44b759SMatthias Ringwald                         // pairing_request -> send pairing request
13936c44b759SMatthias Ringwald                         if (trigger_pairing){
13943deb3ec6SMatthias Ringwald                             sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
1395d4af1595SMatthias Ringwald                             break;
13963deb3ec6SMatthias Ringwald                         }
139742134bc6SMatthias Ringwald #endif
1398298ab52bSMatthias Ringwald                     }
13993deb3ec6SMatthias Ringwald                     break;
14003deb3ec6SMatthias Ringwald                 case ADDRESS_RESOLUTION_FAILED:
14013deb3ec6SMatthias Ringwald                     sm_connection->sm_irk_lookup_state = IRK_LOOKUP_FAILED;
1402f688bdb8SMatthias Ringwald                     if (IS_RESPONDER(sm_connection->sm_role)) {
14037af5dcd5SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
14046c39055aSMatthias Ringwald                         // LTK request received before, IRK required -> negative LTK reply
14056c39055aSMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK){
14066c39055aSMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
14076c39055aSMatthias Ringwald                         }
1408434260a1SMatthias Ringwald                         // Pairing request before, continue
1409434260a1SMatthias Ringwald                         if (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK){
1410434260a1SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
1411434260a1SMatthias Ringwald                             break;
1412434260a1SMatthias Ringwald                         }
14137af5dcd5SMatthias Ringwald                         // send security request if requested
1414728f6757SMatthias Ringwald                         bool trigger_security_request = sm_connection->sm_pairing_requested || sm_slave_request_security;
14155f3874afSMatthias Ringwald                         sm_connection->sm_pairing_requested = false;
14167af5dcd5SMatthias Ringwald                         if (trigger_security_request){
14177af5dcd5SMatthias Ringwald                             sm_connection->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
14187af5dcd5SMatthias Ringwald                             sm_pairing_started(sm_connection);
14197af5dcd5SMatthias Ringwald                         }
14206c39055aSMatthias Ringwald                         break;
14217af5dcd5SMatthias Ringwald #endif
14226c39055aSMatthias Ringwald                     }
142342134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
14245f3874afSMatthias Ringwald                     if ((sm_connection->sm_pairing_requested == false) && (sm_connection->sm_security_request_received == false)) break;
14250dcaa15fSMatthias Ringwald                     sm_connection->sm_security_request_received = false;
14265f3874afSMatthias Ringwald                     sm_connection->sm_pairing_requested = false;
14273deb3ec6SMatthias Ringwald                     sm_connection->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
142842134bc6SMatthias Ringwald #endif
14293deb3ec6SMatthias Ringwald                     break;
14307bbeb3adSMilanka Ringwald 
14317bbeb3adSMilanka Ringwald                 default:
14327bbeb3adSMilanka Ringwald                     btstack_assert(false);
14337bbeb3adSMilanka Ringwald                     break;
14343deb3ec6SMatthias Ringwald             }
14353deb3ec6SMatthias Ringwald             break;
14363deb3ec6SMatthias Ringwald         default:
14373deb3ec6SMatthias Ringwald             break;
14383deb3ec6SMatthias Ringwald     }
14393deb3ec6SMatthias Ringwald 
14403deb3ec6SMatthias Ringwald     switch (event){
1441a66b030fSMatthias Ringwald         case ADDRESS_RESOLUTION_SUCCEEDED:
1442711e6c80SMatthias Ringwald             sm_notify_client_index(SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED, con_handle, sm_address_resolution_addr_type, sm_address_resolution_address, matched_device_id);
14433deb3ec6SMatthias Ringwald             break;
14443deb3ec6SMatthias Ringwald         case ADDRESS_RESOLUTION_FAILED:
1445711e6c80SMatthias Ringwald             sm_notify_client_base(SM_EVENT_IDENTITY_RESOLVING_FAILED, con_handle, sm_address_resolution_addr_type, sm_address_resolution_address);
14463deb3ec6SMatthias Ringwald             break;
14477bbeb3adSMilanka Ringwald         default:
14487bbeb3adSMilanka Ringwald             btstack_assert(false);
14497bbeb3adSMilanka Ringwald             break;
14503deb3ec6SMatthias Ringwald     }
14513deb3ec6SMatthias Ringwald }
14523deb3ec6SMatthias Ringwald 
145355f09f49SMatthias Ringwald static void sm_store_bonding_information(sm_connection_t * sm_conn){
14543deb3ec6SMatthias Ringwald     int le_db_index = -1;
14553deb3ec6SMatthias Ringwald 
14563deb3ec6SMatthias Ringwald     // lookup device based on IRK
1457f688bdb8SMatthias Ringwald     if ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
14583deb3ec6SMatthias Ringwald         int i;
1459092ec58eSMatthias Ringwald         for (i=0; i < le_device_db_max_count(); i++){
14603deb3ec6SMatthias Ringwald             sm_key_t irk;
14613deb3ec6SMatthias Ringwald             bd_addr_t address;
1462c7e2c1a5SMatthias Ringwald             int address_type = BD_ADDR_TYPE_UNKNOWN;
14633deb3ec6SMatthias Ringwald             le_device_db_info(i, &address_type, address, irk);
1464adf5eaa9SMatthias Ringwald             // skip unused entries
1465c7e2c1a5SMatthias Ringwald             if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
146611d10bdaSMatthias Ringwald             // compare Identity Address
146711d10bdaSMatthias Ringwald             if (memcmp(address, setup->sm_peer_address, 6) != 0) continue;
146811d10bdaSMatthias Ringwald             // compare Identity Resolving Key
1469c7e2c1a5SMatthias Ringwald             if (memcmp(irk, setup->sm_peer_irk, 16) != 0) continue;
1470c7e2c1a5SMatthias Ringwald 
14713deb3ec6SMatthias Ringwald             log_info("sm: device found for IRK, updating");
14723deb3ec6SMatthias Ringwald             le_db_index = i;
14733deb3ec6SMatthias Ringwald             break;
14743deb3ec6SMatthias Ringwald         }
1475c7e2c1a5SMatthias Ringwald     } else {
1476c7e2c1a5SMatthias Ringwald         // assert IRK is set to zero
1477c7e2c1a5SMatthias Ringwald         memset(setup->sm_peer_irk, 0, 16);
14783deb3ec6SMatthias Ringwald     }
14793deb3ec6SMatthias Ringwald 
14803deb3ec6SMatthias Ringwald     // if not found, lookup via public address if possible
14813deb3ec6SMatthias Ringwald     log_info("sm peer addr type %u, peer addres %s", setup->sm_peer_addr_type, bd_addr_to_str(setup->sm_peer_address));
1482c1ab6cc1SMatthias Ringwald     if ((le_db_index < 0) && (setup->sm_peer_addr_type == BD_ADDR_TYPE_LE_PUBLIC)){
14833deb3ec6SMatthias Ringwald         int i;
1484092ec58eSMatthias Ringwald         for (i=0; i < le_device_db_max_count(); i++){
14853deb3ec6SMatthias Ringwald             bd_addr_t address;
1486adf5eaa9SMatthias Ringwald             int address_type = BD_ADDR_TYPE_UNKNOWN;
14873deb3ec6SMatthias Ringwald             le_device_db_info(i, &address_type, address, NULL);
1488adf5eaa9SMatthias Ringwald             // skip unused entries
1489adf5eaa9SMatthias Ringwald             if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
14903deb3ec6SMatthias Ringwald             log_info("device %u, sm peer addr type %u, peer addres %s", i, address_type, bd_addr_to_str(address));
14915df9dc78SMatthias Ringwald             if ((address_type == BD_ADDR_TYPE_LE_PUBLIC) && (memcmp(address, setup->sm_peer_address, 6) == 0)){
14923deb3ec6SMatthias Ringwald                 log_info("sm: device found for public address, updating");
14933deb3ec6SMatthias Ringwald                 le_db_index = i;
14943deb3ec6SMatthias Ringwald                 break;
14953deb3ec6SMatthias Ringwald             }
14963deb3ec6SMatthias Ringwald         }
14973deb3ec6SMatthias Ringwald     }
14983deb3ec6SMatthias Ringwald 
14993deb3ec6SMatthias Ringwald     // if not found, add to db
150002b02cffSMatthias Ringwald     bool new_to_le_device_db = false;
15013deb3ec6SMatthias Ringwald     if (le_db_index < 0) {
15023deb3ec6SMatthias Ringwald         le_db_index = le_device_db_add(setup->sm_peer_addr_type, setup->sm_peer_address, setup->sm_peer_irk);
150302b02cffSMatthias Ringwald         new_to_le_device_db = true;
15043deb3ec6SMatthias Ringwald     }
15053deb3ec6SMatthias Ringwald 
15063deb3ec6SMatthias Ringwald     if (le_db_index >= 0){
15073deb3ec6SMatthias Ringwald 
150802b02cffSMatthias Ringwald #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
150902b02cffSMatthias Ringwald         if (!new_to_le_device_db){
151002b02cffSMatthias Ringwald             hci_remove_le_device_db_entry_from_resolving_list(le_db_index);
151102b02cffSMatthias Ringwald         }
151202b02cffSMatthias Ringwald         hci_load_le_device_db_entry_into_resolving_list(le_db_index);
151302b02cffSMatthias Ringwald #else
151402b02cffSMatthias Ringwald         UNUSED(new_to_le_device_db);
151502b02cffSMatthias Ringwald #endif
151602b02cffSMatthias Ringwald 
151748163929SMatthias 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);
1518e1086030SMatthias Ringwald         sm_conn->sm_irk_lookup_state = IRK_LOOKUP_SUCCEEDED;
15197710ebd2SMatthias Ringwald         sm_conn->sm_le_db_index = le_db_index;
152048163929SMatthias Ringwald 
1521eda85fbfSMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
15223deb3ec6SMatthias Ringwald         // store local CSRK
1523715a43d1SMatthias Ringwald         setup->sm_le_device_index = le_db_index;
1524715a43d1SMatthias Ringwald         if ((setup->sm_key_distribution_sent_set) & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
15253deb3ec6SMatthias Ringwald             log_info("sm: store local CSRK");
15263deb3ec6SMatthias Ringwald             le_device_db_local_csrk_set(le_db_index, setup->sm_local_csrk);
15273deb3ec6SMatthias Ringwald             le_device_db_local_counter_set(le_db_index, 0);
15283deb3ec6SMatthias Ringwald         }
15293deb3ec6SMatthias Ringwald 
15303deb3ec6SMatthias Ringwald         // store remote CSRK
15313deb3ec6SMatthias Ringwald         if (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION){
15323deb3ec6SMatthias Ringwald             log_info("sm: store remote CSRK");
15333deb3ec6SMatthias Ringwald             le_device_db_remote_csrk_set(le_db_index, setup->sm_peer_csrk);
15343deb3ec6SMatthias Ringwald             le_device_db_remote_counter_set(le_db_index, 0);
15353deb3ec6SMatthias Ringwald         }
1536eda85fbfSMatthias Ringwald #endif
153778f44163SMatthias Ringwald         // store encryption information for secure connections: LTK generated by ECDH
153878f44163SMatthias Ringwald         if (setup->sm_use_secure_connections){
1539e6343eb6SMatthias Ringwald             log_info("sm: store SC LTK (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
154078f44163SMatthias Ringwald             uint8_t zero_rand[8];
154178f44163SMatthias Ringwald             memset(zero_rand, 0, 8);
154278f44163SMatthias Ringwald             le_device_db_encryption_set(le_db_index, 0, zero_rand, setup->sm_ltk, sm_conn->sm_actual_encryption_key_size,
15433dc3a67dSMatthias Ringwald                                         sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 1);
154478f44163SMatthias Ringwald         }
154578f44163SMatthias Ringwald 
1546e6343eb6SMatthias Ringwald         // store encryption information for legacy pairing: peer LTK, EDIV, RAND
154778f44163SMatthias Ringwald         else if ( (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION)
154878f44163SMatthias Ringwald         && (setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_MASTER_IDENTIFICATION )){
1549e6343eb6SMatthias Ringwald             log_info("sm: set encryption information (key size %u, authenticated %u)", sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated);
15503deb3ec6SMatthias Ringwald             le_device_db_encryption_set(le_db_index, setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
15513dc3a67dSMatthias Ringwald                                         sm_conn->sm_actual_encryption_key_size, sm_conn->sm_connection_authenticated, sm_conn->sm_connection_authorization_state == AUTHORIZATION_GRANTED, 0);
155278f44163SMatthias Ringwald 
15533deb3ec6SMatthias Ringwald         }
15543deb3ec6SMatthias Ringwald     }
155555f09f49SMatthias Ringwald }
155655f09f49SMatthias Ringwald 
15578980298aSMatthias Ringwald static void sm_pairing_error(sm_connection_t * sm_conn, uint8_t reason){
15588980298aSMatthias Ringwald     sm_conn->sm_pairing_failed_reason = reason;
15598980298aSMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_SEND_PAIRING_FAILED;
15608980298aSMatthias Ringwald }
15618980298aSMatthias Ringwald 
156222cb578bSMatthias Ringwald static int sm_le_device_db_index_lookup(bd_addr_type_t address_type, bd_addr_t address){
15631a55487aSMatthias Ringwald     int i;
15641a55487aSMatthias Ringwald     for (i=0; i < le_device_db_max_count(); i++){
156522cb578bSMatthias Ringwald         bd_addr_t db_address;
156622cb578bSMatthias Ringwald         int db_address_type = BD_ADDR_TYPE_UNKNOWN;
156722cb578bSMatthias Ringwald         le_device_db_info(i, &db_address_type, db_address, NULL);
15681a55487aSMatthias Ringwald         // skip unused entries
15691a55487aSMatthias Ringwald         if (address_type == BD_ADDR_TYPE_UNKNOWN) continue;
15703548b7cbSDirk Helbig         if ((address_type == (unsigned int)db_address_type) && (memcmp(address, db_address, 6) == 0)){
15711a55487aSMatthias Ringwald             return i;
15721a55487aSMatthias Ringwald         }
15731a55487aSMatthias Ringwald     }
15741a55487aSMatthias Ringwald     return -1;
15751a55487aSMatthias Ringwald }
15761a55487aSMatthias Ringwald 
15772e08b70bSMatthias Ringwald static void sm_remove_le_device_db_entry(uint16_t i) {
15782e08b70bSMatthias Ringwald     le_device_db_remove(i);
1579672dc582SMatthias Ringwald #ifdef ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
1580672dc582SMatthias Ringwald     // to remove an entry from the resolving list requires its identity address, which was already deleted
1581672dc582SMatthias Ringwald     // fully reload resolving list instead
1582672dc582SMatthias Ringwald     gap_load_resolving_list_from_le_device_db();
1583672dc582SMatthias Ringwald #endif
15842e08b70bSMatthias Ringwald }
15852e08b70bSMatthias Ringwald 
15868980298aSMatthias Ringwald static uint8_t sm_key_distribution_validate_received(sm_connection_t * sm_conn){
15871a55487aSMatthias Ringwald     // if identity is provided, abort if we have bonding with same address but different irk
1588f688bdb8SMatthias Ringwald     if ((setup->sm_key_distribution_received_set & SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
158922cb578bSMatthias Ringwald         int index = sm_le_device_db_index_lookup(BD_ADDR_TYPE_LE_PUBLIC, setup->sm_peer_address);
15901a55487aSMatthias Ringwald         if (index >= 0){
15911a55487aSMatthias Ringwald             sm_key_t irk;
15921a55487aSMatthias Ringwald             le_device_db_info(index, NULL, NULL, irk);
15931a55487aSMatthias Ringwald             if (memcmp(irk, setup->sm_peer_irk, 16) != 0){
15941a55487aSMatthias Ringwald                 // IRK doesn't match, delete bonding information
15951a55487aSMatthias 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);
15969202d845SMatthias Ringwald                 sm_remove_le_device_db_entry(index);
15971a55487aSMatthias Ringwald             }
15981a55487aSMatthias Ringwald         }
15991a55487aSMatthias Ringwald     }
16008980298aSMatthias Ringwald     return 0;
16018980298aSMatthias Ringwald }
16028980298aSMatthias Ringwald 
160355f09f49SMatthias Ringwald static void sm_key_distribution_handle_all_received(sm_connection_t * sm_conn){
160455f09f49SMatthias Ringwald 
16058980298aSMatthias Ringwald     // abort pairing if received keys are not valid
16068980298aSMatthias Ringwald     uint8_t reason = sm_key_distribution_validate_received(sm_conn);
16078980298aSMatthias Ringwald     if (reason != 0){
16088980298aSMatthias Ringwald         sm_pairing_error(sm_conn, reason);
16098980298aSMatthias Ringwald         return;
16108980298aSMatthias Ringwald     }
16118980298aSMatthias Ringwald 
161255f09f49SMatthias Ringwald     // only store pairing information if both sides are bondable, i.e., the bonadble flag is set
161355f09f49SMatthias Ringwald     bool bonding_enabled = (sm_pairing_packet_get_auth_req(setup->sm_m_preq)
161455f09f49SMatthias Ringwald                             & sm_pairing_packet_get_auth_req(setup->sm_s_pres)
161555f09f49SMatthias Ringwald                             & SM_AUTHREQ_BONDING ) != 0u;
161655f09f49SMatthias Ringwald 
161755f09f49SMatthias Ringwald     if (bonding_enabled){
161855f09f49SMatthias Ringwald         sm_store_bonding_information(sm_conn);
161927ef8bc8SMatthias Ringwald     } else {
162027ef8bc8SMatthias Ringwald         log_info("Ignoring received keys, bonding not enabled");
162127ef8bc8SMatthias Ringwald     }
16223deb3ec6SMatthias Ringwald }
16233deb3ec6SMatthias Ringwald 
1624688a08f9SMatthias Ringwald static inline void sm_pdu_received_in_wrong_state(sm_connection_t * sm_conn){
1625688a08f9SMatthias Ringwald     sm_pairing_error(sm_conn, SM_REASON_UNSPECIFIED_REASON);
1626688a08f9SMatthias Ringwald }
1627688a08f9SMatthias Ringwald 
16289af0f475SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
1629688a08f9SMatthias Ringwald 
1630dc300847SMatthias Ringwald static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn);
16311d80f1e6SMatthias Ringwald static bool sm_passkey_used(stk_generation_method_t method);
16321d80f1e6SMatthias Ringwald static bool sm_just_works_or_numeric_comparison(stk_generation_method_t method);
1633dc300847SMatthias Ringwald 
1634b35a3de2SMatthias Ringwald static void sm_sc_start_calculating_local_confirm(sm_connection_t * sm_conn){
1635b90c4e75SMatthias Ringwald     if (setup->sm_stk_generation_method == OOB){
16361f9d84e9SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CONFIRMATION;
1637b90c4e75SMatthias Ringwald     } else {
1638b90c4e75SMatthias 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);
1639b35a3de2SMatthias Ringwald     }
1640b35a3de2SMatthias Ringwald }
1641b35a3de2SMatthias Ringwald 
1642688a08f9SMatthias Ringwald static void sm_sc_state_after_receiving_random(sm_connection_t * sm_conn){
164342134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1644688a08f9SMatthias Ringwald         // Responder
16454acf7b7bSMatthias Ringwald         if (setup->sm_stk_generation_method == OOB){
16464acf7b7bSMatthias Ringwald             // generate Nb
16474acf7b7bSMatthias Ringwald             log_info("Generate Nb");
16486ca80073SMatthias 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);
16494acf7b7bSMatthias Ringwald         } else {
1650688a08f9SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
16514acf7b7bSMatthias Ringwald         }
1652688a08f9SMatthias Ringwald     } else {
1653688a08f9SMatthias Ringwald         // Initiator role
1654688a08f9SMatthias Ringwald         switch (setup->sm_stk_generation_method){
1655688a08f9SMatthias Ringwald             case JUST_WORKS:
1656dc300847SMatthias Ringwald                 sm_sc_prepare_dhkey_check(sm_conn);
1657688a08f9SMatthias Ringwald                 break;
1658688a08f9SMatthias Ringwald 
165947fb4255SMatthias Ringwald             case NUMERIC_COMPARISON:
1660bd57ffebSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_G2;
1661688a08f9SMatthias Ringwald                 break;
1662688a08f9SMatthias Ringwald             case PK_INIT_INPUT:
1663688a08f9SMatthias Ringwald             case PK_RESP_INPUT:
166447fb4255SMatthias Ringwald             case PK_BOTH_INPUT:
16654ea43905SMatthias Ringwald                 if (setup->sm_passkey_bit < 20u) {
1666b35a3de2SMatthias Ringwald                     sm_sc_start_calculating_local_confirm(sm_conn);
1667688a08f9SMatthias Ringwald                 } else {
1668dc300847SMatthias Ringwald                     sm_sc_prepare_dhkey_check(sm_conn);
1669688a08f9SMatthias Ringwald                 }
1670688a08f9SMatthias Ringwald                 break;
1671688a08f9SMatthias Ringwald             case OOB:
167265a9a04eSMatthias Ringwald                 sm_sc_prepare_dhkey_check(sm_conn);
1673688a08f9SMatthias Ringwald                 break;
16747bbeb3adSMilanka Ringwald             default:
16757bbeb3adSMilanka Ringwald                 btstack_assert(false);
16767bbeb3adSMilanka Ringwald                 break;
1677688a08f9SMatthias Ringwald         }
1678688a08f9SMatthias Ringwald     }
1679688a08f9SMatthias Ringwald }
1680688a08f9SMatthias Ringwald 
1681aec94140SMatthias Ringwald static void sm_sc_cmac_done(uint8_t * hash){
1682688a08f9SMatthias Ringwald     log_info("sm_sc_cmac_done: ");
1683688a08f9SMatthias Ringwald     log_info_hexdump(hash, 16);
1684688a08f9SMatthias Ringwald 
1685c59d0c92SMatthias Ringwald     if (sm_sc_oob_state == SM_SC_OOB_W4_CONFIRM){
1686c59d0c92SMatthias Ringwald         sm_sc_oob_state = SM_SC_OOB_IDLE;
1687a680ba6bSMatthias Ringwald         (*sm_sc_oob_callback)(hash, sm_sc_oob_random);
1688c59d0c92SMatthias Ringwald         return;
1689c59d0c92SMatthias Ringwald     }
1690c59d0c92SMatthias Ringwald 
1691bd57ffebSMatthias Ringwald     sm_connection_t * sm_conn = sm_cmac_connection;
1692bd57ffebSMatthias Ringwald     sm_cmac_connection = NULL;
16936857ad8fSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
16942bacf595SMatthias Ringwald     link_key_type_t link_key_type;
1695b4f65634SMatthias Ringwald #endif
1696bd57ffebSMatthias Ringwald 
1697bd57ffebSMatthias Ringwald     switch (sm_conn->sm_engine_state){
1698aec94140SMatthias Ringwald         case SM_SC_W4_CMAC_FOR_CONFIRMATION:
16996535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_confirm, hash, 16);
1700bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_CONFIRMATION;
1701aec94140SMatthias Ringwald             break;
1702688a08f9SMatthias Ringwald         case SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION:
1703688a08f9SMatthias Ringwald             // check
1704688a08f9SMatthias Ringwald             if (0 != memcmp(hash, setup->sm_peer_confirm, 16)){
1705bd57ffebSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CONFIRM_VALUE_FAILED);
1706688a08f9SMatthias Ringwald                 break;
1707688a08f9SMatthias Ringwald             }
1708bd57ffebSMatthias Ringwald             sm_sc_state_after_receiving_random(sm_conn);
1709688a08f9SMatthias Ringwald             break;
1710901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_G2: {
1711901c000fSMatthias Ringwald             uint32_t vab = big_endian_read_32(hash, 12) % 1000000;
1712901c000fSMatthias Ringwald             big_endian_store_32(setup->sm_tk, 12, vab);
1713901c000fSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
1714901c000fSMatthias Ringwald             sm_trigger_user_response(sm_conn);
1715019005a0SMatthias Ringwald             break;
1716019005a0SMatthias Ringwald         }
17170346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_SALT:
17186535961aSMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
1719bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_MACKEY;
17200346c37cSMatthias Ringwald             break;
17210346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_MACKEY:
17226535961aSMatthias Ringwald             (void)memcpy(setup->sm_mackey, hash, 16);
1723bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_LTK;
17240346c37cSMatthias Ringwald             break;
17250346c37cSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_LTK:
1726b18300a6SMatthias Ringwald             // truncate sm_ltk, but keep full LTK for cross-transport key derivation in sm_local_ltk
1727b18300a6SMatthias Ringwald             // Errata Service Release to the Bluetooth Specification: ESR09
1728b18300a6SMatthias Ringwald             //   E6405 – Cross transport key derivation from a key of size less than 128 bits
1729b18300a6SMatthias Ringwald             //   Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
17306535961aSMatthias Ringwald             (void)memcpy(setup->sm_ltk, hash, 16);
17316535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_ltk, hash, 16);
1732893e9333SMatthias Ringwald             sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
1733bd57ffebSMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK;
1734019005a0SMatthias Ringwald             break;
1735901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
17366535961aSMatthias Ringwald             (void)memcpy(setup->sm_local_dhkey_check, hash, 16);
173742134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1738901c000fSMatthias Ringwald                 // responder
1739f688bdb8SMatthias Ringwald                 if ((setup->sm_state_vars & SM_STATE_VAR_DHKEY_COMMAND_RECEIVED) != 0u){
1740901c000fSMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
1741901c000fSMatthias Ringwald                 } else {
1742901c000fSMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
1743901c000fSMatthias Ringwald                 }
1744901c000fSMatthias Ringwald             } else {
1745901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
1746901c000fSMatthias Ringwald             }
1747901c000fSMatthias Ringwald             break;
1748901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
1749901c000fSMatthias Ringwald             if (0 != memcmp(hash, setup->sm_peer_dhkey_check, 16) ){
1750901c000fSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
1751aec94140SMatthias Ringwald                 break;
1752aec94140SMatthias Ringwald             }
175342134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
1754901c000fSMatthias Ringwald                 // responder
1755901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_DHKEY_CHECK_COMMAND;
1756901c000fSMatthias Ringwald             } else {
1757901c000fSMatthias Ringwald                 // initiator
1758901c000fSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
1759bd57ffebSMatthias Ringwald             }
1760901c000fSMatthias Ringwald             break;
17616857ad8fSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
176257132f12SMatthias Ringwald         case SM_SC_W4_CALCULATE_ILK:
17636535961aSMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
176457132f12SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY;
17652bacf595SMatthias Ringwald             break;
176657132f12SMatthias Ringwald         case SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY:
17672bacf595SMatthias Ringwald             reverse_128(hash, setup->sm_t);
17682bacf595SMatthias Ringwald             link_key_type = sm_conn->sm_connection_authenticated ?
17692bacf595SMatthias Ringwald                 AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256 : UNAUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
17708974e43fSMatthias Ringwald             log_info("Derived classic link key from LE using h6, type %u", (int) link_key_type);
177155160b1cSMatthias Ringwald 			gap_store_link_key_for_bd_addr(setup->sm_peer_address, setup->sm_t, link_key_type);
17728974e43fSMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
17732bacf595SMatthias Ringwald                 sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
17742bacf595SMatthias Ringwald             } else {
17752bacf595SMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
17762bacf595SMatthias Ringwald             }
17770ccf6c9cSMatthias Ringwald             sm_pairing_complete(sm_conn, ERROR_CODE_SUCCESS, 0);
17782bacf595SMatthias Ringwald             sm_done_for_handle(sm_conn->sm_handle);
17792bacf595SMatthias Ringwald             break;
1780e0a03c85SMatthias Ringwald         case SM_BR_EDR_W4_CALCULATE_ILK:
1781e0a03c85SMatthias Ringwald             (void)memcpy(setup->sm_t, hash, 16);
1782e0a03c85SMatthias Ringwald             sm_conn->sm_engine_state = SM_BR_EDR_W2_CALCULATE_LE_LTK;
1783e0a03c85SMatthias Ringwald             break;
1784e0a03c85SMatthias Ringwald         case SM_BR_EDR_W4_CALCULATE_LE_LTK:
1785e0a03c85SMatthias Ringwald             log_info("Derived LE LTK from BR/EDR Link Key");
1786e0a03c85SMatthias Ringwald             log_info_key("Link Key", hash);
1787e0a03c85SMatthias Ringwald             (void)memcpy(setup->sm_ltk, hash, 16);
1788e0a03c85SMatthias Ringwald             sm_truncate_key(setup->sm_ltk, sm_conn->sm_actual_encryption_key_size);
1789e0a03c85SMatthias Ringwald             sm_conn->sm_connection_authenticated = setup->sm_link_key_type == AUTHENTICATED_COMBINATION_KEY_GENERATED_FROM_P256;
1790e0a03c85SMatthias Ringwald             sm_store_bonding_information(sm_conn);
1791c18be159SMatthias Ringwald             sm_done_for_handle(sm_conn->sm_handle);
1792e0a03c85SMatthias Ringwald             break;
1793bdb14b0eSMatthias Ringwald #endif
1794bd57ffebSMatthias Ringwald         default:
1795bd57ffebSMatthias Ringwald             log_error("sm_sc_cmac_done in state %u", sm_conn->sm_engine_state);
1796bd57ffebSMatthias Ringwald             break;
1797bd57ffebSMatthias Ringwald     }
179870b44dd4SMatthias Ringwald     sm_trigger_run();
1799aec94140SMatthias Ringwald }
1800aec94140SMatthias Ringwald 
1801688a08f9SMatthias 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){
1802dc300847SMatthias Ringwald     const uint16_t message_len = 65;
1803aec94140SMatthias Ringwald     sm_cmac_connection = sm_conn;
18046535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, u, 32);
18056535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, v, 32);
1806aec94140SMatthias Ringwald     sm_cmac_sc_buffer[64] = z;
1807aec94140SMatthias Ringwald     log_info("f4 key");
1808aec94140SMatthias Ringwald     log_info_hexdump(x, 16);
1809aec94140SMatthias Ringwald     log_info("f4 message");
1810dc300847SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1811d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(x, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1812aec94140SMatthias Ringwald }
1813aec94140SMatthias Ringwald 
18140346c37cSMatthias Ringwald static const uint8_t f5_key_id[] = { 0x62, 0x74, 0x6c, 0x65 };
18150346c37cSMatthias Ringwald static const uint8_t f5_length[] = { 0x01, 0x00};
18160346c37cSMatthias Ringwald 
18170346c37cSMatthias Ringwald static void f5_calculate_salt(sm_connection_t * sm_conn){
18188334d3d8SMatthias Ringwald 
18198334d3d8SMatthias Ringwald     static const sm_key_t f5_salt = { 0x6C ,0x88, 0x83, 0x91, 0xAA, 0xF5, 0xA5, 0x38, 0x60, 0x37, 0x0B, 0xDB, 0x5A, 0x60, 0x83, 0xBE};
18208334d3d8SMatthias Ringwald 
182140c5d850SMatthias Ringwald     log_info("f5_calculate_salt");
18220346c37cSMatthias Ringwald     // calculate salt for f5
18230346c37cSMatthias Ringwald     const uint16_t message_len = 32;
18240346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18256535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, setup->sm_dhkey, message_len);
1826d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(f5_salt, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18270346c37cSMatthias Ringwald }
18280346c37cSMatthias Ringwald 
18290346c37cSMatthias 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){
18300346c37cSMatthias Ringwald     const uint16_t message_len = 53;
18310346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18320346c37cSMatthias Ringwald 
18330346c37cSMatthias Ringwald     // f5(W, N1, N2, A1, A2) = AES-CMACT (Counter = 0 || keyID || N1 || N2|| A1|| A2 || Length = 256) -- this is the MacKey
18340346c37cSMatthias Ringwald     sm_cmac_sc_buffer[0] = 0;
18356535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 01, f5_key_id, 4);
18366535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 05, n1, 16);
18376535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 21, n2, 16);
18386535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 37, a1, 7);
18396535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 44, a2, 7);
18406535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 51, f5_length, 2);
18410346c37cSMatthias Ringwald     log_info("f5 key");
18420346c37cSMatthias Ringwald     log_info_hexdump(t, 16);
18430346c37cSMatthias Ringwald     log_info("f5 message for MacKey");
18440346c37cSMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1845d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(t, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18460346c37cSMatthias Ringwald }
18470346c37cSMatthias Ringwald 
18480346c37cSMatthias Ringwald static void f5_calculate_mackey(sm_connection_t * sm_conn){
18490346c37cSMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
18500346c37cSMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
18510346c37cSMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
18526535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
18536535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
185442134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
18550346c37cSMatthias Ringwald         // responder
18560346c37cSMatthias Ringwald         f5_mackkey(sm_conn, setup->sm_t, setup->sm_peer_nonce, setup->sm_local_nonce, bd_addr_master, bd_addr_slave);
18570346c37cSMatthias Ringwald     } else {
18580346c37cSMatthias Ringwald         // initiator
18590346c37cSMatthias Ringwald         f5_mackkey(sm_conn, setup->sm_t, setup->sm_local_nonce, setup->sm_peer_nonce, bd_addr_master, bd_addr_slave);
18600346c37cSMatthias Ringwald     }
18610346c37cSMatthias Ringwald }
18620346c37cSMatthias Ringwald 
18630346c37cSMatthias Ringwald // note: must be called right after f5_mackey, as sm_cmac_buffer[1..52] will be reused
18640346c37cSMatthias Ringwald static inline void f5_ltk(sm_connection_t * sm_conn, sm_key_t t){
18650346c37cSMatthias Ringwald     const uint16_t message_len = 53;
18660346c37cSMatthias Ringwald     sm_cmac_connection = sm_conn;
18670346c37cSMatthias Ringwald     sm_cmac_sc_buffer[0] = 1;
18680346c37cSMatthias Ringwald     // 1..52 setup before
18690346c37cSMatthias Ringwald     log_info("f5 key");
18700346c37cSMatthias Ringwald     log_info_hexdump(t, 16);
18710346c37cSMatthias Ringwald     log_info("f5 message for LTK");
18720346c37cSMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1873d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(t, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
18740346c37cSMatthias Ringwald }
1875f92edc8eSMatthias Ringwald 
18760346c37cSMatthias Ringwald static void f5_calculate_ltk(sm_connection_t * sm_conn){
18770346c37cSMatthias Ringwald     f5_ltk(sm_conn, setup->sm_t);
18780346c37cSMatthias Ringwald }
18790346c37cSMatthias Ringwald 
188031f061fbSMatthias 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){
18816535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, n1, 16);
18826535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 16, n2, 16);
18836535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, r, 16);
18846535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 48, io_cap, 3);
18856535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 51, a1, 7);
18866535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 58, a2, 7);
188731f061fbSMatthias Ringwald }
188831f061fbSMatthias Ringwald 
188931f061fbSMatthias Ringwald static void f6_engine(sm_connection_t * sm_conn, const sm_key_t w){
189031f061fbSMatthias Ringwald     const uint16_t message_len = 65;
189131f061fbSMatthias Ringwald     sm_cmac_connection = sm_conn;
1892dc300847SMatthias Ringwald     log_info("f6 key");
1893dc300847SMatthias Ringwald     log_info_hexdump(w, 16);
1894dc300847SMatthias Ringwald     log_info("f6 message");
1895dc300847SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1896d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(w, 65, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1897dc300847SMatthias Ringwald }
1898dc300847SMatthias Ringwald 
1899f92edc8eSMatthias Ringwald // g2(U, V, X, Y) = AES-CMACX(U || V || Y) mod 2^32
1900f92edc8eSMatthias Ringwald // - U is 256 bits
1901f92edc8eSMatthias Ringwald // - V is 256 bits
1902f92edc8eSMatthias Ringwald // - X is 128 bits
1903f92edc8eSMatthias Ringwald // - Y is 128 bits
1904bd57ffebSMatthias 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){
1905bd57ffebSMatthias Ringwald     const uint16_t message_len = 80;
1906bd57ffebSMatthias Ringwald     sm_cmac_connection = sm_conn;
19076535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer, u, 32);
19086535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 32, v, 32);
19096535961aSMatthias Ringwald     (void)memcpy(sm_cmac_sc_buffer + 64, y, 16);
1910f92edc8eSMatthias Ringwald     log_info("g2 key");
1911f92edc8eSMatthias Ringwald     log_info_hexdump(x, 16);
1912f92edc8eSMatthias Ringwald     log_info("g2 message");
19132bacf595SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
1914d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(x, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
1915f92edc8eSMatthias Ringwald }
1916f92edc8eSMatthias Ringwald 
1917b35a3de2SMatthias Ringwald static void g2_calculate(sm_connection_t * sm_conn) {
1918f92edc8eSMatthias Ringwald     // calc Va if numeric comparison
191942134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
1920f92edc8eSMatthias Ringwald         // responder
1921fc5bff5fSMatthias Ringwald         g2_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, setup->sm_local_nonce);;
1922f92edc8eSMatthias Ringwald     } else {
1923f92edc8eSMatthias Ringwald         // initiator
1924fc5bff5fSMatthias Ringwald         g2_engine(sm_conn, ec_q, setup->sm_peer_q, setup->sm_local_nonce, setup->sm_peer_nonce);
1925f92edc8eSMatthias Ringwald     }
1926f92edc8eSMatthias Ringwald }
1927f92edc8eSMatthias Ringwald 
1928945888f5SMatthias Ringwald static void sm_sc_calculate_local_confirm(sm_connection_t * sm_conn){
19299af0f475SMatthias Ringwald     uint8_t z = 0;
193040c5d850SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method)){
19319af0f475SMatthias Ringwald         // some form of passkey
19329af0f475SMatthias Ringwald         uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
19334ea43905SMatthias Ringwald         z = 0x80u | ((pk >> setup->sm_passkey_bit) & 1u);
19349af0f475SMatthias Ringwald         setup->sm_passkey_bit++;
19359af0f475SMatthias Ringwald     }
1936fc5bff5fSMatthias Ringwald     f4_engine(sm_conn, ec_q, setup->sm_peer_q, setup->sm_local_nonce, z);
19379af0f475SMatthias Ringwald }
1938688a08f9SMatthias Ringwald 
1939688a08f9SMatthias Ringwald static void sm_sc_calculate_remote_confirm(sm_connection_t * sm_conn){
1940a680ba6bSMatthias Ringwald     // OOB
1941a680ba6bSMatthias Ringwald     if (setup->sm_stk_generation_method == OOB){
19424acf7b7bSMatthias Ringwald         if (IS_RESPONDER(sm_conn->sm_role)){
19434acf7b7bSMatthias Ringwald             f4_engine(sm_conn, setup->sm_peer_q, setup->sm_peer_q, setup->sm_ra, 0);
19444acf7b7bSMatthias Ringwald         } else {
19454acf7b7bSMatthias Ringwald             f4_engine(sm_conn, setup->sm_peer_q, setup->sm_peer_q, setup->sm_rb, 0);
19464acf7b7bSMatthias Ringwald         }
1947a680ba6bSMatthias Ringwald         return;
1948a680ba6bSMatthias Ringwald     }
1949a680ba6bSMatthias Ringwald 
1950688a08f9SMatthias Ringwald     uint8_t z = 0;
195140c5d850SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method)){
1952688a08f9SMatthias Ringwald         // some form of passkey
1953688a08f9SMatthias Ringwald         uint32_t pk = big_endian_read_32(setup->sm_tk, 12);
1954688a08f9SMatthias Ringwald         // sm_passkey_bit was increased before sending confirm value
19554ea43905SMatthias Ringwald         z = 0x80u | ((pk >> (setup->sm_passkey_bit-1u)) & 1u);
1956688a08f9SMatthias Ringwald     }
1957fc5bff5fSMatthias Ringwald     f4_engine(sm_conn, setup->sm_peer_q, ec_q, setup->sm_peer_nonce, z);
1958688a08f9SMatthias Ringwald }
1959688a08f9SMatthias Ringwald 
19600346c37cSMatthias Ringwald static void sm_sc_prepare_dhkey_check(sm_connection_t * sm_conn){
1961f688bdb8SMatthias Ringwald     log_info("sm_sc_prepare_dhkey_check, DHKEY calculated %u", (setup->sm_state_vars & SM_STATE_VAR_DHKEY_CALCULATED) != 0 ? 1 : 0);
19623cf37b8cSMatthias Ringwald 
1963f688bdb8SMatthias Ringwald     if ((setup->sm_state_vars & SM_STATE_VAR_DHKEY_CALCULATED) != 0u){
19643cf37b8cSMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
19653cf37b8cSMatthias Ringwald     } else {
19663cf37b8cSMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W4_CALCULATE_DHKEY;
19673cf37b8cSMatthias Ringwald     }
1968d1a1f6a4SMatthias Ringwald }
19693cf37b8cSMatthias Ringwald 
1970d1a1f6a4SMatthias Ringwald static void sm_sc_dhkey_calculated(void * arg){
1971f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
1972f3582630SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
1973f3582630SMatthias Ringwald     if (sm_conn == NULL) return;
1974f3582630SMatthias Ringwald 
19751c34405fSMatthias Ringwald     // check for invalid public key detected by Controller
19761c34405fSMatthias Ringwald     if (sm_is_ff(setup->sm_dhkey, 32)){
19771c34405fSMatthias Ringwald         log_info("sm: peer public key invalid");
19781c34405fSMatthias Ringwald         sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
19791c34405fSMatthias Ringwald         return;
19801c34405fSMatthias Ringwald     }
19811c34405fSMatthias Ringwald 
1982d1a1f6a4SMatthias Ringwald     log_info("dhkey");
1983d1a1f6a4SMatthias Ringwald     log_info_hexdump(&setup->sm_dhkey[0], 32);
1984d1a1f6a4SMatthias Ringwald     setup->sm_state_vars |= SM_STATE_VAR_DHKEY_CALCULATED;
1985d1a1f6a4SMatthias Ringwald     // trigger next step
1986d1a1f6a4SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_CALCULATE_DHKEY){
1987d1a1f6a4SMatthias Ringwald         sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F5_SALT;
1988d1a1f6a4SMatthias Ringwald     }
198970b44dd4SMatthias Ringwald     sm_trigger_run();
1990dc300847SMatthias Ringwald }
1991dc300847SMatthias Ringwald 
1992dc300847SMatthias Ringwald static void sm_sc_calculate_f6_for_dhkey_check(sm_connection_t * sm_conn){
1993dc300847SMatthias Ringwald     // calculate DHKCheck
1994dc300847SMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
1995dc300847SMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
1996dc300847SMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
19976535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
19986535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
1999dc300847SMatthias Ringwald     uint8_t iocap_a[3];
2000dc300847SMatthias Ringwald     iocap_a[0] = sm_pairing_packet_get_auth_req(setup->sm_m_preq);
2001dc300847SMatthias Ringwald     iocap_a[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq);
2002dc300847SMatthias Ringwald     iocap_a[2] = sm_pairing_packet_get_io_capability(setup->sm_m_preq);
2003dc300847SMatthias Ringwald     uint8_t iocap_b[3];
2004dc300847SMatthias Ringwald     iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
2005dc300847SMatthias Ringwald     iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
2006dc300847SMatthias Ringwald     iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
200742134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
2008dc300847SMatthias Ringwald         // responder
200931f061fbSMatthias Ringwald         f6_setup(setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
201031f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2011dc300847SMatthias Ringwald     } else {
2012dc300847SMatthias Ringwald         // initiator
201331f061fbSMatthias Ringwald         f6_setup( setup->sm_local_nonce, setup->sm_peer_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
201431f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2015dc300847SMatthias Ringwald     }
2016dc300847SMatthias Ringwald }
2017dc300847SMatthias Ringwald 
2018019005a0SMatthias Ringwald static void sm_sc_calculate_f6_to_verify_dhkey_check(sm_connection_t * sm_conn){
2019019005a0SMatthias Ringwald     // validate E = f6()
2020019005a0SMatthias Ringwald     sm_key56_t bd_addr_master, bd_addr_slave;
2021019005a0SMatthias Ringwald     bd_addr_master[0] =  setup->sm_m_addr_type;
2022019005a0SMatthias Ringwald     bd_addr_slave[0]  =  setup->sm_s_addr_type;
20236535961aSMatthias Ringwald     (void)memcpy(&bd_addr_master[1], setup->sm_m_address, 6);
20246535961aSMatthias Ringwald     (void)memcpy(&bd_addr_slave[1], setup->sm_s_address, 6);
2025019005a0SMatthias Ringwald 
2026019005a0SMatthias Ringwald     uint8_t iocap_a[3];
2027019005a0SMatthias Ringwald     iocap_a[0] = sm_pairing_packet_get_auth_req(setup->sm_m_preq);
2028019005a0SMatthias Ringwald     iocap_a[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq);
2029019005a0SMatthias Ringwald     iocap_a[2] = sm_pairing_packet_get_io_capability(setup->sm_m_preq);
2030019005a0SMatthias Ringwald     uint8_t iocap_b[3];
2031019005a0SMatthias Ringwald     iocap_b[0] = sm_pairing_packet_get_auth_req(setup->sm_s_pres);
2032019005a0SMatthias Ringwald     iocap_b[1] = sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres);
2033019005a0SMatthias Ringwald     iocap_b[2] = sm_pairing_packet_get_io_capability(setup->sm_s_pres);
203442134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
2035019005a0SMatthias Ringwald         // responder
203631f061fbSMatthias Ringwald         f6_setup(setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_rb, iocap_a, bd_addr_master, bd_addr_slave);
203731f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2038019005a0SMatthias Ringwald     } else {
2039019005a0SMatthias Ringwald         // initiator
204031f061fbSMatthias Ringwald         f6_setup(setup->sm_peer_nonce, setup->sm_local_nonce, setup->sm_ra, iocap_b, bd_addr_slave, bd_addr_master);
204131f061fbSMatthias Ringwald         f6_engine(sm_conn, setup->sm_mackey);
2042019005a0SMatthias Ringwald     }
2043019005a0SMatthias Ringwald }
20442bacf595SMatthias Ringwald 
204555c62cf5SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
20462bacf595SMatthias Ringwald 
20472bacf595SMatthias Ringwald //
20482bacf595SMatthias Ringwald // Link Key Conversion Function h6
20492bacf595SMatthias Ringwald //
205057132f12SMatthias Ringwald // h6(W, keyID) = AES-CMAC_W(keyID)
20512bacf595SMatthias Ringwald // - W is 128 bits
20522bacf595SMatthias Ringwald // - keyID is 32 bits
20532bacf595SMatthias Ringwald static void h6_engine(sm_connection_t * sm_conn, const sm_key_t w, const uint32_t key_id){
20542bacf595SMatthias Ringwald     const uint16_t message_len = 4;
20552bacf595SMatthias Ringwald     sm_cmac_connection = sm_conn;
20562bacf595SMatthias Ringwald     big_endian_store_32(sm_cmac_sc_buffer, 0, key_id);
20572bacf595SMatthias Ringwald     log_info("h6 key");
20582bacf595SMatthias Ringwald     log_info_hexdump(w, 16);
20592bacf595SMatthias Ringwald     log_info("h6 message");
20602bacf595SMatthias Ringwald     log_info_hexdump(sm_cmac_sc_buffer, message_len);
2061d1a1f6a4SMatthias Ringwald     sm_cmac_message_start(w, message_len, sm_cmac_sc_buffer, &sm_sc_cmac_done);
20622bacf595SMatthias Ringwald }
206357132f12SMatthias Ringwald //
206457132f12SMatthias Ringwald // Link Key Conversion Function h7
206557132f12SMatthias Ringwald //
206657132f12SMatthias Ringwald // h7(SALT, W) = AES-CMAC_SALT(W)
206757132f12SMatthias Ringwald // - SALT is 128 bits
206857132f12SMatthias Ringwald // - W    is 128 bits
206957132f12SMatthias Ringwald static void h7_engine(sm_connection_t * sm_conn, const sm_key_t salt, const sm_key_t w) {
207057132f12SMatthias Ringwald 	const uint16_t message_len = 16;
207157132f12SMatthias Ringwald 	sm_cmac_connection = sm_conn;
207257132f12SMatthias Ringwald 	log_info("h7 key");
207357132f12SMatthias Ringwald 	log_info_hexdump(salt, 16);
207457132f12SMatthias Ringwald 	log_info("h7 message");
207557132f12SMatthias Ringwald 	log_info_hexdump(w, 16);
207657132f12SMatthias Ringwald 	sm_cmac_message_start(salt, message_len, w, &sm_sc_cmac_done);
207757132f12SMatthias Ringwald }
20782bacf595SMatthias Ringwald 
2079b18300a6SMatthias Ringwald // For SC, setup->sm_local_ltk holds full LTK (sm_ltk is already truncated)
2080b18300a6SMatthias Ringwald // Errata Service Release to the Bluetooth Specification: ESR09
2081b18300a6SMatthias Ringwald //   E6405 – Cross transport key derivation from a key of size less than 128 bits
2082b18300a6SMatthias Ringwald //   "Note: When the BR/EDR link key is being derived from the LTK, the derivation is done before the LTK gets masked."
208357132f12SMatthias Ringwald 
2084c82679c3SMatthias Ringwald static void h6_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn){
2085b18300a6SMatthias Ringwald     h6_engine(sm_conn, setup->sm_local_ltk, 0x746D7031);    // "tmp1"
20862bacf595SMatthias Ringwald }
20872bacf595SMatthias Ringwald 
2088e0a03c85SMatthias Ringwald static void h6_calculate_ilk_from_br_edr(sm_connection_t * sm_conn){
2089e0a03c85SMatthias Ringwald     h6_engine(sm_conn, setup->sm_link_key, 0x746D7032);    // "tmp2"
2090e0a03c85SMatthias Ringwald }
2091e0a03c85SMatthias Ringwald 
20922bacf595SMatthias Ringwald static void h6_calculate_br_edr_link_key(sm_connection_t * sm_conn){
20932bacf595SMatthias Ringwald     h6_engine(sm_conn, setup->sm_t, 0x6c656272);    // "lebr"
20942bacf595SMatthias Ringwald }
20952bacf595SMatthias Ringwald 
2096e0a03c85SMatthias Ringwald static void h6_calculate_le_ltk(sm_connection_t * sm_conn){
2097e0a03c85SMatthias Ringwald     h6_engine(sm_conn, setup->sm_t, 0x62726C65);    // "brle"
2098e0a03c85SMatthias Ringwald }
2099e0a03c85SMatthias Ringwald 
2100c82679c3SMatthias Ringwald static void h7_calculate_ilk_from_le_ltk(sm_connection_t * sm_conn){
210157132f12SMatthias Ringwald 	const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x31};  // "tmp1"
210257132f12SMatthias Ringwald 	h7_engine(sm_conn, salt, setup->sm_local_ltk);
210357132f12SMatthias Ringwald }
2104e0a03c85SMatthias Ringwald 
2105e0a03c85SMatthias Ringwald static void h7_calculate_ilk_from_br_edr(sm_connection_t * sm_conn){
2106e0a03c85SMatthias Ringwald     const uint8_t salt[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x32};  // "tmp2"
2107e0a03c85SMatthias Ringwald     h7_engine(sm_conn, salt, setup->sm_link_key);
2108e0a03c85SMatthias Ringwald }
2109e0a03c85SMatthias Ringwald 
2110c18be159SMatthias Ringwald static void sm_ctkd_fetch_br_edr_link_key(sm_connection_t * sm_conn){
2111e0a03c85SMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(sm_conn->sm_handle);
2112e0a03c85SMatthias Ringwald     btstack_assert(hci_connection != NULL);
2113e0a03c85SMatthias Ringwald     reverse_128(hci_connection->link_key, setup->sm_link_key);
2114e0a03c85SMatthias Ringwald     setup->sm_link_key_type =  hci_connection->link_key_type;
2115e0a03c85SMatthias Ringwald }
2116e0a03c85SMatthias Ringwald 
211713aed524SMatthias Ringwald static void sm_ctkd_start_from_br_edr(sm_connection_t * sm_conn){
211813aed524SMatthias Ringwald     // only derive LTK if EncKey is set by both
211913aed524SMatthias Ringwald     bool derive_ltk = (sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres) &
212013aed524SMatthias Ringwald                               sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres) & SM_KEYDIST_ENC_KEY) != 0;
212113aed524SMatthias Ringwald     if (derive_ltk){
2122c18be159SMatthias 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;
212313aed524SMatthias Ringwald         sm_conn->sm_engine_state = use_h7 ? SM_BR_EDR_W2_CALCULATE_ILK_USING_H7 : SM_BR_EDR_W2_CALCULATE_ILK_USING_H6;
212413aed524SMatthias Ringwald     } else {
212513aed524SMatthias Ringwald         sm_done_for_handle(sm_conn->sm_handle);
212613aed524SMatthias Ringwald     }
2127c18be159SMatthias Ringwald }
2128c18be159SMatthias Ringwald 
21299af0f475SMatthias Ringwald #endif
21309af0f475SMatthias Ringwald 
213155c62cf5SMatthias Ringwald #endif
213255c62cf5SMatthias Ringwald 
2133613da3deSMatthias Ringwald // key management legacy connections:
2134613da3deSMatthias Ringwald // - potentially two different LTKs based on direction. each device stores LTK provided by peer
2135613da3deSMatthias Ringwald // - master stores LTK, EDIV, RAND. responder optionally stored master LTK (only if it needs to reconnect)
2136613da3deSMatthias Ringwald // - initiators reconnects: initiator uses stored LTK, EDIV, RAND generated by responder
2137613da3deSMatthias Ringwald // - responder  reconnects: responder uses LTK receveived from master
2138613da3deSMatthias Ringwald 
2139613da3deSMatthias Ringwald // key management secure connections:
2140613da3deSMatthias Ringwald // - both devices store same LTK from ECDH key exchange.
2141613da3deSMatthias Ringwald 
214242134bc6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) || defined(ENABLE_LE_CENTRAL)
21435829ebe2SMatthias Ringwald static void sm_load_security_info(sm_connection_t * sm_connection){
21445829ebe2SMatthias Ringwald     int encryption_key_size;
21455829ebe2SMatthias Ringwald     int authenticated;
21465829ebe2SMatthias Ringwald     int authorized;
21473dc3a67dSMatthias Ringwald     int secure_connection;
21485829ebe2SMatthias Ringwald 
21495829ebe2SMatthias Ringwald     // fetch data from device db - incl. authenticated/authorized/key size. Note all sm_connection_X require encryption enabled
21505829ebe2SMatthias Ringwald     le_device_db_encryption_get(sm_connection->sm_le_db_index, &setup->sm_peer_ediv, setup->sm_peer_rand, setup->sm_peer_ltk,
21513dc3a67dSMatthias Ringwald                                 &encryption_key_size, &authenticated, &authorized, &secure_connection);
21523dc3a67dSMatthias 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);
21535829ebe2SMatthias Ringwald     sm_connection->sm_actual_encryption_key_size = encryption_key_size;
21545829ebe2SMatthias Ringwald     sm_connection->sm_connection_authenticated = authenticated;
21555829ebe2SMatthias Ringwald     sm_connection->sm_connection_authorization_state = authorized ? AUTHORIZATION_GRANTED : AUTHORIZATION_UNKNOWN;
2156d7dbf891SMatthias Ringwald     sm_connection->sm_connection_sc = secure_connection != 0;
21575829ebe2SMatthias Ringwald }
215842134bc6SMatthias Ringwald #endif
2159bd57ffebSMatthias Ringwald 
216042134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
216159066796SMatthias Ringwald static void sm_start_calculating_ltk_from_ediv_and_rand(sm_connection_t * sm_connection){
21626535961aSMatthias Ringwald     (void)memcpy(setup->sm_local_rand, sm_connection->sm_local_rand, 8);
216359066796SMatthias Ringwald     setup->sm_local_ediv = sm_connection->sm_local_ediv;
216459066796SMatthias Ringwald     // re-establish used key encryption size
216559066796SMatthias Ringwald     // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
21664ea43905SMatthias Ringwald     sm_connection->sm_actual_encryption_key_size = (setup->sm_local_rand[7u] & 0x0fu) + 1u;
216759066796SMatthias Ringwald     // no db for authenticated flag hack: flag is stored in bit 4 of LSB
21684ea43905SMatthias Ringwald     sm_connection->sm_connection_authenticated = (setup->sm_local_rand[7u] & 0x10u) >> 4u;
21693dc3a67dSMatthias Ringwald     // Legacy paring -> not SC
2170d7dbf891SMatthias Ringwald     sm_connection->sm_connection_sc = false;
217159066796SMatthias Ringwald     log_info("sm: received ltk request with key size %u, authenticated %u",
217259066796SMatthias Ringwald             sm_connection->sm_actual_encryption_key_size, sm_connection->sm_connection_authenticated);
217359066796SMatthias Ringwald }
217442134bc6SMatthias Ringwald #endif
217559066796SMatthias Ringwald 
21763deb3ec6SMatthias Ringwald // distributed key generation
2177d7f1c72eSMatthias Ringwald static bool sm_run_dpkg(void){
21783deb3ec6SMatthias Ringwald     switch (dkg_state){
21793deb3ec6SMatthias Ringwald         case DKG_CALC_IRK:
21803deb3ec6SMatthias Ringwald             // already busy?
21813deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2182d1a1f6a4SMatthias Ringwald                 log_info("DKG_CALC_IRK started");
21833deb3ec6SMatthias Ringwald                 // IRK = d1(IR, 1, 0)
2184d1a1f6a4SMatthias Ringwald                 sm_d1_d_prime(1, 0, sm_aes128_plaintext);  // plaintext = d1 prime
2185d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2186d1a1f6a4SMatthias 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);
2187d7f1c72eSMatthias Ringwald                 return true;
21883deb3ec6SMatthias Ringwald             }
21893deb3ec6SMatthias Ringwald             break;
21903deb3ec6SMatthias Ringwald         case DKG_CALC_DHK:
21913deb3ec6SMatthias Ringwald             // already busy?
21923deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2193d1a1f6a4SMatthias Ringwald                 log_info("DKG_CALC_DHK started");
21943deb3ec6SMatthias Ringwald                 // DHK = d1(IR, 3, 0)
2195d1a1f6a4SMatthias Ringwald                 sm_d1_d_prime(3, 0, sm_aes128_plaintext);  // plaintext = d1 prime
2196d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2197d1a1f6a4SMatthias 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);
2198d7f1c72eSMatthias Ringwald                 return true;
21993deb3ec6SMatthias Ringwald             }
22003deb3ec6SMatthias Ringwald             break;
22013deb3ec6SMatthias Ringwald         default:
22023deb3ec6SMatthias Ringwald             break;
22033deb3ec6SMatthias Ringwald     }
2204d7f1c72eSMatthias Ringwald     return false;
2205d7f1c72eSMatthias Ringwald }
22063deb3ec6SMatthias Ringwald 
22073deb3ec6SMatthias Ringwald // random address updates
2208d7f1c72eSMatthias Ringwald static bool sm_run_rau(void){
22093deb3ec6SMatthias Ringwald     switch (rau_state){
2210fbd4e238SMatthias Ringwald         case RAU_GET_RANDOM:
2211fbd4e238SMatthias Ringwald             rau_state = RAU_W4_RANDOM;
22125b4dd597SMatthias Ringwald             btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_address, 6, &sm_handle_random_result_rau, NULL);
2213d7f1c72eSMatthias Ringwald             return true;
22143deb3ec6SMatthias Ringwald         case RAU_GET_ENC:
22153deb3ec6SMatthias Ringwald             // already busy?
22163deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_IDLE) {
2217d1a1f6a4SMatthias Ringwald                 sm_ah_r_prime(sm_random_address, sm_aes128_plaintext);
2218d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
2219d1a1f6a4SMatthias Ringwald                 btstack_crypto_aes128_encrypt(&sm_crypto_aes128_request, sm_persistent_irk, sm_aes128_plaintext, sm_aes128_ciphertext, sm_handle_encryption_result_rau, NULL);
2220d7f1c72eSMatthias Ringwald                 return true;
22213deb3ec6SMatthias Ringwald             }
22223deb3ec6SMatthias Ringwald             break;
22233deb3ec6SMatthias Ringwald         default:
22243deb3ec6SMatthias Ringwald             break;
22253deb3ec6SMatthias Ringwald     }
2226d7f1c72eSMatthias Ringwald     return false;
2227d7f1c72eSMatthias Ringwald }
22283deb3ec6SMatthias Ringwald 
222951258968SMatthias Ringwald // device lookup with IRK
223051258968SMatthias Ringwald static bool sm_run_irk_lookup(void){
2231d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
2232d7f1c72eSMatthias Ringwald 
223351258968SMatthias Ringwald     // -- if IRK lookup ready, find connection that require csrk lookup
22343deb3ec6SMatthias Ringwald     if (sm_address_resolution_idle()){
22353deb3ec6SMatthias Ringwald         hci_connections_get_iterator(&it);
2236665d90f2SMatthias Ringwald         while(btstack_linked_list_iterator_has_next(&it)){
2237665d90f2SMatthias Ringwald             hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
22383deb3ec6SMatthias Ringwald             sm_connection_t  * sm_connection  = &hci_connection->sm_connection;
22393deb3ec6SMatthias Ringwald             if (sm_connection->sm_irk_lookup_state == IRK_LOOKUP_W4_READY){
22403deb3ec6SMatthias Ringwald                 // and start lookup
22413deb3ec6SMatthias 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);
22423deb3ec6SMatthias Ringwald                 sm_connection->sm_irk_lookup_state = IRK_LOOKUP_STARTED;
22433deb3ec6SMatthias Ringwald                 break;
22443deb3ec6SMatthias Ringwald             }
22453deb3ec6SMatthias Ringwald         }
22463deb3ec6SMatthias Ringwald     }
22473deb3ec6SMatthias Ringwald 
22483deb3ec6SMatthias Ringwald     // -- if csrk lookup ready, resolved addresses for received addresses
22493deb3ec6SMatthias Ringwald     if (sm_address_resolution_idle()) {
2250665d90f2SMatthias Ringwald         if (!btstack_linked_list_empty(&sm_address_resolution_general_queue)){
22513deb3ec6SMatthias Ringwald             sm_lookup_entry_t * entry = (sm_lookup_entry_t *) sm_address_resolution_general_queue;
2252665d90f2SMatthias Ringwald             btstack_linked_list_remove(&sm_address_resolution_general_queue, (btstack_linked_item_t *) entry);
22533deb3ec6SMatthias Ringwald             sm_address_resolution_start_lookup(entry->address_type, 0, entry->address, ADDRESS_RESOLUTION_GENERAL, NULL);
22543deb3ec6SMatthias Ringwald             btstack_memory_sm_lookup_entry_free(entry);
22553deb3ec6SMatthias Ringwald         }
22563deb3ec6SMatthias Ringwald     }
22573deb3ec6SMatthias Ringwald 
2258ca685291SMatthias Ringwald     // -- Continue with device lookup by public or resolvable private address
22593deb3ec6SMatthias Ringwald     if (!sm_address_resolution_idle()){
2260092ec58eSMatthias Ringwald         while (sm_address_resolution_test < le_device_db_max_count()){
2261adf5eaa9SMatthias Ringwald             int addr_type = BD_ADDR_TYPE_UNKNOWN;
22623deb3ec6SMatthias Ringwald             bd_addr_t addr;
22633deb3ec6SMatthias Ringwald             sm_key_t irk;
22643deb3ec6SMatthias Ringwald             le_device_db_info(sm_address_resolution_test, &addr_type, addr, irk);
22653deb3ec6SMatthias Ringwald 
2266adf5eaa9SMatthias Ringwald             // skip unused entries
2267adf5eaa9SMatthias Ringwald             if (addr_type == BD_ADDR_TYPE_UNKNOWN){
2268adf5eaa9SMatthias Ringwald                 sm_address_resolution_test++;
2269adf5eaa9SMatthias Ringwald                 continue;
2270adf5eaa9SMatthias Ringwald             }
2271adf5eaa9SMatthias Ringwald 
2272c2b94d32SMatthias Ringwald             log_info("LE Device Lookup: device %u of %u - type %u, %s", sm_address_resolution_test,
2273c2b94d32SMatthias Ringwald                      le_device_db_max_count(), addr_type, bd_addr_to_str(addr));
2274ca685291SMatthias Ringwald 
2275c2b94d32SMatthias Ringwald             // map resolved identity addresses to regular addresses
2276515f33beSMatthias Ringwald             int regular_addr_type = sm_address_resolution_addr_type & 1;
2277515f33beSMatthias Ringwald             if ((regular_addr_type == addr_type) && (memcmp(addr, sm_address_resolution_address, 6) == 0)){
2278ca685291SMatthias Ringwald                 log_info("LE Device Lookup: found by { addr_type, address} ");
2279a66b030fSMatthias Ringwald                 sm_address_resolution_handle_event(ADDRESS_RESOLUTION_SUCCEEDED);
22803deb3ec6SMatthias Ringwald                 break;
22813deb3ec6SMatthias Ringwald             }
22823deb3ec6SMatthias Ringwald 
2283c2b94d32SMatthias Ringwald             // if connection type is not random (i.e. public or resolved identity), it must be a different entry
2284c2b94d32SMatthias Ringwald             if (sm_address_resolution_addr_type != BD_ADDR_TYPE_LE_RANDOM){
22853deb3ec6SMatthias Ringwald                 sm_address_resolution_test++;
22863deb3ec6SMatthias Ringwald                 continue;
22873deb3ec6SMatthias Ringwald             }
22883deb3ec6SMatthias Ringwald 
22898cc81b50SMatthias Ringwald             // skip AH if no IRK
22908cc81b50SMatthias Ringwald             if (sm_is_null_key(irk)){
22918cc81b50SMatthias Ringwald                 sm_address_resolution_test++;
22928cc81b50SMatthias Ringwald                 continue;
22938cc81b50SMatthias Ringwald             }
22948cc81b50SMatthias Ringwald 
22953deb3ec6SMatthias Ringwald             if (sm_aes128_state == SM_AES128_ACTIVE) break;
22963deb3ec6SMatthias Ringwald 
22973deb3ec6SMatthias Ringwald             log_info("LE Device Lookup: calculate AH");
22988314c363SMatthias Ringwald             log_info_key("IRK", irk);
22993deb3ec6SMatthias Ringwald 
23006535961aSMatthias Ringwald             (void)memcpy(sm_aes128_key, irk, 16);
2301d1a1f6a4SMatthias Ringwald             sm_ah_r_prime(sm_address_resolution_address, sm_aes128_plaintext);
2302d1a1f6a4SMatthias Ringwald             sm_aes128_state = SM_AES128_ACTIVE;
2303d1a1f6a4SMatthias 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);
2304d7f1c72eSMatthias Ringwald             return true;
23053deb3ec6SMatthias Ringwald         }
23063deb3ec6SMatthias Ringwald 
2307092ec58eSMatthias Ringwald         if (sm_address_resolution_test >= le_device_db_max_count()){
23083deb3ec6SMatthias Ringwald             log_info("LE Device Lookup: not found");
23093deb3ec6SMatthias Ringwald             sm_address_resolution_handle_event(ADDRESS_RESOLUTION_FAILED);
23103deb3ec6SMatthias Ringwald         }
23113deb3ec6SMatthias Ringwald     }
2312d7f1c72eSMatthias Ringwald     return false;
2313d7f1c72eSMatthias Ringwald }
23143deb3ec6SMatthias Ringwald 
2315d7f1c72eSMatthias Ringwald // SC OOB
2316d7f1c72eSMatthias Ringwald static bool sm_run_oob(void){
2317c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2318c59d0c92SMatthias Ringwald     switch (sm_sc_oob_state){
2319c59d0c92SMatthias Ringwald         case SM_SC_OOB_W2_CALC_CONFIRM:
2320c59d0c92SMatthias Ringwald             if (!sm_cmac_ready()) break;
2321c59d0c92SMatthias Ringwald             sm_sc_oob_state = SM_SC_OOB_W4_CONFIRM;
2322c59d0c92SMatthias Ringwald             f4_engine(NULL, ec_q, ec_q, sm_sc_oob_random, 0);
2323d7f1c72eSMatthias Ringwald             return true;
2324c59d0c92SMatthias Ringwald         default:
2325c59d0c92SMatthias Ringwald             break;
2326c59d0c92SMatthias Ringwald     }
2327c59d0c92SMatthias Ringwald #endif
2328d7f1c72eSMatthias Ringwald     return false;
2329d7f1c72eSMatthias Ringwald }
2330275aafe8SMatthias Ringwald 
2331687a03c8SMatthias Ringwald static void sm_send_connectionless(sm_connection_t * sm_connection, const uint8_t * buffer, uint16_t size){
2332687a03c8SMatthias Ringwald     l2cap_send_connectionless(sm_connection->sm_handle, sm_connection->sm_cid, (uint8_t*) buffer, size);
2333687a03c8SMatthias Ringwald }
2334687a03c8SMatthias Ringwald 
233541d32297SMatthias Ringwald // handle basic actions that don't requires the full context
2336d7f1c72eSMatthias Ringwald static bool sm_run_basic(void){
2337d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
233841d32297SMatthias Ringwald     hci_connections_get_iterator(&it);
2339e9af1bf6SMatthias Ringwald     while(btstack_linked_list_iterator_has_next(&it)){
234041d32297SMatthias Ringwald         hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
234141d32297SMatthias Ringwald         sm_connection_t  * sm_connection = &hci_connection->sm_connection;
234241d32297SMatthias Ringwald         switch(sm_connection->sm_engine_state){
2343f4935286SMatthias Ringwald 
2344f4935286SMatthias Ringwald             // general
2345f4935286SMatthias Ringwald             case SM_GENERAL_SEND_PAIRING_FAILED: {
2346f4935286SMatthias Ringwald                 uint8_t buffer[2];
2347f4935286SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_FAILED;
2348f4935286SMatthias Ringwald                 buffer[1] = sm_connection->sm_pairing_failed_reason;
2349f4935286SMatthias Ringwald                 sm_connection->sm_engine_state = sm_connection->sm_role ? SM_RESPONDER_IDLE : SM_INITIATOR_CONNECTED;
2350687a03c8SMatthias Ringwald                 sm_send_connectionless(sm_connection, (uint8_t*) buffer, sizeof(buffer));
2351f4935286SMatthias Ringwald                 sm_pairing_complete(sm_connection, ERROR_CODE_AUTHENTICATION_FAILURE, sm_connection->sm_pairing_failed_reason);
2352f4935286SMatthias Ringwald                 sm_done_for_handle(sm_connection->sm_handle);
2353f4935286SMatthias Ringwald                 break;
2354f4935286SMatthias Ringwald             }
2355f4935286SMatthias Ringwald 
235641d32297SMatthias Ringwald             // responder side
235741d32297SMatthias Ringwald             case SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY:
235841d32297SMatthias Ringwald                 sm_connection->sm_engine_state = SM_RESPONDER_IDLE;
235941d32297SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle);
2360d7f1c72eSMatthias Ringwald                 return true;
23614b8b5afeSMatthias Ringwald 
23624b8b5afeSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
23634b8b5afeSMatthias Ringwald             case SM_SC_RECEIVED_LTK_REQUEST:
23644b8b5afeSMatthias Ringwald                 switch (sm_connection->sm_irk_lookup_state){
23654b8b5afeSMatthias Ringwald                     case IRK_LOOKUP_FAILED:
2366e9af1bf6SMatthias Ringwald                         log_info("LTK Request: IRK Lookup Failed)");
23674b8b5afeSMatthias Ringwald                         sm_connection->sm_engine_state = SM_RESPONDER_IDLE;
23684b8b5afeSMatthias Ringwald                         hci_send_cmd(&hci_le_long_term_key_negative_reply, sm_connection->sm_handle);
2369d7f1c72eSMatthias Ringwald                         return true;
23704b8b5afeSMatthias Ringwald                     default:
23714b8b5afeSMatthias Ringwald                         break;
23724b8b5afeSMatthias Ringwald                 }
23734b8b5afeSMatthias Ringwald                 break;
23744b8b5afeSMatthias Ringwald #endif
237541d32297SMatthias Ringwald             default:
237641d32297SMatthias Ringwald                 break;
237741d32297SMatthias Ringwald         }
237841d32297SMatthias Ringwald     }
2379d7f1c72eSMatthias Ringwald     return false;
2380d7f1c72eSMatthias Ringwald }
23813deb3ec6SMatthias Ringwald 
2382d7f1c72eSMatthias Ringwald static void sm_run_activate_connection(void){
23833deb3ec6SMatthias Ringwald     // Find connections that requires setup context and make active if no other is locked
2384d7f1c72eSMatthias Ringwald     btstack_linked_list_iterator_t it;
23853deb3ec6SMatthias Ringwald     hci_connections_get_iterator(&it);
23867149bde5SMatthias Ringwald     while((sm_active_connection_handle == HCI_CON_HANDLE_INVALID) && btstack_linked_list_iterator_has_next(&it)){
2387665d90f2SMatthias Ringwald         hci_connection_t * hci_connection = (hci_connection_t *) btstack_linked_list_iterator_next(&it);
23883deb3ec6SMatthias Ringwald         sm_connection_t  * sm_connection = &hci_connection->sm_connection;
23893deb3ec6SMatthias Ringwald         // - if no connection locked and we're ready/waiting for setup context, fetch it and start
23901979f09cSMatthias Ringwald         bool done = true;
23913deb3ec6SMatthias Ringwald         int err;
239242134bc6SMatthias Ringwald         UNUSED(err);
239334b6528fSMatthias Ringwald 
239434b6528fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
239534b6528fSMatthias Ringwald         // assert ec key is ready
2396505f1c30SMatthias Ringwald         if (   (sm_connection->sm_engine_state == SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED)
2397178e8c1bSMatthias Ringwald             || (sm_connection->sm_engine_state == SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST)
2398178e8c1bSMatthias Ringwald 			|| (sm_connection->sm_engine_state == SM_RESPONDER_SEND_SECURITY_REQUEST)){
239934b6528fSMatthias Ringwald             if (ec_key_generation_state == EC_KEY_GENERATION_IDLE){
240034b6528fSMatthias Ringwald                 sm_ec_generate_new_key();
240134b6528fSMatthias Ringwald             }
240234b6528fSMatthias Ringwald             if (ec_key_generation_state != EC_KEY_GENERATION_DONE){
240334b6528fSMatthias Ringwald                 continue;
240434b6528fSMatthias Ringwald             }
240534b6528fSMatthias Ringwald         }
240634b6528fSMatthias Ringwald #endif
240734b6528fSMatthias Ringwald 
24083deb3ec6SMatthias Ringwald         switch (sm_connection->sm_engine_state) {
240942134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
24103deb3ec6SMatthias Ringwald             case SM_RESPONDER_SEND_SECURITY_REQUEST:
24113deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
241242134bc6SMatthias Ringwald             case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
2413549ad5d2SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
241406cd539fSMatthias Ringwald             case SM_SC_RECEIVED_LTK_REQUEST:
241587014f74SMatthias Ringwald #endif
241687014f74SMatthias Ringwald #endif
241734c39fbdSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
24185567aa60SMatthias Ringwald             case SM_INITIATOR_PH4_HAS_LTK:
241934c39fbdSMatthias Ringwald 			case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
2420549ad5d2SMatthias Ringwald #endif
2421c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
2422c18be159SMatthias Ringwald             case SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED:
2423c18be159SMatthias Ringwald             case SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST:
2424c18be159SMatthias Ringwald #endif
242587014f74SMatthias Ringwald 				// just lock context
242687014f74SMatthias Ringwald 				break;
24273deb3ec6SMatthias Ringwald             default:
24281979f09cSMatthias Ringwald                 done = false;
24293deb3ec6SMatthias Ringwald                 break;
24303deb3ec6SMatthias Ringwald         }
24313deb3ec6SMatthias Ringwald         if (done){
24327149bde5SMatthias Ringwald             sm_active_connection_handle = sm_connection->sm_handle;
24337149bde5SMatthias 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);
24343deb3ec6SMatthias Ringwald         }
24353deb3ec6SMatthias Ringwald     }
2436d7f1c72eSMatthias Ringwald }
2437d7f1c72eSMatthias Ringwald 
2438403280b9SMatthias Ringwald static void sm_run_send_keypress_notification(sm_connection_t * connection){
2439403280b9SMatthias Ringwald     int i;
2440403280b9SMatthias Ringwald     uint8_t flags       = setup->sm_keypress_notification & 0x1fu;
2441403280b9SMatthias Ringwald     uint8_t num_actions = setup->sm_keypress_notification >> 5;
2442403280b9SMatthias Ringwald     uint8_t action = 0;
2443403280b9SMatthias Ringwald     for (i=SM_KEYPRESS_PASSKEY_ENTRY_STARTED;i<=SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED;i++){
24441d80f1e6SMatthias Ringwald         if ((flags & (1u<<i)) != 0u){
2445403280b9SMatthias Ringwald             bool clear_flag = true;
2446403280b9SMatthias Ringwald             switch (i){
2447403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_ENTRY_STARTED:
2448403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_CLEARED:
2449403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED:
2450403280b9SMatthias Ringwald                 default:
2451403280b9SMatthias Ringwald                     break;
2452403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_DIGIT_ENTERED:
2453403280b9SMatthias Ringwald                 case SM_KEYPRESS_PASSKEY_DIGIT_ERASED:
2454403280b9SMatthias Ringwald                     num_actions--;
2455403280b9SMatthias Ringwald                     clear_flag = num_actions == 0u;
2456403280b9SMatthias Ringwald                     break;
2457403280b9SMatthias Ringwald             }
2458403280b9SMatthias Ringwald             if (clear_flag){
2459403280b9SMatthias Ringwald                 flags &= ~(1<<i);
2460403280b9SMatthias Ringwald             }
2461403280b9SMatthias Ringwald             action = i;
2462403280b9SMatthias Ringwald             break;
2463403280b9SMatthias Ringwald         }
2464403280b9SMatthias Ringwald     }
2465403280b9SMatthias Ringwald     setup->sm_keypress_notification = (num_actions << 5) | flags;
2466403280b9SMatthias Ringwald 
2467403280b9SMatthias Ringwald     // send keypress notification
2468403280b9SMatthias Ringwald     uint8_t buffer[2];
2469403280b9SMatthias Ringwald     buffer[0] = SM_CODE_KEYPRESS_NOTIFICATION;
2470403280b9SMatthias Ringwald     buffer[1] = action;
2471687a03c8SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2472403280b9SMatthias Ringwald 
2473403280b9SMatthias Ringwald     // try
2474384eabd3SMatthias Ringwald     l2cap_request_can_send_fix_channel_now_event(sm_active_connection_handle, connection->sm_cid);
2475403280b9SMatthias Ringwald }
2476403280b9SMatthias Ringwald 
2477403280b9SMatthias Ringwald static void sm_run_distribute_keys(sm_connection_t * connection){
24781d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION) != 0u){
2479403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
2480403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
2481403280b9SMatthias Ringwald         uint8_t buffer[17];
2482403280b9SMatthias Ringwald         buffer[0] = SM_CODE_ENCRYPTION_INFORMATION;
2483403280b9SMatthias Ringwald         reverse_128(setup->sm_ltk, &buffer[1]);
2484687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2485403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2486403280b9SMatthias Ringwald         return;
2487403280b9SMatthias Ringwald     }
24881d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_MASTER_IDENTIFICATION) != 0u){
2489403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
2490403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
2491403280b9SMatthias Ringwald         uint8_t buffer[11];
2492403280b9SMatthias Ringwald         buffer[0] = SM_CODE_MASTER_IDENTIFICATION;
2493403280b9SMatthias Ringwald         little_endian_store_16(buffer, 1, setup->sm_local_ediv);
2494403280b9SMatthias Ringwald         reverse_64(setup->sm_local_rand, &buffer[3]);
2495687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2496403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2497403280b9SMatthias Ringwald         return;
2498403280b9SMatthias Ringwald     }
24991d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_IDENTITY_INFORMATION) != 0u){
2500403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
2501403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
2502403280b9SMatthias Ringwald         uint8_t buffer[17];
2503403280b9SMatthias Ringwald         buffer[0] = SM_CODE_IDENTITY_INFORMATION;
2504403280b9SMatthias Ringwald         reverse_128(sm_persistent_irk, &buffer[1]);
2505687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2506403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2507403280b9SMatthias Ringwald         return;
2508403280b9SMatthias Ringwald     }
25091d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION) != 0u){
2510403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
2511403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
2512403280b9SMatthias Ringwald         bd_addr_t local_address;
2513403280b9SMatthias Ringwald         uint8_t buffer[8];
2514403280b9SMatthias Ringwald         buffer[0] = SM_CODE_IDENTITY_ADDRESS_INFORMATION;
2515403280b9SMatthias Ringwald         switch (gap_random_address_get_mode()){
2516403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_TYPE_OFF:
2517403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_TYPE_STATIC:
2518403280b9SMatthias Ringwald                 // public or static random
2519403280b9SMatthias Ringwald                 gap_le_get_own_address(&buffer[1], local_address);
2520403280b9SMatthias Ringwald                 break;
2521403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_NON_RESOLVABLE:
2522403280b9SMatthias Ringwald             case GAP_RANDOM_ADDRESS_RESOLVABLE:
2523403280b9SMatthias Ringwald                 // fallback to public
2524403280b9SMatthias Ringwald                 gap_local_bd_addr(local_address);
2525403280b9SMatthias Ringwald                 buffer[1] = 0;
2526403280b9SMatthias Ringwald                 break;
2527403280b9SMatthias Ringwald             default:
2528403280b9SMatthias Ringwald                 btstack_assert(false);
2529403280b9SMatthias Ringwald                 break;
2530403280b9SMatthias Ringwald         }
2531403280b9SMatthias Ringwald         reverse_bd_addr(local_address, &buffer[2]);
2532687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2533403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2534403280b9SMatthias Ringwald         return;
2535403280b9SMatthias Ringwald     }
25361d80f1e6SMatthias Ringwald     if ((setup->sm_key_distribution_send_set &   SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION) != 0u){
2537403280b9SMatthias Ringwald         setup->sm_key_distribution_send_set &= ~SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
2538403280b9SMatthias Ringwald         setup->sm_key_distribution_sent_set |=  SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
2539403280b9SMatthias Ringwald 
2540403280b9SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
2541403280b9SMatthias Ringwald         // hack to reproduce test runs
2542403280b9SMatthias Ringwald                     if (test_use_fixed_local_csrk){
2543403280b9SMatthias Ringwald                         memset(setup->sm_local_csrk, 0xcc, 16);
2544403280b9SMatthias Ringwald                     }
2545403280b9SMatthias Ringwald 
2546403280b9SMatthias Ringwald                     // store local CSRK
2547403280b9SMatthias Ringwald                     if (setup->sm_le_device_index >= 0){
2548403280b9SMatthias Ringwald                         log_info("sm: store local CSRK");
2549403280b9SMatthias Ringwald                         le_device_db_local_csrk_set(setup->sm_le_device_index, setup->sm_local_csrk);
2550403280b9SMatthias Ringwald                         le_device_db_local_counter_set(setup->sm_le_device_index, 0);
2551403280b9SMatthias Ringwald                     }
2552403280b9SMatthias Ringwald #endif
2553403280b9SMatthias Ringwald 
2554403280b9SMatthias Ringwald         uint8_t buffer[17];
2555403280b9SMatthias Ringwald         buffer[0] = SM_CODE_SIGNING_INFORMATION;
2556403280b9SMatthias Ringwald         reverse_128(setup->sm_local_csrk, &buffer[1]);
2557687a03c8SMatthias Ringwald         sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2558403280b9SMatthias Ringwald         sm_timeout_reset(connection);
2559403280b9SMatthias Ringwald         return;
2560403280b9SMatthias Ringwald     }
2561403280b9SMatthias Ringwald     btstack_assert(false);
2562403280b9SMatthias Ringwald }
2563403280b9SMatthias Ringwald 
2564bbd73538SMatthias Ringwald static bool sm_ctkd_from_le(sm_connection_t *sm_connection) {
2565bbd73538SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
2566bbd73538SMatthias Ringwald     // requirements to derive link key from  LE:
2567bbd73538SMatthias Ringwald     // - use secure connections
2568bbd73538SMatthias Ringwald     if (setup->sm_use_secure_connections == 0) return false;
2569bbd73538SMatthias Ringwald     // - bonding needs to be enabled:
2570bbd73538SMatthias 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;
2571bbd73538SMatthias Ringwald     if (!bonding_enabled) return false;
2572bbd73538SMatthias Ringwald     // - need identity address / public addr
2573bbd73538SMatthias 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);
2574bbd73538SMatthias Ringwald     if (!have_identity_address_info) return false;
2575bbd73538SMatthias 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)
2576bbd73538SMatthias Ringwald     //   this requirement is motivated by BLURtooth paper. The paper recommends to not overwrite keys at all.
2577bbd73538SMatthias Ringwald     //      If SC is authenticated, we consider it safe to overwrite a stored key.
2578bbd73538SMatthias 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.
2579bbd73538SMatthias Ringwald     uint8_t link_key[16];
2580bbd73538SMatthias Ringwald     link_key_type_t link_key_type;
2581bbd73538SMatthias Ringwald     bool have_link_key             = gap_get_link_key_for_bd_addr(setup->sm_peer_address, link_key, &link_key_type);
25827040ba26SMatthias Ringwald     bool link_key_authenticated    = gap_authenticated_for_link_key_type(link_key_type);
2583bbd73538SMatthias Ringwald     bool derived_key_authenticated = sm_connection->sm_connection_authenticated != 0;
2584bbd73538SMatthias Ringwald     if (have_link_key && link_key_authenticated && !derived_key_authenticated) {
2585bbd73538SMatthias Ringwald         return false;
2586bbd73538SMatthias Ringwald     }
2587bbd73538SMatthias Ringwald     // get started (all of the above are true)
2588bbd73538SMatthias Ringwald     return true;
2589bbd73538SMatthias Ringwald #else
2590bbd73538SMatthias Ringwald     UNUSED(sm_connection);
2591bbd73538SMatthias Ringwald 	return false;
2592bbd73538SMatthias Ringwald #endif
2593bbd73538SMatthias Ringwald }
2594bbd73538SMatthias Ringwald 
25956a718a5eSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
25966a718a5eSMatthias Ringwald static bool sm_ctkd_from_classic(sm_connection_t * sm_connection){
25976a718a5eSMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(sm_connection->sm_handle);
25986a718a5eSMatthias Ringwald     btstack_assert(hci_connection != NULL);
25996a718a5eSMatthias Ringwald     // requirements to derive ltk from BR/EDR:
26006a718a5eSMatthias Ringwald     // - BR/EDR uses secure connections
26016a718a5eSMatthias Ringwald     if (gap_secure_connection_for_link_key_type(hci_connection->link_key_type) == false) return false;
26026a718a5eSMatthias 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)
26036a718a5eSMatthias Ringwald     bool link_key_authenticated = gap_authenticated_for_link_key_type(hci_connection->link_key_type);
26046a718a5eSMatthias Ringwald     if (link_key_authenticated) return true;
26056a718a5eSMatthias Ringwald     int index = sm_le_device_db_index_lookup(BD_ADDR_TYPE_LE_PUBLIC, hci_connection->address);
26066a718a5eSMatthias Ringwald     if (index >= 0){
26076a718a5eSMatthias Ringwald         int ltk_authenticated;
26086a718a5eSMatthias Ringwald         sm_key_t ltk;
26096a718a5eSMatthias Ringwald         le_device_db_encryption_get(sm_connection->sm_le_db_index, NULL, NULL, ltk, NULL, &ltk_authenticated, NULL, NULL);
26106a718a5eSMatthias Ringwald         bool have_ltk = !sm_is_null_key(ltk);
26116a718a5eSMatthias Ringwald         if (have_ltk && ltk_authenticated) return false;
26126a718a5eSMatthias Ringwald     }
26136a718a5eSMatthias Ringwald     return true;
26146a718a5eSMatthias Ringwald }
26156a718a5eSMatthias Ringwald #endif
26166a718a5eSMatthias Ringwald 
26176f7422f1SMatthias Ringwald static void sm_key_distribution_complete_responder(sm_connection_t * connection){
26186f7422f1SMatthias Ringwald     if (sm_ctkd_from_le(connection)){
26196f7422f1SMatthias 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;
26206f7422f1SMatthias Ringwald         connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
26216f7422f1SMatthias Ringwald     } else {
26226f7422f1SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_IDLE;
26236f7422f1SMatthias Ringwald         sm_pairing_complete(connection, ERROR_CODE_SUCCESS, 0);
26246f7422f1SMatthias Ringwald         sm_done_for_handle(connection->sm_handle);
26256f7422f1SMatthias Ringwald     }
26266f7422f1SMatthias Ringwald }
26276f7422f1SMatthias Ringwald 
2628af7ef9d1SMatthias Ringwald static void sm_key_distribution_complete_initiator(sm_connection_t * connection){
2629af7ef9d1SMatthias Ringwald     if (sm_ctkd_from_le(connection)){
2630af7ef9d1SMatthias 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;
2631af7ef9d1SMatthias Ringwald         connection->sm_engine_state = use_h7 ? SM_SC_W2_CALCULATE_ILK_USING_H7 : SM_SC_W2_CALCULATE_ILK_USING_H6;
2632af7ef9d1SMatthias Ringwald     } else {
2633af7ef9d1SMatthias Ringwald         sm_master_pairing_success(connection);
2634af7ef9d1SMatthias Ringwald     }
2635af7ef9d1SMatthias Ringwald }
2636af7ef9d1SMatthias Ringwald 
2637b919f264SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2638b919f264SMatthias Ringwald static void sm_run_state_sc_send_confirmation(sm_connection_t *connection) {
2639b919f264SMatthias Ringwald     uint8_t buffer[17];
2640b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_CONFIRM;
2641b919f264SMatthias Ringwald     reverse_128(setup->sm_local_confirm, &buffer[1]);
2642b919f264SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
2643b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2644b919f264SMatthias Ringwald     } else {
2645b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2646b919f264SMatthias Ringwald     }
2647b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2648b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2649b919f264SMatthias Ringwald }
2650b919f264SMatthias Ringwald 
2651b919f264SMatthias Ringwald static void sm_run_state_sc_send_pairing_random(sm_connection_t *connection) {
2652b919f264SMatthias Ringwald     uint8_t buffer[17];
2653b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_RANDOM;
2654b919f264SMatthias Ringwald     reverse_128(setup->sm_local_nonce, &buffer[1]);
2655b919f264SMatthias Ringwald     log_info("stk method %u, bit num: %u", setup->sm_stk_generation_method, setup->sm_passkey_bit);
2656b919f264SMatthias Ringwald     if (sm_passkey_entry(setup->sm_stk_generation_method) && (setup->sm_passkey_bit < 20u)){
2657b919f264SMatthias Ringwald         log_info("SM_SC_SEND_PAIRING_RANDOM A");
2658b919f264SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
2659b919f264SMatthias Ringwald             // responder
2660b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2661b919f264SMatthias Ringwald         } else {
2662b919f264SMatthias Ringwald             // initiator
2663b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2664b919f264SMatthias Ringwald         }
2665b919f264SMatthias Ringwald     } else {
2666b919f264SMatthias Ringwald         log_info("SM_SC_SEND_PAIRING_RANDOM B");
2667b919f264SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
2668b919f264SMatthias Ringwald             // responder
2669b919f264SMatthias Ringwald             if (setup->sm_stk_generation_method == NUMERIC_COMPARISON){
2670b919f264SMatthias Ringwald                 log_info("SM_SC_SEND_PAIRING_RANDOM B1");
2671b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W2_CALCULATE_G2;
2672b919f264SMatthias Ringwald             } else {
2673b919f264SMatthias Ringwald                 log_info("SM_SC_SEND_PAIRING_RANDOM B2");
2674b919f264SMatthias Ringwald                 sm_sc_prepare_dhkey_check(connection);
2675b919f264SMatthias Ringwald             }
2676b919f264SMatthias Ringwald         } else {
2677b919f264SMatthias Ringwald             // initiator
2678b919f264SMatthias Ringwald             connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2679b919f264SMatthias Ringwald         }
2680b919f264SMatthias Ringwald     }
2681b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2682b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2683b919f264SMatthias Ringwald }
2684b919f264SMatthias Ringwald 
2685b919f264SMatthias Ringwald static void sm_run_state_sc_send_dhkey_check_command(sm_connection_t *connection) {
2686b919f264SMatthias Ringwald     uint8_t buffer[17];
2687b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_DHKEY_CHECK;
2688b919f264SMatthias Ringwald     reverse_128(setup->sm_local_dhkey_check, &buffer[1]);
2689b919f264SMatthias Ringwald 
2690b919f264SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
2691b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_LTK_REQUEST_SC;
2692b919f264SMatthias Ringwald     } else {
2693b919f264SMatthias Ringwald         connection->sm_engine_state = SM_SC_W4_DHKEY_CHECK_COMMAND;
2694b919f264SMatthias Ringwald     }
2695b919f264SMatthias Ringwald 
2696b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2697b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2698b919f264SMatthias Ringwald }
2699b919f264SMatthias Ringwald 
2700b919f264SMatthias Ringwald static void sm_run_state_sc_send_public_key_command(sm_connection_t *connection) {
2701b919f264SMatthias Ringwald     bool trigger_user_response   = false;
2702b919f264SMatthias Ringwald     bool trigger_start_calculating_local_confirm = false;
2703b919f264SMatthias Ringwald     uint8_t buffer[65];
2704b919f264SMatthias Ringwald     buffer[0] = SM_CODE_PAIRING_PUBLIC_KEY;
2705b919f264SMatthias Ringwald     //
2706b919f264SMatthias Ringwald     reverse_256(&ec_q[0],  &buffer[1]);
2707b919f264SMatthias Ringwald     reverse_256(&ec_q[32], &buffer[33]);
2708b919f264SMatthias Ringwald 
2709b919f264SMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
2710b919f264SMatthias Ringwald     if (test_pairing_failure == SM_REASON_DHKEY_CHECK_FAILED){
2711b919f264SMatthias Ringwald             log_info("testing_support: invalidating public key");
2712b919f264SMatthias Ringwald             // flip single bit of public key coordinate
2713b919f264SMatthias Ringwald             buffer[1] ^= 1;
2714b919f264SMatthias Ringwald         }
2715b919f264SMatthias Ringwald #endif
2716b919f264SMatthias Ringwald 
2717b919f264SMatthias Ringwald     // stk generation method
2718b919f264SMatthias Ringwald // passkey entry: notify app to show passkey or to request passkey
2719b919f264SMatthias Ringwald     switch (setup->sm_stk_generation_method){
2720b919f264SMatthias Ringwald         case JUST_WORKS:
2721b919f264SMatthias Ringwald         case NUMERIC_COMPARISON:
2722b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2723b919f264SMatthias Ringwald                 // responder
2724b919f264SMatthias Ringwald                 trigger_start_calculating_local_confirm = true;
2725b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_LOCAL_NONCE;
2726b919f264SMatthias Ringwald             } else {
2727b919f264SMatthias Ringwald                 // initiator
2728b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2729b919f264SMatthias Ringwald             }
2730b919f264SMatthias Ringwald             break;
2731b919f264SMatthias Ringwald         case PK_INIT_INPUT:
2732b919f264SMatthias Ringwald         case PK_RESP_INPUT:
2733b919f264SMatthias Ringwald         case PK_BOTH_INPUT:
2734b919f264SMatthias Ringwald             // use random TK for display
2735b919f264SMatthias Ringwald             (void)memcpy(setup->sm_ra, setup->sm_tk, 16);
2736b919f264SMatthias Ringwald             (void)memcpy(setup->sm_rb, setup->sm_tk, 16);
2737b919f264SMatthias Ringwald             setup->sm_passkey_bit = 0;
2738b919f264SMatthias Ringwald 
2739b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2740b919f264SMatthias Ringwald                 // responder
2741b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CONFIRMATION;
2742b919f264SMatthias Ringwald             } else {
2743b919f264SMatthias Ringwald                 // initiator
2744b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2745b919f264SMatthias Ringwald             }
2746b919f264SMatthias Ringwald             trigger_user_response = true;
2747b919f264SMatthias Ringwald             break;
2748b919f264SMatthias Ringwald         case OOB:
2749b919f264SMatthias Ringwald             if (IS_RESPONDER(connection->sm_role)){
2750b919f264SMatthias Ringwald                 // responder
2751b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PAIRING_RANDOM;
2752b919f264SMatthias Ringwald             } else {
2753b919f264SMatthias Ringwald                 // initiator
2754b919f264SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
2755b919f264SMatthias Ringwald             }
2756b919f264SMatthias Ringwald             break;
2757b919f264SMatthias Ringwald         default:
2758b919f264SMatthias Ringwald             btstack_assert(false);
2759b919f264SMatthias Ringwald             break;
2760b919f264SMatthias Ringwald     }
2761b919f264SMatthias Ringwald 
2762b919f264SMatthias Ringwald     sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
2763b919f264SMatthias Ringwald     sm_timeout_reset(connection);
2764b919f264SMatthias Ringwald 
2765b919f264SMatthias Ringwald     // trigger user response and calc confirm after sending pdu
2766b919f264SMatthias Ringwald     if (trigger_user_response){
2767b919f264SMatthias Ringwald         sm_trigger_user_response(connection);
2768b919f264SMatthias Ringwald     }
2769b919f264SMatthias Ringwald     if (trigger_start_calculating_local_confirm){
2770b919f264SMatthias Ringwald         sm_sc_start_calculating_local_confirm(connection);
2771b919f264SMatthias Ringwald     }
2772b919f264SMatthias Ringwald }
2773b919f264SMatthias Ringwald #endif
2774b919f264SMatthias Ringwald 
2775de42cac5SMatthias Ringwald static bool sm_run_non_connection_logic(void){
2776de42cac5SMatthias Ringwald     bool done;;
2777de42cac5SMatthias Ringwald 
2778de42cac5SMatthias Ringwald     done = sm_run_dpkg();
2779de42cac5SMatthias Ringwald     if (done) return true;
2780de42cac5SMatthias Ringwald 
2781de42cac5SMatthias Ringwald     done = sm_run_rau();
2782de42cac5SMatthias Ringwald     if (done) return true;
2783de42cac5SMatthias Ringwald 
278451258968SMatthias Ringwald     done = sm_run_irk_lookup();
2785de42cac5SMatthias Ringwald     if (done) return true;
2786de42cac5SMatthias Ringwald 
2787de42cac5SMatthias Ringwald     done = sm_run_oob();
2788de42cac5SMatthias Ringwald     return done;
2789de42cac5SMatthias Ringwald }
2790b919f264SMatthias Ringwald 
2791d7f1c72eSMatthias Ringwald static void sm_run(void){
2792d7f1c72eSMatthias Ringwald 
2793d7f1c72eSMatthias Ringwald     // assert that stack has already bootet
2794d7f1c72eSMatthias Ringwald     if (hci_get_state() != HCI_STATE_WORKING) return;
2795d7f1c72eSMatthias Ringwald 
2796d7f1c72eSMatthias Ringwald     // assert that we can send at least commands
2797d7f1c72eSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return;
2798d7f1c72eSMatthias Ringwald 
2799d7f1c72eSMatthias Ringwald     // pause until IR/ER are ready
2800d7f1c72eSMatthias Ringwald     if (sm_persistent_keys_random_active) return;
2801d7f1c72eSMatthias Ringwald 
2802d7f1c72eSMatthias Ringwald     // non-connection related behaviour
2803de42cac5SMatthias Ringwald     bool done = sm_run_non_connection_logic();
2804d7f1c72eSMatthias Ringwald     if (done) return;
2805d7f1c72eSMatthias Ringwald 
2806d7f1c72eSMatthias Ringwald     // assert that we can send at least commands - cmd might have been sent by crypto engine
2807d7f1c72eSMatthias Ringwald     if (!hci_can_send_command_packet_now()) return;
2808d7f1c72eSMatthias Ringwald 
2809d7f1c72eSMatthias Ringwald     // handle basic actions that don't requires the full context
2810d7f1c72eSMatthias Ringwald     done = sm_run_basic();
2811d7f1c72eSMatthias Ringwald     if (done) return;
2812d7f1c72eSMatthias Ringwald 
2813d7f1c72eSMatthias Ringwald     //
2814d7f1c72eSMatthias Ringwald     // active connection handling
2815d7f1c72eSMatthias Ringwald     // -- use loop to handle next connection if lock on setup context is released
2816d7f1c72eSMatthias Ringwald 
2817d7f1c72eSMatthias Ringwald     while (true) {
2818d7f1c72eSMatthias Ringwald 
2819d7f1c72eSMatthias Ringwald         sm_run_activate_connection();
2820d7f1c72eSMatthias Ringwald 
2821d7f1c72eSMatthias Ringwald         if (sm_active_connection_handle == HCI_CON_HANDLE_INVALID) return;
28223deb3ec6SMatthias Ringwald 
28233deb3ec6SMatthias Ringwald         //
28243deb3ec6SMatthias Ringwald         // active connection handling
28253deb3ec6SMatthias Ringwald         //
28263deb3ec6SMatthias Ringwald 
28273cf37b8cSMatthias Ringwald         sm_connection_t * connection = sm_get_connection_for_handle(sm_active_connection_handle);
28283cf37b8cSMatthias Ringwald         if (!connection) {
28293cf37b8cSMatthias Ringwald             log_info("no connection for handle 0x%04x", sm_active_connection_handle);
28303cf37b8cSMatthias Ringwald             return;
28313cf37b8cSMatthias Ringwald         }
28323cf37b8cSMatthias Ringwald 
28333deb3ec6SMatthias Ringwald         // assert that we could send a SM PDU - not needed for all of the following
2834384eabd3SMatthias Ringwald         if (!l2cap_can_send_fixed_channel_packet_now(sm_active_connection_handle, connection->sm_cid)) {
28357149bde5SMatthias Ringwald             log_info("cannot send now, requesting can send now event");
2836384eabd3SMatthias Ringwald             l2cap_request_can_send_fix_channel_now_event(sm_active_connection_handle, connection->sm_cid);
2837b170b20fSMatthias Ringwald             return;
2838b170b20fSMatthias Ringwald         }
28393deb3ec6SMatthias Ringwald 
28403d7fe1e9SMatthias Ringwald         // send keypress notifications
28411d80f1e6SMatthias Ringwald         if (setup->sm_keypress_notification != 0u){
2842403280b9SMatthias Ringwald             sm_run_send_keypress_notification(connection);
2843d7471931SMatthias Ringwald             return;
28443d7fe1e9SMatthias Ringwald         }
28453d7fe1e9SMatthias Ringwald 
2846f7ea4423SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2847234022e5SMatthias Ringwald         // assert that sm cmac engine is ready
2848234022e5SMatthias Ringwald         if (sm_cmac_ready() == false){
2849234022e5SMatthias Ringwald             break;
2850234022e5SMatthias Ringwald         }
2851f7ea4423SMatthias Ringwald #endif
2852234022e5SMatthias Ringwald 
28533deb3ec6SMatthias Ringwald         int key_distribution_flags;
285442134bc6SMatthias Ringwald         UNUSED(key_distribution_flags);
2855b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
2856b6afa23eSMatthias Ringwald         int err;
28579b75de03SMatthias Ringwald         bool have_ltk;
28589b75de03SMatthias Ringwald         uint8_t ltk[16];
2859b6f39a74SMatthias Ringwald #endif
28603deb3ec6SMatthias Ringwald 
28613deb3ec6SMatthias Ringwald         log_info("sm_run: state %u", connection->sm_engine_state);
28623deb3ec6SMatthias Ringwald         switch (connection->sm_engine_state){
28633deb3ec6SMatthias Ringwald 
2864f32b7a88SMatthias Ringwald             // secure connections, initiator + responding states
2865aec94140SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2866aec94140SMatthias Ringwald             case SM_SC_W2_CMAC_FOR_CONFIRMATION:
2867aec94140SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CMAC_FOR_CONFIRMATION;
2868aec94140SMatthias Ringwald                 sm_sc_calculate_local_confirm(connection);
2869aec94140SMatthias Ringwald                 break;
2870688a08f9SMatthias Ringwald             case SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION:
2871688a08f9SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CMAC_FOR_CHECK_CONFIRMATION;
2872688a08f9SMatthias Ringwald                 sm_sc_calculate_remote_confirm(connection);
2873688a08f9SMatthias Ringwald                 break;
2874dc300847SMatthias Ringwald             case SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK:
2875dc300847SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK;
2876dc300847SMatthias Ringwald                 sm_sc_calculate_f6_for_dhkey_check(connection);
2877dc300847SMatthias Ringwald                 break;
2878019005a0SMatthias Ringwald             case SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK:
2879019005a0SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
28800346c37cSMatthias Ringwald                 sm_sc_calculate_f6_to_verify_dhkey_check(connection);
28810346c37cSMatthias Ringwald                 break;
28820346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_SALT:
28830346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_SALT;
28840346c37cSMatthias Ringwald                 f5_calculate_salt(connection);
28850346c37cSMatthias Ringwald                 break;
28860346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_MACKEY:
28870346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_MACKEY;
28880346c37cSMatthias Ringwald                 f5_calculate_mackey(connection);
28890346c37cSMatthias Ringwald                 break;
28900346c37cSMatthias Ringwald             case SM_SC_W2_CALCULATE_F5_LTK:
28910346c37cSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_F5_LTK;
28920346c37cSMatthias Ringwald                 f5_calculate_ltk(connection);
2893019005a0SMatthias Ringwald                 break;
2894bd57ffebSMatthias Ringwald             case SM_SC_W2_CALCULATE_G2:
2895bd57ffebSMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_G2;
2896b35a3de2SMatthias Ringwald                 g2_calculate(connection);
2897bd57ffebSMatthias Ringwald                 break;
2898e0a03c85SMatthias Ringwald #endif
2899e0a03c85SMatthias Ringwald 
290042134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
29013deb3ec6SMatthias Ringwald             // initiator side
2902f32b7a88SMatthias Ringwald 
29035567aa60SMatthias Ringwald             case SM_INITIATOR_PH4_HAS_LTK: {
2904f32b7a88SMatthias Ringwald 				sm_reset_setup();
2905f32b7a88SMatthias Ringwald 				sm_load_security_info(connection);
2906f32b7a88SMatthias Ringwald 
2907bcab6650SMatthias Ringwald                 // cache key before using
2908f76e733aSMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_peer_ltk);
2909bcab6650SMatthias Ringwald 
29103deb3ec6SMatthias Ringwald                 sm_key_t peer_ltk_flipped;
29119c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_peer_ltk, peer_ltk_flipped);
29125567aa60SMatthias Ringwald                 connection->sm_engine_state = SM_PH4_W4_CONNECTION_ENCRYPTED;
29133deb3ec6SMatthias Ringwald                 log_info("sm: hci_le_start_encryption ediv 0x%04x", setup->sm_peer_ediv);
2914c9b8fdd9SMatthias Ringwald                 uint32_t rand_high = big_endian_read_32(setup->sm_peer_rand, 0);
2915c9b8fdd9SMatthias Ringwald                 uint32_t rand_low  = big_endian_read_32(setup->sm_peer_rand, 4);
29163deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_start_encryption, connection->sm_handle,rand_low, rand_high, setup->sm_peer_ediv, peer_ltk_flipped);
291749c9e430SMatthias Ringwald 
291849c9e430SMatthias Ringwald                 // notify after sending
291949c9e430SMatthias Ringwald                 sm_reencryption_started(connection);
29203deb3ec6SMatthias Ringwald                 return;
29213deb3ec6SMatthias Ringwald             }
29223deb3ec6SMatthias Ringwald 
2923b26f445fSMatthias Ringwald 			case SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST:
2924b26f445fSMatthias Ringwald 				sm_reset_setup();
2925b26f445fSMatthias Ringwald 				sm_init_setup(connection);
2926b26f445fSMatthias Ringwald 
29271ad129beSMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST);
29283deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_INITIATOR_PH1_W4_PAIRING_RESPONSE;
2929687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
29303deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
293149c9e430SMatthias Ringwald 
293249c9e430SMatthias Ringwald                 // notify after sending
293349c9e430SMatthias Ringwald                 sm_pairing_started(connection);
29343deb3ec6SMatthias Ringwald                 break;
293542134bc6SMatthias Ringwald #endif
29363deb3ec6SMatthias Ringwald 
293727c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
2938b919f264SMatthias Ringwald             case SM_SC_SEND_PUBLIC_KEY_COMMAND:
2939b919f264SMatthias Ringwald                 sm_run_state_sc_send_public_key_command(connection);
294045a61d50SMatthias Ringwald                 break;
2941b919f264SMatthias Ringwald             case SM_SC_SEND_CONFIRMATION:
2942b919f264SMatthias Ringwald                 sm_run_state_sc_send_confirmation(connection);
294345a61d50SMatthias Ringwald                 break;
2944b919f264SMatthias Ringwald             case SM_SC_SEND_PAIRING_RANDOM:
2945b919f264SMatthias Ringwald                 sm_run_state_sc_send_pairing_random(connection);
294645a61d50SMatthias Ringwald                 break;
2947b919f264SMatthias Ringwald             case SM_SC_SEND_DHKEY_CHECK_COMMAND:
2948b919f264SMatthias Ringwald                 sm_run_state_sc_send_dhkey_check_command(connection);
29497bbeb3adSMilanka Ringwald                 break;
2950e53be891SMatthias Ringwald #endif
295142134bc6SMatthias Ringwald 
295242134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
2953dd12a62bSMatthias Ringwald 
295487014f74SMatthias Ringwald 			case SM_RESPONDER_SEND_SECURITY_REQUEST: {
295587014f74SMatthias Ringwald 				const uint8_t buffer[2] = {SM_CODE_SECURITY_REQUEST, sm_auth_req};
295687014f74SMatthias Ringwald 				connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_REQUEST;
2957687a03c8SMatthias Ringwald 				sm_send_connectionless(connection,  (uint8_t *) buffer, sizeof(buffer));
2958c8d0ff33SMatthias Ringwald 				sm_timeout_start(connection);
295987014f74SMatthias Ringwald 				break;
296087014f74SMatthias Ringwald 			}
296187014f74SMatthias Ringwald 
296238196718SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
296338196718SMatthias Ringwald 			case SM_SC_RECEIVED_LTK_REQUEST:
296438196718SMatthias Ringwald 				switch (connection->sm_irk_lookup_state){
296538196718SMatthias Ringwald 					case IRK_LOOKUP_SUCCEEDED:
296638196718SMatthias Ringwald 						// assuming Secure Connection, we have a stored LTK and the EDIV/RAND are null
296738196718SMatthias Ringwald 						// start using context by loading security info
296838196718SMatthias Ringwald 						sm_reset_setup();
296938196718SMatthias Ringwald 						sm_load_security_info(connection);
297038196718SMatthias Ringwald 						if ((setup->sm_peer_ediv == 0u) && sm_is_null_random(setup->sm_peer_rand) && !sm_is_null_key(setup->sm_peer_ltk)){
297138196718SMatthias Ringwald 							(void)memcpy(setup->sm_ltk, setup->sm_peer_ltk, 16);
297238196718SMatthias Ringwald 							connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
297342646f38SMatthias Ringwald                             sm_reencryption_started(connection);
297438196718SMatthias Ringwald                             sm_trigger_run();
297538196718SMatthias Ringwald 							break;
297638196718SMatthias Ringwald 						}
297738196718SMatthias Ringwald 						log_info("LTK Request: ediv & random are empty, but no stored LTK (IRK Lookup Succeeded)");
297838196718SMatthias Ringwald 						connection->sm_engine_state = SM_RESPONDER_IDLE;
297938196718SMatthias Ringwald 						hci_send_cmd(&hci_le_long_term_key_negative_reply, connection->sm_handle);
298038196718SMatthias Ringwald 						return;
298138196718SMatthias Ringwald 					default:
298238196718SMatthias Ringwald 						// just wait until IRK lookup is completed
298338196718SMatthias Ringwald 						break;
298438196718SMatthias Ringwald 				}
298538196718SMatthias Ringwald 				break;
298638196718SMatthias Ringwald #endif /* ENABLE_LE_SECURE_CONNECTIONS */
298738196718SMatthias Ringwald 
2988b6afa23eSMatthias Ringwald 			case SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED:
2989b6afa23eSMatthias Ringwald                 sm_reset_setup();
29909b75de03SMatthias Ringwald 
29919b75de03SMatthias Ringwald 			    // handle Pairing Request with LTK available
29929b75de03SMatthias Ringwald                 switch (connection->sm_irk_lookup_state) {
29939b75de03SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
29949b75de03SMatthias Ringwald                         le_device_db_encryption_get(connection->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
29959b75de03SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
29969b75de03SMatthias Ringwald                         if (have_ltk){
29979b75de03SMatthias Ringwald                             log_info("pairing request but LTK available");
299819a40772SMatthias Ringwald                             // emit re-encryption start/fail sequence
29999b75de03SMatthias Ringwald                             sm_reencryption_started(connection);
30009b75de03SMatthias Ringwald                             sm_reencryption_complete(connection, ERROR_CODE_PIN_OR_KEY_MISSING);
30019b75de03SMatthias Ringwald                         }
30029b75de03SMatthias Ringwald                         break;
30039b75de03SMatthias Ringwald                     default:
30049b75de03SMatthias Ringwald                         break;
30059b75de03SMatthias Ringwald                 }
30069b75de03SMatthias Ringwald 
3007b6afa23eSMatthias Ringwald 				sm_init_setup(connection);
300839543d07SMatthias Ringwald 
3009b6afa23eSMatthias Ringwald 				// recover pairing request
3010b6afa23eSMatthias Ringwald 				(void)memcpy(&setup->sm_m_preq, &connection->sm_m_preq, sizeof(sm_pairing_packet_t));
3011b6afa23eSMatthias Ringwald 				err = sm_stk_generation_init(connection);
3012b6afa23eSMatthias Ringwald 
3013b6afa23eSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
3014b6afa23eSMatthias Ringwald 				if ((0 < test_pairing_failure) && (test_pairing_failure < SM_REASON_DHKEY_CHECK_FAILED)){
3015b6afa23eSMatthias Ringwald                         log_info("testing_support: respond with pairing failure %u", test_pairing_failure);
3016b6afa23eSMatthias Ringwald                         err = test_pairing_failure;
3017b6afa23eSMatthias Ringwald                     }
3018b6afa23eSMatthias Ringwald #endif
30199305033eSMatthias Ringwald 				if (err != 0){
302049c9e430SMatthias Ringwald                     // emit pairing started/failed sequence
302149c9e430SMatthias Ringwald                     sm_pairing_started(connection);
3022f4935286SMatthias Ringwald                     sm_pairing_error(connection, err);
3023b6afa23eSMatthias Ringwald 					sm_trigger_run();
3024b6afa23eSMatthias Ringwald 					break;
3025b6afa23eSMatthias Ringwald 				}
3026b6afa23eSMatthias Ringwald 
3027b6afa23eSMatthias Ringwald 				sm_timeout_start(connection);
3028b6afa23eSMatthias Ringwald 
3029b6afa23eSMatthias Ringwald 				// generate random number first, if we need to show passkey, otherwise send response
3030b6afa23eSMatthias Ringwald 				if (setup->sm_stk_generation_method == PK_INIT_INPUT){
3031b6afa23eSMatthias 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);
3032b6afa23eSMatthias Ringwald 					break;
3033b6afa23eSMatthias Ringwald 				}
3034b6afa23eSMatthias Ringwald 
3035b6afa23eSMatthias Ringwald 				/* fall through */
3036b6afa23eSMatthias Ringwald 
30373deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE:
30381ad129beSMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_s_pres,SM_CODE_PAIRING_RESPONSE);
3039f55bd529SMatthias Ringwald 
3040f55bd529SMatthias Ringwald                 // start with initiator key dist flags
30413deb3ec6SMatthias Ringwald                 key_distribution_flags = sm_key_distribution_flags_for_auth_req();
30421ad129beSMatthias Ringwald 
3043f55bd529SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
3044b2072c76SMatthias Ringwald                 // LTK (= encryption information & master identification) only exchanged for LE Legacy Connection
3045f55bd529SMatthias Ringwald                 if (setup->sm_use_secure_connections){
3046f55bd529SMatthias Ringwald                     key_distribution_flags &= ~SM_KEYDIST_ENC_KEY;
3047f55bd529SMatthias Ringwald                 }
3048f55bd529SMatthias Ringwald #endif
3049f55bd529SMatthias Ringwald                 // setup in response
3050f55bd529SMatthias 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);
3051f55bd529SMatthias 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);
3052f55bd529SMatthias Ringwald 
3053f55bd529SMatthias Ringwald                 // update key distribution after ENC was dropped
30549a90d41aSMatthias 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));
3055f55bd529SMatthias Ringwald 
305627c32905SMatthias Ringwald                 if (setup->sm_use_secure_connections){
3057c6b7cbd9SMatthias Ringwald                     connection->sm_engine_state = SM_SC_W4_PUBLIC_KEY_COMMAND;
30580b8af2a5SMatthias Ringwald                 } else {
30590b8af2a5SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH1_W4_PAIRING_CONFIRM;
306027c32905SMatthias Ringwald                 }
30610b8af2a5SMatthias Ringwald 
3062687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
30633deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
306449c9e430SMatthias Ringwald 
306549c9e430SMatthias Ringwald                 // notify after sending
306649c9e430SMatthias Ringwald                 sm_pairing_started(connection);
306749c9e430SMatthias Ringwald 
3068446a8c36SMatthias Ringwald                 // SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
3069c1ab6cc1SMatthias Ringwald                 if (!setup->sm_use_secure_connections || (setup->sm_stk_generation_method == JUST_WORKS)){
30703deb3ec6SMatthias Ringwald                     sm_trigger_user_response(connection);
3071446a8c36SMatthias Ringwald                 }
30723deb3ec6SMatthias Ringwald                 return;
307342134bc6SMatthias Ringwald #endif
30743deb3ec6SMatthias Ringwald 
30753deb3ec6SMatthias Ringwald             case SM_PH2_SEND_PAIRING_RANDOM: {
30763deb3ec6SMatthias Ringwald                 uint8_t buffer[17];
30773deb3ec6SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_RANDOM;
30789c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_local_random, &buffer[1]);
307942134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
30803deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH2_W4_LTK_REQUEST;
30813deb3ec6SMatthias Ringwald                 } else {
30823deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_RANDOM;
30833deb3ec6SMatthias Ringwald                 }
3084687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
30853deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
30863deb3ec6SMatthias Ringwald                 break;
30873deb3ec6SMatthias Ringwald             }
30883deb3ec6SMatthias Ringwald 
3089d1a1f6a4SMatthias Ringwald             case SM_PH2_C1_GET_ENC_A:
30903deb3ec6SMatthias Ringwald                 // already busy?
30913deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
3092d1a1f6a4SMatthias Ringwald                 // calculate confirm using aes128 engine - step 1
3093d1a1f6a4SMatthias 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);
3094d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_C1_W4_ENC_A;
3095d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3096f3582630SMatthias 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);
30973deb3ec6SMatthias Ringwald                 break;
30983deb3ec6SMatthias Ringwald 
30993deb3ec6SMatthias Ringwald             case SM_PH2_C1_GET_ENC_C:
31003deb3ec6SMatthias Ringwald                 // already busy?
31013deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31023deb3ec6SMatthias Ringwald                 // calculate m_confirm using aes128 engine - step 1
3103d1a1f6a4SMatthias 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);
3104d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_C1_W4_ENC_C;
3105d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3106f3582630SMatthias 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);
31073deb3ec6SMatthias Ringwald                 break;
3108d1a1f6a4SMatthias Ringwald 
31093deb3ec6SMatthias Ringwald             case SM_PH2_CALC_STK:
31103deb3ec6SMatthias Ringwald                 // already busy?
31113deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31123deb3ec6SMatthias Ringwald                 // calculate STK
311342134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
3114d1a1f6a4SMatthias Ringwald                     sm_s1_r_prime(setup->sm_local_random, setup->sm_peer_random, sm_aes128_plaintext);
31153deb3ec6SMatthias Ringwald                 } else {
3116d1a1f6a4SMatthias Ringwald                     sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, sm_aes128_plaintext);
31173deb3ec6SMatthias Ringwald                 }
3118d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_STK;
3119d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3120f3582630SMatthias 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);
31213deb3ec6SMatthias Ringwald                 break;
3122d1a1f6a4SMatthias Ringwald 
31233deb3ec6SMatthias Ringwald             case SM_PH3_Y_GET_ENC:
31243deb3ec6SMatthias Ringwald                 // already busy?
31253deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31263deb3ec6SMatthias Ringwald                 // PH3B2 - calculate Y from      - enc
31279ad0dd7cSMatthias Ringwald 
31289ad0dd7cSMatthias Ringwald                 // dm helper (was sm_dm_r_prime)
31299ad0dd7cSMatthias Ringwald                 // r' = padding || r
31309ad0dd7cSMatthias Ringwald                 // r - 64 bit value
31319ad0dd7cSMatthias Ringwald                 memset(&sm_aes128_plaintext[0], 0, 8);
31326535961aSMatthias Ringwald                 (void)memcpy(&sm_aes128_plaintext[8], setup->sm_local_rand, 8);
31339ad0dd7cSMatthias Ringwald 
31343deb3ec6SMatthias Ringwald                 // Y = dm(DHK, Rand)
3135d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_PH3_Y_W4_ENC;
3136d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3137f3582630SMatthias 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);
3138d1a1f6a4SMatthias Ringwald                 break;
3139d1a1f6a4SMatthias Ringwald 
31403deb3ec6SMatthias Ringwald             case SM_PH2_C1_SEND_PAIRING_CONFIRM: {
31413deb3ec6SMatthias Ringwald                 uint8_t buffer[17];
31423deb3ec6SMatthias Ringwald                 buffer[0] = SM_CODE_PAIRING_CONFIRM;
31439c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_local_confirm, &buffer[1]);
314442134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
31453deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_RESPONDER_PH2_W4_PAIRING_RANDOM;
31463deb3ec6SMatthias Ringwald                 } else {
31473deb3ec6SMatthias Ringwald                     connection->sm_engine_state = SM_INITIATOR_PH2_W4_PAIRING_CONFIRM;
31483deb3ec6SMatthias Ringwald                 }
3149687a03c8SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t*) buffer, sizeof(buffer));
31503deb3ec6SMatthias Ringwald                 sm_timeout_reset(connection);
31513deb3ec6SMatthias Ringwald                 return;
31523deb3ec6SMatthias Ringwald             }
315342134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
31543deb3ec6SMatthias Ringwald             case SM_RESPONDER_PH2_SEND_LTK_REPLY: {
3155916ea5b2SMatthias Ringwald                 // cache key before using
3156916ea5b2SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
31573deb3ec6SMatthias Ringwald                 sm_key_t stk_flipped;
31589c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_ltk, stk_flipped);
31593deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
31603deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, stk_flipped);
31613deb3ec6SMatthias Ringwald                 return;
31623deb3ec6SMatthias Ringwald             }
3163d7471931SMatthias Ringwald             case SM_RESPONDER_PH4_SEND_LTK_REPLY: {
3164b96d60a6SMatthias Ringwald                 // allow to override LTK
3165b96d60a6SMatthias Ringwald                 if (sm_get_ltk_callback != NULL){
3166b96d60a6SMatthias Ringwald                     (void)(*sm_get_ltk_callback)(connection->sm_handle, connection->sm_peer_addr_type, connection->sm_peer_address, setup->sm_ltk);
3167b96d60a6SMatthias Ringwald                 }
3168916ea5b2SMatthias Ringwald                 // cache key before using
3169916ea5b2SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
31703deb3ec6SMatthias Ringwald                 sm_key_t ltk_flipped;
31719c80e4ccSMatthias Ringwald                 reverse_128(setup->sm_ltk, ltk_flipped);
31725567aa60SMatthias Ringwald                 connection->sm_engine_state = SM_PH4_W4_CONNECTION_ENCRYPTED;
31733deb3ec6SMatthias Ringwald                 hci_send_cmd(&hci_le_long_term_key_request_reply, connection->sm_handle, ltk_flipped);
31743deb3ec6SMatthias Ringwald                 return;
31753deb3ec6SMatthias Ringwald             }
3176dd12a62bSMatthias Ringwald 
3177dd12a62bSMatthias Ringwald 			case SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST:
31783deb3ec6SMatthias Ringwald                 // already busy?
31793deb3ec6SMatthias Ringwald                 if (sm_aes128_state == SM_AES128_ACTIVE) break;
31803deb3ec6SMatthias Ringwald                 log_info("LTK Request: recalculating with ediv 0x%04x", setup->sm_local_ediv);
3181c61cfe5aSMatthias Ringwald 
3182dd12a62bSMatthias Ringwald 				sm_reset_setup();
3183dd12a62bSMatthias Ringwald 				sm_start_calculating_ltk_from_ediv_and_rand(connection);
3184dd12a62bSMatthias Ringwald 
318542646f38SMatthias Ringwald 				sm_reencryption_started(connection);
318642646f38SMatthias Ringwald 
3187c61cfe5aSMatthias Ringwald                 // dm helper (was sm_dm_r_prime)
3188c61cfe5aSMatthias Ringwald                 // r' = padding || r
3189c61cfe5aSMatthias Ringwald                 // r - 64 bit value
3190c61cfe5aSMatthias Ringwald                 memset(&sm_aes128_plaintext[0], 0, 8);
31916535961aSMatthias Ringwald                 (void)memcpy(&sm_aes128_plaintext[8], setup->sm_local_rand, 8);
3192c61cfe5aSMatthias Ringwald 
31933deb3ec6SMatthias Ringwald                 // Y = dm(DHK, Rand)
3194d1a1f6a4SMatthias Ringwald                 connection->sm_engine_state = SM_RESPONDER_PH4_Y_W4_ENC;
3195d1a1f6a4SMatthias Ringwald                 sm_aes128_state = SM_AES128_ACTIVE;
3196f3582630SMatthias 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);
31973deb3ec6SMatthias Ringwald                 return;
319842134bc6SMatthias Ringwald #endif
319942134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
320042134bc6SMatthias Ringwald             case SM_INITIATOR_PH3_SEND_START_ENCRYPTION: {
3201bcab6650SMatthias Ringwald                 // cache key before using
3202bcab6650SMatthias Ringwald                 sm_cache_ltk(connection, setup->sm_ltk);
3203bcab6650SMatthias Ringwald 
320442134bc6SMatthias Ringwald                 sm_key_t stk_flipped;
320542134bc6SMatthias Ringwald                 reverse_128(setup->sm_ltk, stk_flipped);
320642134bc6SMatthias Ringwald                 connection->sm_engine_state = SM_PH2_W4_CONNECTION_ENCRYPTED;
320742134bc6SMatthias Ringwald                 hci_send_cmd(&hci_le_start_encryption, connection->sm_handle, 0, 0, 0, stk_flipped);
320842134bc6SMatthias Ringwald                 return;
320942134bc6SMatthias Ringwald             }
321042134bc6SMatthias Ringwald #endif
32113deb3ec6SMatthias Ringwald 
32123deb3ec6SMatthias Ringwald             case SM_PH3_DISTRIBUTE_KEYS:
3213e94757aeSMatthias Ringwald                 // send next key
3214403280b9SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
3215403280b9SMatthias Ringwald                     sm_run_distribute_keys(connection);
3216e94757aeSMatthias Ringwald                 }
3217e94757aeSMatthias Ringwald 
3218e94757aeSMatthias Ringwald                 // more to send?
3219e94757aeSMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0){
32203deb3ec6SMatthias Ringwald                     return;
32213deb3ec6SMatthias Ringwald                 }
32223deb3ec6SMatthias Ringwald 
32233deb3ec6SMatthias Ringwald                 // keys are sent
322442134bc6SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)){
32253deb3ec6SMatthias Ringwald                     // slave -> receive master keys if any
322661d1a45eSMatthias Ringwald                     if (sm_key_distribution_all_received()){
32273deb3ec6SMatthias Ringwald                         sm_key_distribution_handle_all_received(connection);
3228f5020412SMatthias Ringwald                         sm_key_distribution_complete_responder(connection);
3229f5020412SMatthias Ringwald                         // start CTKD right away
3230f5020412SMatthias Ringwald                         continue;
32313deb3ec6SMatthias Ringwald                     } else {
32323deb3ec6SMatthias Ringwald                         connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
32333deb3ec6SMatthias Ringwald                     }
32343deb3ec6SMatthias Ringwald                 } else {
32351dca9d8aSMatthias Ringwald                     sm_master_pairing_success(connection);
32363deb3ec6SMatthias Ringwald                 }
32373deb3ec6SMatthias Ringwald                 break;
32383deb3ec6SMatthias Ringwald 
3239c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3240c18be159SMatthias Ringwald             case SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST:
3241c18be159SMatthias Ringwald                 // fill in sm setup (lite version of sm_init_setup)
3242c18be159SMatthias Ringwald                 sm_reset_setup();
3243c18be159SMatthias Ringwald                 setup->sm_peer_addr_type = connection->sm_peer_addr_type;
3244c18be159SMatthias Ringwald                 setup->sm_m_addr_type = connection->sm_peer_addr_type;
3245c18be159SMatthias Ringwald                 setup->sm_s_addr_type = connection->sm_own_addr_type;
3246c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_peer_address, connection->sm_peer_address, 6);
3247c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_m_address, connection->sm_peer_address, 6);
3248c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_s_address, connection->sm_own_address, 6);
3249c18be159SMatthias Ringwald                 setup->sm_use_secure_connections = true;
3250c18be159SMatthias Ringwald                 sm_ctkd_fetch_br_edr_link_key(connection);
3251c18be159SMatthias Ringwald 
3252c18be159SMatthias Ringwald                 // Enc Key and IRK if requested
3253c18be159SMatthias Ringwald                 key_distribution_flags = SM_KEYDIST_ID_KEY | SM_KEYDIST_ENC_KEY;
3254c18be159SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
3255c18be159SMatthias Ringwald                 // Plus signing key if supported
3256c18be159SMatthias Ringwald                 key_distribution_flags |= SM_KEYDIST_ID_KEY;
3257c18be159SMatthias Ringwald #endif
3258c18be159SMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_m_preq, SM_CODE_PAIRING_REQUEST);
3259c18be159SMatthias Ringwald                 sm_pairing_packet_set_io_capability(setup->sm_m_preq, 0);
3260c18be159SMatthias Ringwald                 sm_pairing_packet_set_oob_data_flag(setup->sm_m_preq, 0);
3261c18be159SMatthias Ringwald                 sm_pairing_packet_set_auth_req(setup->sm_m_preq, SM_AUTHREQ_CT2);
3262c18be159SMatthias Ringwald                 sm_pairing_packet_set_max_encryption_key_size(setup->sm_m_preq, sm_max_encryption_key_size);
3263c18be159SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_m_preq, key_distribution_flags);
3264c18be159SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_m_preq, key_distribution_flags);
3265c18be159SMatthias Ringwald 
3266c18be159SMatthias Ringwald                 // set state and send pairing response
3267c18be159SMatthias Ringwald                 sm_timeout_start(connection);
3268c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_INITIATOR_W4_PAIRING_RESPONSE;
3269c18be159SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t *) &setup->sm_m_preq, sizeof(sm_pairing_packet_t));
3270c18be159SMatthias Ringwald                 break;
3271c18be159SMatthias Ringwald 
3272c18be159SMatthias Ringwald             case SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED:
3273c18be159SMatthias Ringwald                 // fill in sm setup (lite version of sm_init_setup)
3274c18be159SMatthias Ringwald                 sm_reset_setup();
3275c18be159SMatthias Ringwald                 setup->sm_peer_addr_type = connection->sm_peer_addr_type;
3276c18be159SMatthias Ringwald                 setup->sm_m_addr_type = connection->sm_peer_addr_type;
3277c18be159SMatthias Ringwald                 setup->sm_s_addr_type = connection->sm_own_addr_type;
3278c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_peer_address, connection->sm_peer_address, 6);
3279c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_m_address, connection->sm_peer_address, 6);
3280c18be159SMatthias Ringwald                 (void) memcpy(setup->sm_s_address, connection->sm_own_address, 6);
3281c18be159SMatthias Ringwald                 setup->sm_use_secure_connections = true;
3282c18be159SMatthias Ringwald                 sm_ctkd_fetch_br_edr_link_key(connection);
3283c18be159SMatthias Ringwald                 (void) memcpy(&setup->sm_m_preq, &connection->sm_m_preq, sizeof(sm_pairing_packet_t));
3284c18be159SMatthias Ringwald 
3285c18be159SMatthias Ringwald                 // Enc Key and IRK if requested
3286c18be159SMatthias Ringwald                 key_distribution_flags = SM_KEYDIST_ID_KEY | SM_KEYDIST_ENC_KEY;
3287c18be159SMatthias Ringwald #ifdef ENABLE_LE_SIGNED_WRITE
3288c18be159SMatthias Ringwald                 // Plus signing key if supported
3289c18be159SMatthias Ringwald                 key_distribution_flags |= SM_KEYDIST_ID_KEY;
3290c18be159SMatthias Ringwald #endif
3291c18be159SMatthias Ringwald                 // drop flags not requested by initiator
3292c18be159SMatthias Ringwald                 key_distribution_flags &= sm_pairing_packet_get_initiator_key_distribution(connection->sm_m_preq);
3293c18be159SMatthias Ringwald 
3294c18be159SMatthias 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:
3295c18be159SMatthias Ringwald                 // - the IO Capability field,
3296c18be159SMatthias Ringwald                 // - the OOB data flag field, and
3297c18be159SMatthias Ringwald                 // - all bits in the Auth Req field except the CT2 bit.
3298c18be159SMatthias Ringwald                 sm_pairing_packet_set_code(setup->sm_s_pres, SM_CODE_PAIRING_RESPONSE);
3299c18be159SMatthias Ringwald                 sm_pairing_packet_set_io_capability(setup->sm_s_pres, 0);
3300c18be159SMatthias Ringwald                 sm_pairing_packet_set_oob_data_flag(setup->sm_s_pres, 0);
3301c18be159SMatthias Ringwald                 sm_pairing_packet_set_auth_req(setup->sm_s_pres, SM_AUTHREQ_CT2);
3302c18be159SMatthias Ringwald                 sm_pairing_packet_set_max_encryption_key_size(setup->sm_s_pres, connection->sm_actual_encryption_key_size);
3303c18be159SMatthias Ringwald                 sm_pairing_packet_set_initiator_key_distribution(setup->sm_s_pres, key_distribution_flags);
3304c18be159SMatthias Ringwald                 sm_pairing_packet_set_responder_key_distribution(setup->sm_s_pres, key_distribution_flags);
3305c18be159SMatthias Ringwald 
3306c18be159SMatthias Ringwald                 // configure key distribution, LTK is derived locally
3307c18be159SMatthias Ringwald                 key_distribution_flags &= ~SM_KEYDIST_ENC_KEY;
3308c18be159SMatthias Ringwald                 sm_setup_key_distribution(key_distribution_flags, key_distribution_flags);
3309c18be159SMatthias Ringwald 
3310c18be159SMatthias Ringwald                 // set state and send pairing response
3311c18be159SMatthias Ringwald                 sm_timeout_start(connection);
3312c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
3313c18be159SMatthias Ringwald                 sm_send_connectionless(connection, (uint8_t *) &setup->sm_s_pres, sizeof(sm_pairing_packet_t));
3314c18be159SMatthias Ringwald                 break;
3315c18be159SMatthias Ringwald             case SM_BR_EDR_DISTRIBUTE_KEYS:
3316c18be159SMatthias Ringwald                 if (setup->sm_key_distribution_send_set != 0) {
3317c18be159SMatthias Ringwald                     sm_run_distribute_keys(connection);
3318c18be159SMatthias Ringwald                     return;
3319c18be159SMatthias Ringwald                 }
3320c18be159SMatthias Ringwald                 // keys are sent
3321c18be159SMatthias Ringwald                 if (IS_RESPONDER(connection->sm_role)) {
3322c18be159SMatthias Ringwald                     // responder -> receive master keys if there are any
332361d1a45eSMatthias Ringwald                     if (!sm_key_distribution_all_received()){
3324c18be159SMatthias Ringwald                         connection->sm_engine_state = SM_BR_EDR_RECEIVE_KEYS;
3325c18be159SMatthias Ringwald                         break;
3326c18be159SMatthias Ringwald                     }
3327c18be159SMatthias Ringwald                 }
3328c18be159SMatthias Ringwald                 // otherwise start CTKD right away (responder and no keys to receive / initiator)
3329c18be159SMatthias Ringwald                 sm_ctkd_start_from_br_edr(connection);
3330c18be159SMatthias Ringwald                 continue;
3331c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_ILK_USING_H6:
3332c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
3333c18be159SMatthias Ringwald                 h6_calculate_ilk_from_le_ltk(connection);
3334c18be159SMatthias Ringwald                 break;
3335c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_BR_EDR_LINK_KEY:
3336c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_BR_EDR_LINK_KEY;
3337c18be159SMatthias Ringwald                 h6_calculate_br_edr_link_key(connection);
3338c18be159SMatthias Ringwald                 break;
3339c18be159SMatthias Ringwald             case SM_SC_W2_CALCULATE_ILK_USING_H7:
3340c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_SC_W4_CALCULATE_ILK;
3341c18be159SMatthias Ringwald                 h7_calculate_ilk_from_le_ltk(connection);
3342c18be159SMatthias Ringwald                 break;
3343c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_ILK_USING_H6:
3344c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_ILK;
3345c18be159SMatthias Ringwald                 h6_calculate_ilk_from_br_edr(connection);
3346c18be159SMatthias Ringwald                 break;
3347c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_LE_LTK:
3348c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_LE_LTK;
3349c18be159SMatthias Ringwald                 h6_calculate_le_ltk(connection);
3350c18be159SMatthias Ringwald                 break;
3351c18be159SMatthias Ringwald             case SM_BR_EDR_W2_CALCULATE_ILK_USING_H7:
3352c18be159SMatthias Ringwald                 connection->sm_engine_state = SM_BR_EDR_W4_CALCULATE_ILK;
3353c18be159SMatthias Ringwald                 h7_calculate_ilk_from_br_edr(connection);
3354c18be159SMatthias Ringwald                 break;
3355c18be159SMatthias Ringwald #endif
3356c18be159SMatthias Ringwald 
33573deb3ec6SMatthias Ringwald             default:
33583deb3ec6SMatthias Ringwald                 break;
33593deb3ec6SMatthias Ringwald         }
33603deb3ec6SMatthias Ringwald 
33613deb3ec6SMatthias Ringwald         // check again if active connection was released
33627149bde5SMatthias Ringwald         if (sm_active_connection_handle != HCI_CON_HANDLE_INVALID) break;
33633deb3ec6SMatthias Ringwald     }
33643deb3ec6SMatthias Ringwald }
33653deb3ec6SMatthias Ringwald 
3366d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3367d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_a(void *arg){
3368f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
336904678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
337004678764SMatthias Ringwald 
3371f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3372f3582630SMatthias Ringwald     if (connection == NULL) return;
3373f3582630SMatthias Ringwald 
3374d1a1f6a4SMatthias Ringwald     sm_c1_t3(sm_aes128_ciphertext, setup->sm_m_address, setup->sm_s_address, setup->sm_c1_t3_value);
337504678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3376f3582630SMatthias 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);
3377d1a1f6a4SMatthias Ringwald }
33783deb3ec6SMatthias Ringwald 
3379d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_b(void *arg){
3380f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
338104678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
338204678764SMatthias Ringwald 
3383f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3384f3582630SMatthias Ringwald     if (connection == NULL) return;
3385f3582630SMatthias Ringwald 
33868314c363SMatthias Ringwald     log_info_key("c1!", setup->sm_local_confirm);
33873deb3ec6SMatthias Ringwald     connection->sm_engine_state = SM_PH2_C1_SEND_PAIRING_CONFIRM;
338870b44dd4SMatthias Ringwald     sm_trigger_run();
3389d1a1f6a4SMatthias Ringwald }
3390d1a1f6a4SMatthias Ringwald 
3391d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3392d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_c(void *arg){
3393f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
339404678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
339504678764SMatthias Ringwald 
3396f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3397f3582630SMatthias Ringwald     if (connection == NULL) return;
3398f3582630SMatthias Ringwald 
3399d1a1f6a4SMatthias Ringwald     sm_c1_t3(sm_aes128_ciphertext, setup->sm_m_address, setup->sm_s_address, setup->sm_c1_t3_value);
340004678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3401f3582630SMatthias 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);
3402d1a1f6a4SMatthias Ringwald }
3403d1a1f6a4SMatthias Ringwald 
3404d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_d(void * arg){
3405f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
340604678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
340704678764SMatthias Ringwald 
3408f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3409f3582630SMatthias Ringwald     if (connection == NULL) return;
3410f3582630SMatthias Ringwald 
3411d1a1f6a4SMatthias Ringwald     log_info_key("c1!", sm_aes128_ciphertext);
3412d1a1f6a4SMatthias Ringwald     if (memcmp(setup->sm_peer_confirm, sm_aes128_ciphertext, 16) != 0){
3413f4935286SMatthias Ringwald         sm_pairing_error(connection, SM_REASON_CONFIRM_VALUE_FAILED);
341470b44dd4SMatthias Ringwald         sm_trigger_run();
34153deb3ec6SMatthias Ringwald         return;
34163deb3ec6SMatthias Ringwald     }
341742134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
34183deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
341970b44dd4SMatthias Ringwald         sm_trigger_run();
34203deb3ec6SMatthias Ringwald     } else {
3421d1a1f6a4SMatthias Ringwald         sm_s1_r_prime(setup->sm_peer_random, setup->sm_local_random, sm_aes128_plaintext);
3422d1a1f6a4SMatthias Ringwald         sm_aes128_state = SM_AES128_ACTIVE;
3423f3582630SMatthias 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);
34243deb3ec6SMatthias Ringwald     }
34253deb3ec6SMatthias Ringwald }
3426d1a1f6a4SMatthias Ringwald 
3427d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_stk(void *arg){
342804678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
3429f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
343004678764SMatthias Ringwald 
3431f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3432f3582630SMatthias Ringwald     if (connection == NULL) return;
3433f3582630SMatthias Ringwald 
34343deb3ec6SMatthias Ringwald     sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
34358314c363SMatthias Ringwald     log_info_key("stk", setup->sm_ltk);
343642134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
34373deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
34383deb3ec6SMatthias Ringwald     } else {
34393deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_INITIATOR_PH3_SEND_START_ENCRYPTION;
34403deb3ec6SMatthias Ringwald     }
344170b44dd4SMatthias Ringwald     sm_trigger_run();
3442d1a1f6a4SMatthias Ringwald }
3443d1a1f6a4SMatthias Ringwald 
3444d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3445d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_y(void *arg){
3446f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
344704678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
344804678764SMatthias Ringwald 
3449f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3450f3582630SMatthias Ringwald     if (connection == NULL) return;
3451f3582630SMatthias Ringwald 
3452d1a1f6a4SMatthias Ringwald     setup->sm_local_y = big_endian_read_16(sm_aes128_ciphertext, 14);
34533deb3ec6SMatthias Ringwald     log_info_hex16("y", setup->sm_local_y);
34543deb3ec6SMatthias Ringwald     // PH3B3 - calculate EDIV
34553deb3ec6SMatthias Ringwald     setup->sm_local_ediv = setup->sm_local_y ^ setup->sm_local_div;
34563deb3ec6SMatthias Ringwald     log_info_hex16("ediv", setup->sm_local_ediv);
34573deb3ec6SMatthias Ringwald     // PH3B4 - calculate LTK         - enc
34583deb3ec6SMatthias Ringwald     // LTK = d1(ER, DIV, 0))
3459d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 0, sm_aes128_plaintext);
346004678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3461f3582630SMatthias 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);
34623deb3ec6SMatthias Ringwald }
3463d1a1f6a4SMatthias Ringwald 
34642a526f21SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
3465d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3466d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_y(void *arg){
346704678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
3468f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
346904678764SMatthias Ringwald 
3470f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3471f3582630SMatthias Ringwald     if (connection == NULL) return;
3472f3582630SMatthias Ringwald 
3473d1a1f6a4SMatthias Ringwald     setup->sm_local_y = big_endian_read_16(sm_aes128_ciphertext, 14);
34743deb3ec6SMatthias Ringwald     log_info_hex16("y", setup->sm_local_y);
34753deb3ec6SMatthias Ringwald 
34763deb3ec6SMatthias Ringwald     // PH3B3 - calculate DIV
34773deb3ec6SMatthias Ringwald     setup->sm_local_div = setup->sm_local_y ^ setup->sm_local_ediv;
34783deb3ec6SMatthias Ringwald     log_info_hex16("ediv", setup->sm_local_ediv);
34793deb3ec6SMatthias Ringwald     // PH3B4 - calculate LTK         - enc
34803deb3ec6SMatthias Ringwald     // LTK = d1(ER, DIV, 0))
3481d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 0, sm_aes128_plaintext);
348204678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3483f3582630SMatthias 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);
34843deb3ec6SMatthias Ringwald }
34852a526f21SMatthias Ringwald #endif
3486d1a1f6a4SMatthias Ringwald 
3487d1a1f6a4SMatthias Ringwald // sm_aes128_state stays active
3488d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph3_ltk(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 
34958314c363SMatthias Ringwald     log_info_key("ltk", setup->sm_ltk);
34963deb3ec6SMatthias Ringwald     // calc CSRK next
3497d1a1f6a4SMatthias Ringwald     sm_d1_d_prime(setup->sm_local_div, 1, sm_aes128_plaintext);
349804678764SMatthias Ringwald     sm_aes128_state = SM_AES128_ACTIVE;
3499f3582630SMatthias 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);
3500d1a1f6a4SMatthias Ringwald }
3501d1a1f6a4SMatthias Ringwald 
3502d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_csrk(void *arg){
3503f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
350404678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
350504678764SMatthias Ringwald 
3506f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3507f3582630SMatthias Ringwald     if (connection == NULL) return;
3508f3582630SMatthias Ringwald 
3509d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
35108314c363SMatthias Ringwald     log_info_key("csrk", setup->sm_local_csrk);
35111d80f1e6SMatthias Ringwald     if (setup->sm_key_distribution_send_set != 0u){
35123deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
35133deb3ec6SMatthias Ringwald     } else {
35143deb3ec6SMatthias Ringwald         // no keys to send, just continue
351542134bc6SMatthias Ringwald         if (IS_RESPONDER(connection->sm_role)){
351661d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
3517c5a72e35SMatthias Ringwald                 sm_key_distribution_handle_all_received(connection);
3518c5a72e35SMatthias Ringwald                 sm_key_distribution_complete_responder(connection);
3519c5a72e35SMatthias Ringwald             } else {
35203deb3ec6SMatthias Ringwald                 // slave -> receive master keys
35213deb3ec6SMatthias Ringwald                 connection->sm_engine_state = SM_PH3_RECEIVE_KEYS;
3522c5a72e35SMatthias Ringwald             }
35233deb3ec6SMatthias Ringwald         } else {
3524af7ef9d1SMatthias Ringwald             sm_key_distribution_complete_initiator(connection);
35253deb3ec6SMatthias Ringwald         }
35262bacf595SMatthias Ringwald     }
352770b44dd4SMatthias Ringwald     sm_trigger_run();
3528d1a1f6a4SMatthias Ringwald }
3529d1a1f6a4SMatthias Ringwald 
353042134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
3531d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_enc_ph4_ltk(void *arg){
3532f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
353304678764SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
353404678764SMatthias Ringwald 
3535f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3536f3582630SMatthias Ringwald     if (connection == NULL) return;
3537f3582630SMatthias Ringwald 
35383deb3ec6SMatthias Ringwald     sm_truncate_key(setup->sm_ltk, connection->sm_actual_encryption_key_size);
35398314c363SMatthias Ringwald     log_info_key("ltk", setup->sm_ltk);
3540d7471931SMatthias Ringwald     connection->sm_engine_state = SM_RESPONDER_PH4_SEND_LTK_REPLY;
354170b44dd4SMatthias Ringwald     sm_trigger_run();
3542d1a1f6a4SMatthias Ringwald }
3543d1a1f6a4SMatthias Ringwald #endif
3544d1a1f6a4SMatthias Ringwald 
3545d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_address_resolution(void *arg){
3546d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3547d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
354804678764SMatthias Ringwald 
3549d1a1f6a4SMatthias Ringwald     // compare calulated address against connecting device
3550d1a1f6a4SMatthias Ringwald     uint8_t * hash = &sm_aes128_ciphertext[13];
3551d1a1f6a4SMatthias Ringwald     if (memcmp(&sm_address_resolution_address[3], hash, 3) == 0){
3552d1a1f6a4SMatthias Ringwald         log_info("LE Device Lookup: matched resolvable private address");
3553a66b030fSMatthias Ringwald         sm_address_resolution_handle_event(ADDRESS_RESOLUTION_SUCCEEDED);
355470b44dd4SMatthias Ringwald         sm_trigger_run();
35553deb3ec6SMatthias Ringwald         return;
35563deb3ec6SMatthias Ringwald     }
3557d1a1f6a4SMatthias Ringwald     // no match, try next
3558d1a1f6a4SMatthias Ringwald     sm_address_resolution_test++;
355970b44dd4SMatthias Ringwald     sm_trigger_run();
35603deb3ec6SMatthias Ringwald }
35613deb3ec6SMatthias Ringwald 
3562d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_irk(void *arg){
3563d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3564d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
356504678764SMatthias Ringwald 
3566d1a1f6a4SMatthias Ringwald     log_info_key("irk", sm_persistent_irk);
3567d1a1f6a4SMatthias Ringwald     dkg_state = DKG_CALC_DHK;
356870b44dd4SMatthias Ringwald     sm_trigger_run();
35697df18c15SMatthias Ringwald }
3570d1a1f6a4SMatthias Ringwald 
3571d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_dkg_dhk(void *arg){
3572d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3573d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
357404678764SMatthias Ringwald 
3575d1a1f6a4SMatthias Ringwald     log_info_key("dhk", sm_persistent_dhk);
3576d1a1f6a4SMatthias Ringwald     dkg_state = DKG_READY;
357770b44dd4SMatthias Ringwald     sm_trigger_run();
35787df18c15SMatthias Ringwald }
3579d1a1f6a4SMatthias Ringwald 
3580d1a1f6a4SMatthias Ringwald static void sm_handle_encryption_result_rau(void *arg){
3581d1a1f6a4SMatthias Ringwald     UNUSED(arg);
3582d1a1f6a4SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
358304678764SMatthias Ringwald 
35846535961aSMatthias Ringwald     (void)memcpy(&sm_random_address[3], &sm_aes128_ciphertext[13], 3);
3585e91ddb40SMatthias Ringwald     rau_state = RAU_IDLE;
3586e91ddb40SMatthias Ringwald     hci_le_random_address_set(sm_random_address);
3587e91ddb40SMatthias Ringwald 
358870b44dd4SMatthias Ringwald     sm_trigger_run();
358951fa0b28SMatthias Ringwald }
35907df18c15SMatthias Ringwald 
3591d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_rau(void * arg){
3592d1a1f6a4SMatthias Ringwald     UNUSED(arg);
35933deb3ec6SMatthias Ringwald     // non-resolvable vs. resolvable
35943deb3ec6SMatthias Ringwald     switch (gap_random_adress_type){
35953deb3ec6SMatthias Ringwald         case GAP_RANDOM_ADDRESS_RESOLVABLE:
35963deb3ec6SMatthias Ringwald             // resolvable: use random as prand and calc address hash
35973deb3ec6SMatthias Ringwald             // "The two most significant bits of prand shall be equal to ‘0’ and ‘1"
35984ea43905SMatthias Ringwald             sm_random_address[0u] &= 0x3fu;
35994ea43905SMatthias Ringwald             sm_random_address[0u] |= 0x40u;
36003deb3ec6SMatthias Ringwald             rau_state = RAU_GET_ENC;
36013deb3ec6SMatthias Ringwald             break;
36023deb3ec6SMatthias Ringwald         case GAP_RANDOM_ADDRESS_NON_RESOLVABLE:
36033deb3ec6SMatthias Ringwald         default:
36043deb3ec6SMatthias Ringwald             // "The two most significant bits of the address shall be equal to ‘0’""
36054ea43905SMatthias Ringwald             sm_random_address[0u] &= 0x3fu;
36062954e6c6SMatthias Ringwald             rau_state = RAU_IDLE;
3607e91ddb40SMatthias Ringwald             hci_le_random_address_set(sm_random_address);
36083deb3ec6SMatthias Ringwald             break;
36093deb3ec6SMatthias Ringwald     }
361070b44dd4SMatthias Ringwald     sm_trigger_run();
36113deb3ec6SMatthias Ringwald }
36123deb3ec6SMatthias Ringwald 
3613c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
36146ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_send_pairing_random(void * arg){
3615f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3616f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3617f3582630SMatthias Ringwald     if (connection == NULL) return;
3618c59d0c92SMatthias Ringwald 
361965a9a04eSMatthias Ringwald     connection->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
362070b44dd4SMatthias Ringwald     sm_trigger_run();
362165a9a04eSMatthias Ringwald }
3622d1a1f6a4SMatthias Ringwald 
36236ca80073SMatthias Ringwald static void sm_handle_random_result_sc_next_w2_cmac_for_confirmation(void * arg){
36246ca80073SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
36256ca80073SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
36266ca80073SMatthias Ringwald     if (connection == NULL) return;
36276ca80073SMatthias Ringwald 
3628b35a3de2SMatthias Ringwald     connection->sm_engine_state = SM_SC_W2_CMAC_FOR_CONFIRMATION;
362970b44dd4SMatthias Ringwald     sm_trigger_run();
3630d1a1f6a4SMatthias Ringwald }
3631f1c1783eSMatthias Ringwald #endif
3632f1c1783eSMatthias Ringwald 
3633d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_random(void * arg){
3634f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3635f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3636f3582630SMatthias Ringwald     if (connection == NULL) return;
3637f3582630SMatthias Ringwald 
3638d1a1f6a4SMatthias Ringwald     connection->sm_engine_state = SM_PH2_C1_GET_ENC_A;
363970b44dd4SMatthias Ringwald     sm_trigger_run();
3640d1a1f6a4SMatthias Ringwald }
3641d1a1f6a4SMatthias Ringwald 
3642d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph2_tk(void * arg){
3643f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3644f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3645f3582630SMatthias Ringwald     if (connection == NULL) return;
3646f3582630SMatthias Ringwald 
3647caf15bf3SMatthias Ringwald     sm_reset_tk();
3648caf15bf3SMatthias Ringwald     uint32_t tk;
36495ce1359eSMatthias Ringwald     if (sm_fixed_passkey_in_display_role == 0xffffffffU){
36503deb3ec6SMatthias Ringwald         // map random to 0-999999 without speding much cycles on a modulus operation
3651d1a1f6a4SMatthias Ringwald         tk = little_endian_read_32(sm_random_data,0);
36523deb3ec6SMatthias Ringwald         tk = tk & 0xfffff;  // 1048575
36534ea43905SMatthias Ringwald         if (tk >= 999999u){
36544ea43905SMatthias Ringwald             tk = tk - 999999u;
36553deb3ec6SMatthias Ringwald         }
3656caf15bf3SMatthias Ringwald     } else {
3657caf15bf3SMatthias Ringwald         // override with pre-defined passkey
36584b8c611fSMatthias Ringwald         tk = sm_fixed_passkey_in_display_role;
3659caf15bf3SMatthias Ringwald     }
3660f8fbdce0SMatthias Ringwald     big_endian_store_32(setup->sm_tk, 12, tk);
366142134bc6SMatthias Ringwald     if (IS_RESPONDER(connection->sm_role)){
36623deb3ec6SMatthias Ringwald         connection->sm_engine_state = SM_RESPONDER_PH1_SEND_PAIRING_RESPONSE;
36633deb3ec6SMatthias Ringwald     } else {
3664b41539d5SMatthias Ringwald         if (setup->sm_use_secure_connections){
3665b41539d5SMatthias Ringwald             connection->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
3666b41539d5SMatthias Ringwald         } else {
36673deb3ec6SMatthias Ringwald             connection->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
36683deb3ec6SMatthias Ringwald             sm_trigger_user_response(connection);
36693deb3ec6SMatthias Ringwald             // response_idle == nothing <--> sm_trigger_user_response() did not require response
36703deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
3671f3582630SMatthias 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);
36723deb3ec6SMatthias Ringwald             }
36733deb3ec6SMatthias Ringwald         }
3674b41539d5SMatthias Ringwald     }
367570b44dd4SMatthias Ringwald     sm_trigger_run();
36763deb3ec6SMatthias Ringwald }
3677d1a1f6a4SMatthias Ringwald 
3678d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph3_div(void * arg){
3679f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3680f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3681f3582630SMatthias Ringwald     if (connection == NULL) return;
3682f3582630SMatthias Ringwald 
3683d1a1f6a4SMatthias Ringwald     // use 16 bit from random value as div
3684d1a1f6a4SMatthias Ringwald     setup->sm_local_div = big_endian_read_16(sm_random_data, 0);
3685d1a1f6a4SMatthias Ringwald     log_info_hex16("div", setup->sm_local_div);
3686d1a1f6a4SMatthias Ringwald     connection->sm_engine_state = SM_PH3_Y_GET_ENC;
368770b44dd4SMatthias Ringwald     sm_trigger_run();
3688d1a1f6a4SMatthias Ringwald }
3689d1a1f6a4SMatthias Ringwald 
3690d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_ph3_random(void * arg){
3691f3582630SMatthias Ringwald     hci_con_handle_t con_handle = (hci_con_handle_t) (uintptr_t) arg;
3692f3582630SMatthias Ringwald     sm_connection_t * connection = sm_get_connection_for_handle(con_handle);
3693f3582630SMatthias Ringwald     if (connection == NULL) return;
3694f3582630SMatthias Ringwald 
3695d1a1f6a4SMatthias Ringwald     reverse_64(sm_random_data, setup->sm_local_rand);
36963deb3ec6SMatthias Ringwald     // no db for encryption size hack: encryption size is stored in lowest nibble of setup->sm_local_rand
36974ea43905SMatthias Ringwald     setup->sm_local_rand[7u] = (setup->sm_local_rand[7u] & 0xf0u) + (connection->sm_actual_encryption_key_size - 1u);
36983deb3ec6SMatthias Ringwald     // no db for authenticated flag hack: store flag in bit 4 of LSB
36994ea43905SMatthias Ringwald     setup->sm_local_rand[7u] = (setup->sm_local_rand[7u] & 0xefu) + (connection->sm_connection_authenticated << 4u);
37008b3ffec5SMatthias 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);
37013deb3ec6SMatthias Ringwald }
3702899e6e02SMatthias Ringwald static void sm_validate_er_ir(void){
3703899e6e02SMatthias Ringwald     // warn about default ER/IR
37041979f09cSMatthias Ringwald     bool warning = false;
3705899e6e02SMatthias Ringwald     if (sm_ir_is_default()){
37061979f09cSMatthias Ringwald         warning = true;
3707899e6e02SMatthias Ringwald         log_error("Persistent IR not set with sm_set_ir. Use of private addresses will cause pairing issues");
3708899e6e02SMatthias Ringwald     }
3709899e6e02SMatthias Ringwald     if (sm_er_is_default()){
37101979f09cSMatthias Ringwald         warning = true;
3711899e6e02SMatthias Ringwald         log_error("Persistent ER not set with sm_set_er. Legacy Pairing LTK is not secure");
3712899e6e02SMatthias Ringwald     }
371321045273SMatthias Ringwald     if (warning) {
3714899e6e02SMatthias Ringwald         log_error("Please configure btstack_tlv to let BTstack setup ER and IR keys");
3715899e6e02SMatthias Ringwald     }
371621045273SMatthias Ringwald }
3717899e6e02SMatthias Ringwald 
3718899e6e02SMatthias Ringwald static void sm_handle_random_result_ir(void *arg){
37191979f09cSMatthias Ringwald     sm_persistent_keys_random_active = false;
37209305033eSMatthias Ringwald     if (arg != NULL){
3721899e6e02SMatthias Ringwald         // key generated, store in tlv
37224ea43905SMatthias Ringwald         int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16u);
3723899e6e02SMatthias Ringwald         log_info("Generated IR key. Store in TLV status: %d", status);
3724e0d13a19SMilanka Ringwald         UNUSED(status);
3725899e6e02SMatthias Ringwald     }
3726899e6e02SMatthias Ringwald     log_info_key("IR", sm_persistent_ir);
37278d9b6072SMatthias Ringwald     dkg_state = DKG_CALC_IRK;
3728841468bbSMatthias Ringwald 
3729841468bbSMatthias Ringwald     if (test_use_fixed_local_irk){
3730841468bbSMatthias Ringwald         log_info_key("IRK", sm_persistent_irk);
3731841468bbSMatthias Ringwald         dkg_state = DKG_CALC_DHK;
3732841468bbSMatthias Ringwald     }
3733841468bbSMatthias Ringwald 
373470b44dd4SMatthias Ringwald     sm_trigger_run();
3735899e6e02SMatthias Ringwald }
3736899e6e02SMatthias Ringwald 
3737899e6e02SMatthias Ringwald static void sm_handle_random_result_er(void *arg){
37381979f09cSMatthias Ringwald     sm_persistent_keys_random_active = false;
37399305033eSMatthias Ringwald     if (arg != 0){
3740899e6e02SMatthias Ringwald         // key generated, store in tlv
37414ea43905SMatthias Ringwald         int status = sm_tlv_impl->store_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16u);
3742899e6e02SMatthias Ringwald         log_info("Generated ER key. Store in TLV status: %d", status);
3743e0d13a19SMilanka Ringwald         UNUSED(status);
3744899e6e02SMatthias Ringwald     }
3745899e6e02SMatthias Ringwald     log_info_key("ER", sm_persistent_er);
3746899e6e02SMatthias Ringwald 
3747899e6e02SMatthias Ringwald     // try load ir
37484ea43905SMatthias Ringwald     int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','I','R'), sm_persistent_ir, 16u);
3749899e6e02SMatthias Ringwald     if (key_size == 16){
3750899e6e02SMatthias Ringwald         // ok, let's continue
3751899e6e02SMatthias Ringwald         log_info("IR from TLV");
3752899e6e02SMatthias Ringwald         sm_handle_random_result_ir( NULL );
3753899e6e02SMatthias Ringwald     } else {
3754899e6e02SMatthias Ringwald         // invalid, generate new random one
37551979f09cSMatthias Ringwald         sm_persistent_keys_random_active = true;
3756899e6e02SMatthias Ringwald         btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_ir, 16, &sm_handle_random_result_ir, &sm_persistent_ir);
3757899e6e02SMatthias Ringwald     }
3758899e6e02SMatthias Ringwald }
37593deb3ec6SMatthias Ringwald 
376050053c13SMatthias Ringwald static void sm_connection_init(sm_connection_t * sm_conn, hci_con_handle_t con_handle, uint8_t role, uint8_t peer_addr_type, bd_addr_t peer_address){
3761f664b5e8SMatthias Ringwald 
3762f664b5e8SMatthias Ringwald     // connection info
3763f664b5e8SMatthias Ringwald     sm_conn->sm_handle = con_handle;
3764f664b5e8SMatthias Ringwald     sm_conn->sm_role = role;
376550053c13SMatthias Ringwald     sm_conn->sm_peer_addr_type = peer_addr_type;
376650053c13SMatthias Ringwald     memcpy(sm_conn->sm_peer_address, peer_address, 6);
3767f664b5e8SMatthias Ringwald 
3768f664b5e8SMatthias Ringwald     // security properties
3769f664b5e8SMatthias Ringwald     sm_conn->sm_connection_encrypted = 0;
3770f664b5e8SMatthias Ringwald     sm_conn->sm_connection_authenticated = 0;
3771f664b5e8SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_UNKNOWN;
3772f664b5e8SMatthias Ringwald     sm_conn->sm_le_db_index = -1;
3773f664b5e8SMatthias Ringwald     sm_conn->sm_reencryption_active = false;
3774f664b5e8SMatthias Ringwald 
3775f664b5e8SMatthias Ringwald     // prepare CSRK lookup (does not involve setup)
3776f664b5e8SMatthias Ringwald     sm_conn->sm_irk_lookup_state = IRK_LOOKUP_W4_READY;
3777f664b5e8SMatthias Ringwald 
3778f664b5e8SMatthias Ringwald     sm_conn->sm_engine_state = SM_GENERAL_IDLE;
3779f664b5e8SMatthias Ringwald }
3780f664b5e8SMatthias Ringwald 
3781599e89daSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3782599e89daSMatthias Ringwald static void sm_event_handle_classic_encryption_event(sm_connection_t * sm_conn, hci_con_handle_t con_handle){
3783599e89daSMatthias Ringwald     // CTKD requires BR/EDR Secure Connection
3784599e89daSMatthias Ringwald     if (sm_conn->sm_connection_encrypted != 2) return;
3785599e89daSMatthias Ringwald     // prepare for pairing request
3786599e89daSMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
3787599e89daSMatthias Ringwald         sm_conn->sm_engine_state = SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST;
3788599e89daSMatthias Ringwald     } else if (sm_conn->sm_pairing_requested){
3789599e89daSMatthias Ringwald         // check if remote supports fixed channels
3790599e89daSMatthias Ringwald         bool defer = true;
3791599e89daSMatthias Ringwald         const hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
3792599e89daSMatthias Ringwald         if (hci_connection->l2cap_state.information_state == L2CAP_INFORMATION_STATE_DONE){
3793599e89daSMatthias Ringwald             // check if remote supports SMP over BR/EDR
3794599e89daSMatthias Ringwald             if ((hci_connection->l2cap_state.fixed_channels_supported & (1 << L2CAP_CID_BR_EDR_SECURITY_MANAGER)) != 0){
3795599e89daSMatthias Ringwald                 log_info("CTKD: SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST");
3796599e89daSMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST;
3797599e89daSMatthias Ringwald             } else {
3798599e89daSMatthias Ringwald                 defer = false;
3799599e89daSMatthias Ringwald             }
3800599e89daSMatthias Ringwald         } else {
3801599e89daSMatthias Ringwald             // wait for fixed channel info
3802599e89daSMatthias Ringwald             log_info("CTKD: SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK");
3803599e89daSMatthias Ringwald             sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK;
3804599e89daSMatthias Ringwald         }
3805599e89daSMatthias Ringwald         if (defer){
3806599e89daSMatthias Ringwald             hci_dedicated_bonding_defer_disconnect(con_handle, true);
3807599e89daSMatthias Ringwald         }
3808599e89daSMatthias Ringwald     }
3809599e89daSMatthias Ringwald }
3810599e89daSMatthias Ringwald #endif
3811599e89daSMatthias Ringwald 
3812d9a7306aSMatthias Ringwald static void sm_event_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
38133deb3ec6SMatthias Ringwald 
3814cbdfe9f7SMatthias Ringwald     UNUSED(channel);    // ok: there is no channel
3815cbdfe9f7SMatthias Ringwald     UNUSED(size);       // ok: fixed format HCI events
38169ec2630cSMatthias Ringwald 
38173deb3ec6SMatthias Ringwald     sm_connection_t * sm_conn;
3818711e6c80SMatthias Ringwald     hci_con_handle_t  con_handle;
3819fbe050beSMatthias Ringwald     uint8_t           status;
3820f664b5e8SMatthias Ringwald     bd_addr_t         addr;
3821d9f3ead5SMatthias Ringwald     bd_addr_type_t    addr_type;
3822f664b5e8SMatthias Ringwald 
38233deb3ec6SMatthias Ringwald     switch (packet_type) {
38243deb3ec6SMatthias Ringwald 
38253deb3ec6SMatthias Ringwald 		case HCI_EVENT_PACKET:
38260e2df43fSMatthias Ringwald 			switch (hci_event_packet_get_type(packet)) {
38273deb3ec6SMatthias Ringwald 
38283deb3ec6SMatthias Ringwald                 case BTSTACK_EVENT_STATE:
3829745015f6SMatthias Ringwald                     switch (btstack_event_state_get_state(packet)){
3830745015f6SMatthias Ringwald                         case HCI_STATE_WORKING:
38313deb3ec6SMatthias Ringwald                             log_info("HCI Working!");
3832899e6e02SMatthias Ringwald                             // setup IR/ER with TLV
3833899e6e02SMatthias Ringwald                             btstack_tlv_get_instance(&sm_tlv_impl, &sm_tlv_context);
38349305033eSMatthias Ringwald                             if (sm_tlv_impl != NULL){
38354ea43905SMatthias Ringwald                                 int key_size = sm_tlv_impl->get_tag(sm_tlv_context, BTSTACK_TAG32('S','M','E','R'), sm_persistent_er, 16u);
3836899e6e02SMatthias Ringwald                                 if (key_size == 16){
3837899e6e02SMatthias Ringwald                                     // ok, let's continue
3838899e6e02SMatthias Ringwald                                     log_info("ER from TLV");
3839899e6e02SMatthias Ringwald                                     sm_handle_random_result_er( NULL );
3840899e6e02SMatthias Ringwald                                 } else {
3841899e6e02SMatthias Ringwald                                     // invalid, generate random one
38421979f09cSMatthias Ringwald                                     sm_persistent_keys_random_active = true;
3843899e6e02SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_persistent_er, 16, &sm_handle_random_result_er, &sm_persistent_er);
3844899e6e02SMatthias Ringwald                                 }
3845899e6e02SMatthias Ringwald                             } else {
3846899e6e02SMatthias Ringwald                                 sm_validate_er_ir();
38478d9b6072SMatthias Ringwald                                 dkg_state = DKG_CALC_IRK;
3848841468bbSMatthias Ringwald 
3849841468bbSMatthias Ringwald                                 if (test_use_fixed_local_irk){
3850841468bbSMatthias Ringwald                                     log_info_key("IRK", sm_persistent_irk);
3851841468bbSMatthias Ringwald                                     dkg_state = DKG_CALC_DHK;
3852841468bbSMatthias Ringwald                                 }
3853899e6e02SMatthias Ringwald                             }
38541bf086daSMatthias Ringwald 
385515211b85SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
385615211b85SMatthias Ringwald                             // trigger ECC key generation
385715211b85SMatthias Ringwald                             if (ec_key_generation_state == EC_KEY_GENERATION_IDLE){
385815211b85SMatthias Ringwald                                 sm_ec_generate_new_key();
385915211b85SMatthias Ringwald                             }
386015211b85SMatthias Ringwald #endif
386115211b85SMatthias Ringwald 
38621bf086daSMatthias Ringwald                             // restart random address updates after power cycle
38634a688bd1SMatthias Ringwald                             if (gap_random_adress_type == GAP_RANDOM_ADDRESS_TYPE_STATIC){
38644a688bd1SMatthias Ringwald                                 gap_random_address_set(sm_random_address);
38654a688bd1SMatthias Ringwald                             } else {
38661bf086daSMatthias Ringwald                                 gap_random_address_set_mode(gap_random_adress_type);
38674a688bd1SMatthias Ringwald                             }
3868745015f6SMatthias Ringwald                             break;
3869745015f6SMatthias Ringwald 
3870745015f6SMatthias Ringwald                         case HCI_STATE_OFF:
38717f775357SMatthias Ringwald                         case HCI_STATE_HALTING:
3872cbdd51cfSMatthias Ringwald                             log_info("SM: reset state");
3873745015f6SMatthias Ringwald                             // stop random address update
3874745015f6SMatthias Ringwald                             gap_random_address_update_stop();
3875cbdd51cfSMatthias Ringwald                             // reset state
3876cbdd51cfSMatthias Ringwald                             sm_state_reset();
3877745015f6SMatthias Ringwald                             break;
3878745015f6SMatthias Ringwald 
3879745015f6SMatthias Ringwald                         default:
3880745015f6SMatthias Ringwald                             break;
38813deb3ec6SMatthias Ringwald                     }
38823deb3ec6SMatthias Ringwald 					break;
3883c18be159SMatthias Ringwald 
38842d095694SMatthias Ringwald #ifdef ENABLE_CLASSIC
38852d095694SMatthias Ringwald 			    case HCI_EVENT_CONNECTION_COMPLETE:
38862d095694SMatthias Ringwald 			        // ignore if connection failed
38872d095694SMatthias Ringwald 			        if (hci_event_connection_complete_get_status(packet)) return;
38883deb3ec6SMatthias Ringwald 
38892d095694SMatthias Ringwald 			        con_handle = hci_event_connection_complete_get_connection_handle(packet);
38902d095694SMatthias Ringwald 			        sm_conn = sm_get_connection_for_handle(con_handle);
38912d095694SMatthias Ringwald 			        if (!sm_conn) break;
38922d095694SMatthias Ringwald 
38932d095694SMatthias Ringwald                     hci_event_connection_complete_get_bd_addr(packet, addr);
38942d095694SMatthias Ringwald 			        sm_connection_init(sm_conn,
38952d095694SMatthias Ringwald                                        con_handle,
38962d095694SMatthias Ringwald                                        (uint8_t) gap_get_role(con_handle),
3897f72f7944SMatthias Ringwald                                        BD_ADDR_TYPE_LE_PUBLIC,
38982d095694SMatthias Ringwald                                        addr);
38992d095694SMatthias Ringwald 			        // classic connection corresponds to public le address
39002d095694SMatthias Ringwald 			        sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_PUBLIC;
39012d095694SMatthias Ringwald                     gap_local_bd_addr(sm_conn->sm_own_address);
39022d095694SMatthias Ringwald                     sm_conn->sm_cid = L2CAP_CID_BR_EDR_SECURITY_MANAGER;
3903c18be159SMatthias Ringwald                     sm_conn->sm_engine_state = SM_BR_EDR_W4_ENCRYPTION_COMPLETE;
39042d095694SMatthias Ringwald 			        break;
39052d095694SMatthias Ringwald #endif
3906c18be159SMatthias Ringwald 
3907c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
3908c18be159SMatthias Ringwald 			    case HCI_EVENT_SIMPLE_PAIRING_COMPLETE:
3909c18be159SMatthias Ringwald 			        if (hci_event_simple_pairing_complete_get_status(packet) != ERROR_CODE_SUCCESS) break;
3910c18be159SMatthias Ringwald                     hci_event_simple_pairing_complete_get_bd_addr(packet, addr);
3911c18be159SMatthias Ringwald                     sm_conn = sm_get_connection_for_bd_addr_and_type(addr, BD_ADDR_TYPE_ACL);
3912c18be159SMatthias Ringwald                     if (sm_conn == NULL) break;
39135f3874afSMatthias Ringwald                     sm_conn->sm_pairing_requested = true;
3914c18be159SMatthias Ringwald 			        break;
3915c18be159SMatthias Ringwald #endif
3916c18be159SMatthias Ringwald 
39179d1eff91SMatthias Ringwald 			    case HCI_EVENT_META_GAP:
39189d1eff91SMatthias Ringwald 			        switch (hci_event_gap_meta_get_subevent_code(packet)) {
39199d1eff91SMatthias Ringwald 			            case GAP_SUBEVENT_LE_CONNECTION_COMPLETE:
3920f664b5e8SMatthias Ringwald 			                // ignore if connection failed
39219d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_status(packet) != ERROR_CODE_SUCCESS) break;
39223deb3ec6SMatthias Ringwald 
39239d1eff91SMatthias Ringwald 			                con_handle = gap_subevent_le_connection_complete_get_connection_handle(packet);
3924711e6c80SMatthias Ringwald 			                sm_conn = sm_get_connection_for_handle(con_handle);
39253deb3ec6SMatthias Ringwald 			                if (!sm_conn) break;
39263deb3ec6SMatthias Ringwald 
3927d9f3ead5SMatthias Ringwald                             // Get current peer address
3928d9f3ead5SMatthias Ringwald                             addr_type = gap_subevent_le_connection_complete_get_peer_address_type(packet);
3929d9f3ead5SMatthias Ringwald                             if (hci_is_le_identity_address_type(addr_type)){
3930d9f3ead5SMatthias Ringwald                                 addr_type = BD_ADDR_TYPE_LE_RANDOM;
3931d9f3ead5SMatthias Ringwald                                 gap_subevent_le_connection_complete_get_peer_resolvable_private_address(packet, addr);
3932d9f3ead5SMatthias Ringwald                             } else {
39339d1eff91SMatthias Ringwald                                 gap_subevent_le_connection_complete_get_peer_address(packet, addr);
3934d9f3ead5SMatthias Ringwald                             }
3935f664b5e8SMatthias Ringwald 			                sm_connection_init(sm_conn,
3936f664b5e8SMatthias Ringwald                                                con_handle,
39379d1eff91SMatthias Ringwald                                                gap_subevent_le_connection_complete_get_role(packet),
3938d9f3ead5SMatthias Ringwald                                                addr_type,
3939f664b5e8SMatthias Ringwald                                                addr);
3940687a03c8SMatthias Ringwald 			                sm_conn->sm_cid = L2CAP_CID_SECURITY_MANAGER_PROTOCOL;
3941f664b5e8SMatthias Ringwald 
3942f664b5e8SMatthias Ringwald 			                // track our addr used for this connection and set state
3943b6f39a74SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
39449d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_role(packet) != 0){
3945ba9fc867SMatthias Ringwald 			                    // responder - use own address from advertisements
394667bf59ffSMatthias Ringwald #ifdef ENABLE_LE_EXTENDED_ADVERTISING
394767bf59ffSMatthias Ringwald                                 if (hci_le_extended_advertising_supported()){
394867bf59ffSMatthias Ringwald                                     // cache local resolvable address
394967bf59ffSMatthias Ringwald                                     // note: will be overwritten if random or private address was used in adv set by HCI_SUBEVENT_LE_ADVERTISING_SET_TERMINATED
395067bf59ffSMatthias Ringwald                                     sm_conn->sm_own_addr_type = BD_ADDR_TYPE_LE_RANDOM;
395167bf59ffSMatthias Ringwald                                     gap_subevent_le_connection_complete_get_local_resolvable_private_address(packet,sm_conn->sm_own_address);
395267bf59ffSMatthias Ringwald                                 } else
395367bf59ffSMatthias Ringwald #endif
395467bf59ffSMatthias Ringwald                                 {
3955ba9fc867SMatthias Ringwald                                     gap_le_get_own_advertisements_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address);
395667bf59ffSMatthias Ringwald                                 }
3957f664b5e8SMatthias Ringwald 			                    sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
3958b892db1cSMatthias Ringwald 			                }
3959b892db1cSMatthias Ringwald #endif
3960b892db1cSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
39619d1eff91SMatthias Ringwald 			                if (gap_subevent_le_connection_complete_get_role(packet) == 0){
3962ba9fc867SMatthias Ringwald 			                    // initiator - use own address from create connection
3963ba9fc867SMatthias Ringwald 			                    gap_le_get_own_connection_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address);
39643deb3ec6SMatthias Ringwald 			                    sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
39653deb3ec6SMatthias Ringwald 			                }
3966b892db1cSMatthias Ringwald #endif
39673deb3ec6SMatthias Ringwald 			                break;
39689d1eff91SMatthias Ringwald 			            default:
39699d1eff91SMatthias Ringwald 			                break;
39709d1eff91SMatthias Ringwald 			        }
39719d1eff91SMatthias Ringwald 			        break;
39729d1eff91SMatthias Ringwald                 case HCI_EVENT_LE_META:
39739d1eff91SMatthias Ringwald                     switch (hci_event_le_meta_get_subevent_code(packet)) {
397467bf59ffSMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
397567bf59ffSMatthias Ringwald #ifdef ENABLE_LE_EXTENDED_ADVERTISING
397667bf59ffSMatthias Ringwald                         case HCI_SUBEVENT_LE_ADVERTISING_SET_TERMINATED:
397767bf59ffSMatthias Ringwald                             if (hci_subevent_le_advertising_set_terminated_get_status(packet) == ERROR_CODE_SUCCESS){
397867bf59ffSMatthias Ringwald                                 uint8_t advertising_handle = hci_subevent_le_advertising_set_terminated_get_advertising_handle(packet);
397967bf59ffSMatthias Ringwald                                 con_handle = hci_subevent_le_advertising_set_terminated_get_connection_handle(packet);
398067bf59ffSMatthias Ringwald                                 sm_conn = sm_get_connection_for_handle(con_handle);
398167bf59ffSMatthias Ringwald                                 gap_le_get_own_advertising_set_address(&sm_conn->sm_own_addr_type, sm_conn->sm_own_address, advertising_handle);
398267bf59ffSMatthias Ringwald                                 log_info("Adv set %u terminated -> use addr type %u, addr %s for con handle 0x%04x", advertising_handle, sm_conn->sm_own_addr_type,
398367bf59ffSMatthias Ringwald                                          bd_addr_to_str(sm_conn->sm_own_address), con_handle);
398467bf59ffSMatthias Ringwald                             }
398567bf59ffSMatthias Ringwald                             break;
398667bf59ffSMatthias Ringwald #endif
398767bf59ffSMatthias Ringwald #endif
39883deb3ec6SMatthias Ringwald                         case HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST:
39899d1eff91SMatthias Ringwald                             con_handle = hci_subevent_le_long_term_key_request_get_connection_handle(packet);
3990711e6c80SMatthias Ringwald                             sm_conn = sm_get_connection_for_handle(con_handle);
39913deb3ec6SMatthias Ringwald                             if (!sm_conn) break;
39923deb3ec6SMatthias Ringwald 
39933deb3ec6SMatthias Ringwald                             log_info("LTK Request: state %u", sm_conn->sm_engine_state);
39943deb3ec6SMatthias Ringwald                             if (sm_conn->sm_engine_state == SM_RESPONDER_PH2_W4_LTK_REQUEST){
39953deb3ec6SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_PH2_CALC_STK;
39963deb3ec6SMatthias Ringwald                                 break;
39973deb3ec6SMatthias Ringwald                             }
3998c6b7cbd9SMatthias Ringwald                             if (sm_conn->sm_engine_state == SM_SC_W4_LTK_REQUEST_SC){
3999778b6aadSMatthias Ringwald                                 // PH2 SEND LTK as we need to exchange keys in PH3
4000778b6aadSMatthias Ringwald                                 sm_conn->sm_engine_state = SM_RESPONDER_PH2_SEND_LTK_REPLY;
4001e53be891SMatthias Ringwald                                 break;
4002e53be891SMatthias Ringwald                             }
40033deb3ec6SMatthias Ringwald 
40043deb3ec6SMatthias Ringwald                             // store rand and ediv
40059c80e4ccSMatthias Ringwald                             reverse_64(&packet[5], sm_conn->sm_local_rand);
40069d1eff91SMatthias Ringwald                             sm_conn->sm_local_ediv = hci_subevent_le_long_term_key_request_get_encryption_diversifier(packet);
4007549ad5d2SMatthias Ringwald 
4008549ad5d2SMatthias Ringwald                             // For Legacy Pairing (<=> EDIV != 0 || RAND != NULL), we need to recalculated our LTK as a
4009549ad5d2SMatthias Ringwald                             // potentially stored LTK is from the master
40104ea43905SMatthias Ringwald                             if ((sm_conn->sm_local_ediv != 0u) || !sm_is_null_random(sm_conn->sm_local_rand)){
40116c39055aSMatthias Ringwald                                 if (sm_reconstruct_ltk_without_le_device_db_entry){
401206cd539fSMatthias Ringwald                                     sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
4013549ad5d2SMatthias Ringwald                                     break;
4014549ad5d2SMatthias Ringwald                                 }
40156c39055aSMatthias Ringwald                                 // additionally check if remote is in LE Device DB if requested
40166c39055aSMatthias Ringwald                                 switch(sm_conn->sm_irk_lookup_state){
40176c39055aSMatthias Ringwald                                     case IRK_LOOKUP_FAILED:
40186c39055aSMatthias Ringwald                                         log_info("LTK Request: device not in device db");
40196c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
40206c39055aSMatthias Ringwald                                         break;
40216c39055aSMatthias Ringwald                                     case IRK_LOOKUP_SUCCEEDED:
40226c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_REQUEST;
40236c39055aSMatthias Ringwald                                         break;
40246c39055aSMatthias Ringwald                                     default:
40256c39055aSMatthias Ringwald                                         // wait for irk look doen
40266c39055aSMatthias Ringwald                                         sm_conn->sm_engine_state = SM_RESPONDER_PH0_RECEIVED_LTK_W4_IRK;
40276c39055aSMatthias Ringwald                                         break;
40286c39055aSMatthias Ringwald                                 }
40296c39055aSMatthias Ringwald                                 break;
40306c39055aSMatthias Ringwald                             }
4031549ad5d2SMatthias Ringwald 
4032549ad5d2SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
403306cd539fSMatthias Ringwald                             sm_conn->sm_engine_state = SM_SC_RECEIVED_LTK_REQUEST;
4034549ad5d2SMatthias Ringwald #else
4035549ad5d2SMatthias Ringwald                             log_info("LTK Request: ediv & random are empty, but LE Secure Connections not supported");
4036549ad5d2SMatthias Ringwald                             sm_conn->sm_engine_state = SM_RESPONDER_PH0_SEND_LTK_REQUESTED_NEGATIVE_REPLY;
4037549ad5d2SMatthias Ringwald #endif
40383deb3ec6SMatthias Ringwald                             break;
4039804d3e67SMatthias Ringwald 
40403deb3ec6SMatthias Ringwald                         default:
40413deb3ec6SMatthias Ringwald                             break;
40423deb3ec6SMatthias Ringwald                     }
40433deb3ec6SMatthias Ringwald                     break;
40443deb3ec6SMatthias Ringwald 
40453deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE:
40468601e696SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_CHANGE_V2:
40473b7fd749SMatthias Ringwald                 	con_handle = hci_event_encryption_change_get_connection_handle(packet);
4048711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
40493deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
40503deb3ec6SMatthias Ringwald 
40513b7fd749SMatthias Ringwald                     sm_conn->sm_connection_encrypted = hci_event_encryption_change_get_encryption_enabled(packet);
40523deb3ec6SMatthias Ringwald                     log_info("Encryption state change: %u, key size %u", sm_conn->sm_connection_encrypted,
40533deb3ec6SMatthias Ringwald                         sm_conn->sm_actual_encryption_key_size);
40543deb3ec6SMatthias Ringwald                     log_info("event handler, state %u", sm_conn->sm_engine_state);
405503a9359aSMatthias Ringwald 
4056fbe050beSMatthias Ringwald                     switch (sm_conn->sm_engine_state){
4057fbe050beSMatthias Ringwald 
40585567aa60SMatthias Ringwald                         case SM_PH4_W4_CONNECTION_ENCRYPTED:
405903a9359aSMatthias Ringwald                             // encryption change event concludes re-encryption for bonded devices (even if it fails)
40601d80f1e6SMatthias Ringwald                             if (sm_conn->sm_connection_encrypted != 0u) {
4061fbe050beSMatthias Ringwald                                 status = ERROR_CODE_SUCCESS;
40621d80f1e6SMatthias Ringwald                                 if (IS_RESPONDER(sm_conn->sm_role)){
40638d4eef95SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
40648d4eef95SMatthias Ringwald                                 } else {
406503a9359aSMatthias Ringwald                                     sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
40668d4eef95SMatthias Ringwald                                 }
4067fbe050beSMatthias Ringwald                             } else {
4068e28291c1SMatthias Ringwald                                 status = hci_event_encryption_change_get_status(packet);
4069cb6d7eb0SMatthias Ringwald                                 // set state to 'RE-ENCRYPTION FAILED' to allow pairing but prevent other interactions
40703b7fd749SMatthias Ringwald                                 // also, gap_reconnect_security_setup_active will return true
4071cb6d7eb0SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_GENERAL_REENCRYPTION_FAILED;
40723b7fd749SMatthias Ringwald                             }
4073fbe050beSMatthias Ringwald 
4074fbe050beSMatthias Ringwald                             // emit re-encryption complete
407573102768SMatthias Ringwald                             sm_reencryption_complete(sm_conn, status);
4076fbe050beSMatthias Ringwald 
4077c245ca32SMatthias Ringwald                             // notify client, if pairing was requested before
4078c245ca32SMatthias Ringwald                             if (sm_conn->sm_pairing_requested){
40795f3874afSMatthias Ringwald                                 sm_conn->sm_pairing_requested = false;
40800ccf6c9cSMatthias Ringwald                                 sm_pairing_complete(sm_conn, status, 0);
408103a9359aSMatthias Ringwald                             }
408203a9359aSMatthias Ringwald 
40833deb3ec6SMatthias Ringwald                             sm_done_for_handle(sm_conn->sm_handle);
40843deb3ec6SMatthias Ringwald                             break;
4085fbe050beSMatthias Ringwald 
40863deb3ec6SMatthias Ringwald                         case SM_PH2_W4_CONNECTION_ENCRYPTED:
4087fbe050beSMatthias Ringwald                             if (!sm_conn->sm_connection_encrypted) break;
408857ff4745SMatthias Ringwald                             // handler for HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE
408957ff4745SMatthias Ringwald                             // contains the same code for this state
4090dd583d9fSMatthias Ringwald                             sm_conn->sm_connection_sc = setup->sm_use_secure_connections;
409142134bc6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
40923deb3ec6SMatthias Ringwald                                 // slave
409357ff4745SMatthias Ringwald                                 if (sm_conn->sm_connection_sc){
4094bbf8db22SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
4095bbf8db22SMatthias Ringwald                                 } else {
4096f3582630SMatthias 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);
4097bbf8db22SMatthias Ringwald                                 }
40983deb3ec6SMatthias Ringwald                             } else {
40993deb3ec6SMatthias Ringwald                                 // master
410061d1a45eSMatthias Ringwald                                 if (sm_key_distribution_all_received()){
41013deb3ec6SMatthias Ringwald                                     // skip receiving keys as there are none
41023deb3ec6SMatthias Ringwald                                     sm_key_distribution_handle_all_received(sm_conn);
4103f3582630SMatthias 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);
41043deb3ec6SMatthias Ringwald                                 } else {
41053deb3ec6SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
41063deb3ec6SMatthias Ringwald                                 }
41073deb3ec6SMatthias Ringwald                             }
41083deb3ec6SMatthias Ringwald                             break;
4109c18be159SMatthias Ringwald 
4110c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4111c18be159SMatthias Ringwald                         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
4112599e89daSMatthias Ringwald                             sm_event_handle_classic_encryption_event(sm_conn, con_handle);
4113c18be159SMatthias Ringwald                             break;
4114c18be159SMatthias Ringwald #endif
41153deb3ec6SMatthias Ringwald                         default:
41163deb3ec6SMatthias Ringwald                             break;
41173deb3ec6SMatthias Ringwald                     }
41183deb3ec6SMatthias Ringwald                     break;
41193deb3ec6SMatthias Ringwald 
41203deb3ec6SMatthias Ringwald                 case HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE:
4121711e6c80SMatthias Ringwald                     con_handle = little_endian_read_16(packet, 3);
4122711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
41233deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
41243deb3ec6SMatthias Ringwald 
41253deb3ec6SMatthias Ringwald                     log_info("Encryption key refresh complete, key size %u", sm_conn->sm_actual_encryption_key_size);
41263deb3ec6SMatthias Ringwald                     log_info("event handler, state %u", sm_conn->sm_engine_state);
41273deb3ec6SMatthias Ringwald                     // continue if part of initial pairing
41283deb3ec6SMatthias Ringwald                     switch (sm_conn->sm_engine_state){
41295567aa60SMatthias Ringwald                         case SM_PH4_W4_CONNECTION_ENCRYPTED:
41301d80f1e6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
41315567aa60SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_RESPONDER_IDLE;
41325567aa60SMatthias Ringwald                             } else {
41333deb3ec6SMatthias Ringwald                                 sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
41345567aa60SMatthias Ringwald                             }
41353deb3ec6SMatthias Ringwald                             sm_done_for_handle(sm_conn->sm_handle);
41363deb3ec6SMatthias Ringwald                             break;
41373deb3ec6SMatthias Ringwald                         case SM_PH2_W4_CONNECTION_ENCRYPTED:
413857ff4745SMatthias Ringwald                             // handler for HCI_EVENT_ENCRYPTION_CHANGE
413957ff4745SMatthias Ringwald                             // contains the same code for this state
414057ff4745SMatthias Ringwald                             sm_conn->sm_connection_sc = setup->sm_use_secure_connections;
414142134bc6SMatthias Ringwald                             if (IS_RESPONDER(sm_conn->sm_role)){
41423deb3ec6SMatthias Ringwald                                 // slave
414357ff4745SMatthias Ringwald                                 if (sm_conn->sm_connection_sc){
414457ff4745SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
414557ff4745SMatthias Ringwald                                 } else {
4146f3582630SMatthias Ringwald                                     btstack_crypto_random_generate(&sm_crypto_random_request, sm_random_data, 8, &sm_handle_random_result_ph3_random, (void *)(uintptr_t) sm_conn->sm_handle);
414757ff4745SMatthias Ringwald                                 }
41483deb3ec6SMatthias Ringwald                             } else {
41493deb3ec6SMatthias Ringwald                                 // master
415057ff4745SMatthias Ringwald                                 if (sm_key_distribution_all_received()){
415157ff4745SMatthias Ringwald                                     // skip receiving keys as there are none
415257ff4745SMatthias Ringwald                                     sm_key_distribution_handle_all_received(sm_conn);
415357ff4745SMatthias 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);
415457ff4745SMatthias Ringwald                                 } else {
41553deb3ec6SMatthias Ringwald                                     sm_conn->sm_engine_state = SM_PH3_RECEIVE_KEYS;
41563deb3ec6SMatthias Ringwald                                 }
415757ff4745SMatthias Ringwald                             }
41583deb3ec6SMatthias Ringwald                             break;
415994219034SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
416094219034SMatthias Ringwald                         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
416194219034SMatthias Ringwald                             sm_event_handle_classic_encryption_event(sm_conn, con_handle);
416294219034SMatthias Ringwald                             break;
416394219034SMatthias Ringwald #endif
41643deb3ec6SMatthias Ringwald                         default:
41653deb3ec6SMatthias Ringwald                             break;
41663deb3ec6SMatthias Ringwald                     }
41673deb3ec6SMatthias Ringwald                     break;
41683deb3ec6SMatthias Ringwald 
41693deb3ec6SMatthias Ringwald 
41703deb3ec6SMatthias Ringwald                 case HCI_EVENT_DISCONNECTION_COMPLETE:
4171711e6c80SMatthias Ringwald                     con_handle = little_endian_read_16(packet, 3);
4172711e6c80SMatthias Ringwald                     sm_done_for_handle(con_handle);
4173711e6c80SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
41743deb3ec6SMatthias Ringwald                     if (!sm_conn) break;
41753deb3ec6SMatthias Ringwald 
417603f736b1SMatthias Ringwald                     // pairing failed, if it was ongoing
41777f3f442dSMatthias Ringwald                     switch (sm_conn->sm_engine_state){
41787f3f442dSMatthias Ringwald                         case SM_GENERAL_IDLE:
41797f3f442dSMatthias Ringwald                         case SM_INITIATOR_CONNECTED:
41807f3f442dSMatthias Ringwald                         case SM_RESPONDER_IDLE:
41817f3f442dSMatthias Ringwald                             break;
41827f3f442dSMatthias Ringwald                         default:
418368a18fb9SMatthias Ringwald                             sm_reencryption_complete(sm_conn, ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION);
41840ccf6c9cSMatthias Ringwald                             sm_pairing_complete(sm_conn, ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION, 0);
41857f3f442dSMatthias Ringwald                             break;
418603f736b1SMatthias Ringwald                     }
4187accbde80SMatthias Ringwald 
41883deb3ec6SMatthias Ringwald                     sm_conn->sm_engine_state = SM_GENERAL_IDLE;
41893deb3ec6SMatthias Ringwald                     sm_conn->sm_handle = 0;
41903deb3ec6SMatthias Ringwald                     break;
41913deb3ec6SMatthias Ringwald 
41923deb3ec6SMatthias Ringwald                 case HCI_EVENT_COMMAND_COMPLETE:
4193f7811256SMatthias Ringwald                     if (hci_event_command_complete_get_command_opcode(packet) == HCI_OPCODE_HCI_READ_BD_ADDR) {
41949091c5f5SMatthias Ringwald                         // set local addr for le device db
419533373e40SMatthias Ringwald                         reverse_bd_addr(&packet[OFFSET_OF_DATA_IN_COMMAND_COMPLETE + 1], addr);
41960c130b19SMatthias Ringwald                         le_device_db_set_local_bd_addr(addr);
419733373e40SMatthias Ringwald                     }
419865b44ffdSMatthias Ringwald                     break;
4199a036ae12SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4200a036ae12SMatthias Ringwald                 case L2CAP_EVENT_INFORMATION_RESPONSE:
4201a036ae12SMatthias Ringwald                     con_handle = l2cap_event_information_response_get_con_handle(packet);
4202a036ae12SMatthias Ringwald                     sm_conn = sm_get_connection_for_handle(con_handle);
4203a036ae12SMatthias Ringwald                     if (!sm_conn) break;
4204a036ae12SMatthias Ringwald                     if (sm_conn->sm_engine_state == SM_BR_EDR_INITIATOR_W4_FIXED_CHANNEL_MASK){
4205a036ae12SMatthias Ringwald                         // check if remote supports SMP over BR/EDR
4206a036ae12SMatthias Ringwald                         const hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
4207a036ae12SMatthias Ringwald                         if ((hci_connection->l2cap_state.fixed_channels_supported & (1 << L2CAP_CID_BR_EDR_SECURITY_MANAGER)) != 0){
4208a036ae12SMatthias Ringwald                             sm_conn->sm_engine_state = SM_BR_EDR_INITIATOR_SEND_PAIRING_REQUEST;
4209a036ae12SMatthias Ringwald                         } else {
4210a036ae12SMatthias Ringwald                             sm_conn->sm_engine_state = SM_INITIATOR_CONNECTED;
4211f82b8f4bSMatthias Ringwald                             hci_dedicated_bonding_defer_disconnect(con_handle, false);
4212a036ae12SMatthias Ringwald                         }
4213a036ae12SMatthias Ringwald                     }
4214a036ae12SMatthias Ringwald                     break;
4215a036ae12SMatthias Ringwald #endif
421665b44ffdSMatthias Ringwald                 default:
421765b44ffdSMatthias Ringwald                     break;
42183deb3ec6SMatthias Ringwald 			}
421965b44ffdSMatthias Ringwald             break;
422065b44ffdSMatthias Ringwald         default:
422165b44ffdSMatthias Ringwald             break;
42223deb3ec6SMatthias Ringwald 	}
42233deb3ec6SMatthias Ringwald 
42243deb3ec6SMatthias Ringwald     sm_run();
42253deb3ec6SMatthias Ringwald }
42263deb3ec6SMatthias Ringwald 
42273deb3ec6SMatthias Ringwald static inline int sm_calc_actual_encryption_key_size(int other){
42283deb3ec6SMatthias Ringwald     if (other < sm_min_encryption_key_size) return 0;
42293deb3ec6SMatthias Ringwald     if (other < sm_max_encryption_key_size) return other;
42303deb3ec6SMatthias Ringwald     return sm_max_encryption_key_size;
42313deb3ec6SMatthias Ringwald }
42323deb3ec6SMatthias Ringwald 
4233945888f5SMatthias Ringwald 
423431c09488SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
42351d80f1e6SMatthias Ringwald static bool sm_just_works_or_numeric_comparison(stk_generation_method_t method){
4236945888f5SMatthias Ringwald     switch (method){
4237945888f5SMatthias Ringwald         case JUST_WORKS:
423847fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
42391d80f1e6SMatthias Ringwald             return true;
4240945888f5SMatthias Ringwald         default:
42411d80f1e6SMatthias Ringwald             return false;
4242945888f5SMatthias Ringwald     }
4243945888f5SMatthias Ringwald }
424407036a04SMatthias Ringwald // responder
4245945888f5SMatthias Ringwald 
42461d80f1e6SMatthias Ringwald static bool sm_passkey_used(stk_generation_method_t method){
4247688a08f9SMatthias Ringwald     switch (method){
4248688a08f9SMatthias Ringwald         case PK_RESP_INPUT:
42491d80f1e6SMatthias Ringwald             return true;
4250688a08f9SMatthias Ringwald         default:
4251688a08f9SMatthias Ringwald             return 0;
4252688a08f9SMatthias Ringwald     }
4253688a08f9SMatthias Ringwald }
425440c5d850SMatthias Ringwald 
42556777d8fdSMatthias Ringwald static bool sm_passkey_entry(stk_generation_method_t method){
425640c5d850SMatthias Ringwald     switch (method){
425740c5d850SMatthias Ringwald         case PK_RESP_INPUT:
425840c5d850SMatthias Ringwald         case PK_INIT_INPUT:
425947fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
42606777d8fdSMatthias Ringwald             return true;
426140c5d850SMatthias Ringwald         default:
42626777d8fdSMatthias Ringwald             return false;
426340c5d850SMatthias Ringwald     }
426440c5d850SMatthias Ringwald }
426540c5d850SMatthias Ringwald 
426631c09488SMatthias Ringwald #endif
4267688a08f9SMatthias Ringwald 
42683deb3ec6SMatthias Ringwald /**
42693deb3ec6SMatthias Ringwald  * @return ok
42703deb3ec6SMatthias Ringwald  */
42713deb3ec6SMatthias Ringwald static int sm_validate_stk_generation_method(void){
42723deb3ec6SMatthias Ringwald     // check if STK generation method is acceptable by client
42733deb3ec6SMatthias Ringwald     switch (setup->sm_stk_generation_method){
42743deb3ec6SMatthias Ringwald         case JUST_WORKS:
42754ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_JUST_WORKS) != 0u;
42763deb3ec6SMatthias Ringwald         case PK_RESP_INPUT:
42773deb3ec6SMatthias Ringwald         case PK_INIT_INPUT:
427847fb4255SMatthias Ringwald         case PK_BOTH_INPUT:
42794ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_PASSKEY) != 0u;
42803deb3ec6SMatthias Ringwald         case OOB:
42814ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_OOB) != 0u;
428247fb4255SMatthias Ringwald         case NUMERIC_COMPARISON:
42834ea43905SMatthias Ringwald             return (sm_accepted_stk_generation_methods & SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON) != 0u;
42843deb3ec6SMatthias Ringwald         default:
42853deb3ec6SMatthias Ringwald             return 0;
42863deb3ec6SMatthias Ringwald     }
42873deb3ec6SMatthias Ringwald }
42883deb3ec6SMatthias Ringwald 
428936f0defaSMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
429036f0defaSMatthias Ringwald static void sm_initiator_connected_handle_security_request(sm_connection_t * sm_conn, const uint8_t *packet){
429136f0defaSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
429236f0defaSMatthias Ringwald     if (sm_sc_only_mode){
429336f0defaSMatthias Ringwald         uint8_t auth_req = packet[1];
429436f0defaSMatthias Ringwald         if ((auth_req & SM_AUTHREQ_SECURE_CONNECTION) == 0){
429536f0defaSMatthias Ringwald             sm_pairing_error(sm_conn, SM_REASON_AUTHENTHICATION_REQUIREMENTS);
429636f0defaSMatthias Ringwald             return;
429736f0defaSMatthias Ringwald         }
429836f0defaSMatthias Ringwald     }
429936f0defaSMatthias Ringwald #else
430036f0defaSMatthias Ringwald     UNUSED(packet);
430136f0defaSMatthias Ringwald #endif
430236f0defaSMatthias Ringwald 
430336f0defaSMatthias Ringwald     int have_ltk;
430436f0defaSMatthias Ringwald     uint8_t ltk[16];
430536f0defaSMatthias Ringwald 
430636f0defaSMatthias Ringwald     // IRK complete?
430736f0defaSMatthias Ringwald     switch (sm_conn->sm_irk_lookup_state){
430836f0defaSMatthias Ringwald         case IRK_LOOKUP_FAILED:
430936f0defaSMatthias Ringwald             // start pairing
431036f0defaSMatthias Ringwald             sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
431136f0defaSMatthias Ringwald             break;
431236f0defaSMatthias Ringwald         case IRK_LOOKUP_SUCCEEDED:
431336f0defaSMatthias Ringwald             le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
431436f0defaSMatthias Ringwald             have_ltk = !sm_is_null_key(ltk);
431536f0defaSMatthias Ringwald             log_info("central: security request - have_ltk %u, encryption %u", have_ltk, sm_conn->sm_connection_encrypted);
431636f0defaSMatthias Ringwald             if (have_ltk && (sm_conn->sm_connection_encrypted == 0)){
431736f0defaSMatthias Ringwald                 // start re-encrypt if we have LTK and the connection is not already encrypted
431836f0defaSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
431936f0defaSMatthias Ringwald             } else {
432036f0defaSMatthias Ringwald                 // start pairing
432136f0defaSMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
432236f0defaSMatthias Ringwald             }
432336f0defaSMatthias Ringwald             break;
432436f0defaSMatthias Ringwald         default:
432536f0defaSMatthias Ringwald             // otherwise, store security request
43260dcaa15fSMatthias Ringwald             sm_conn->sm_security_request_received = true;
432736f0defaSMatthias Ringwald             break;
432836f0defaSMatthias Ringwald     }
432936f0defaSMatthias Ringwald }
433036f0defaSMatthias Ringwald #endif
433136f0defaSMatthias Ringwald 
4332f9bda154SMatthias Ringwald static uint8_t sm_pdu_validate_and_get_opcode(uint8_t packet_type, const uint8_t *packet, uint16_t size){
43338334d3d8SMatthias Ringwald 
43344c1d1092SMatthias Ringwald     // size of complete sm_pdu used to validate input
43354c1d1092SMatthias Ringwald     static const uint8_t sm_pdu_size[] = {
43364c1d1092SMatthias Ringwald             0,  // 0x00 invalid opcode
43374c1d1092SMatthias Ringwald             7,  // 0x01 pairing request
43384c1d1092SMatthias Ringwald             7,  // 0x02 pairing response
43394c1d1092SMatthias Ringwald             17, // 0x03 pairing confirm
43404c1d1092SMatthias Ringwald             17, // 0x04 pairing random
43414c1d1092SMatthias Ringwald             2,  // 0x05 pairing failed
43424c1d1092SMatthias Ringwald             17, // 0x06 encryption information
43437a2e6387SMatthias Ringwald             11, // 0x07 master identification
43444c1d1092SMatthias Ringwald             17, // 0x08 identification information
43454c1d1092SMatthias Ringwald             8,  // 0x09 identify address information
43464c1d1092SMatthias Ringwald             17, // 0x0a signing information
43474c1d1092SMatthias Ringwald             2,  // 0x0b security request
43484c1d1092SMatthias Ringwald             65, // 0x0c pairing public key
43494c1d1092SMatthias Ringwald             17, // 0x0d pairing dhk check
43504c1d1092SMatthias Ringwald             2,  // 0x0e keypress notification
43514c1d1092SMatthias Ringwald     };
43523deb3ec6SMatthias Ringwald 
4353f9bda154SMatthias Ringwald     if (packet_type != SM_DATA_PACKET) return 0;
4354f9bda154SMatthias Ringwald     if (size == 0u) return 0;
43554c1d1092SMatthias Ringwald 
43564c1d1092SMatthias Ringwald     uint8_t sm_pdu_code = packet[0];
43574c1d1092SMatthias Ringwald 
43584c1d1092SMatthias Ringwald     // validate pdu size
4359f9bda154SMatthias Ringwald     if (sm_pdu_code >= sizeof(sm_pdu_size)) return 0;
4360f9bda154SMatthias Ringwald     if (sm_pdu_size[sm_pdu_code] != size)   return 0;
4361f9bda154SMatthias Ringwald 
4362f9bda154SMatthias Ringwald     return sm_pdu_code;
4363f9bda154SMatthias Ringwald }
4364f9bda154SMatthias Ringwald 
4365f9bda154SMatthias Ringwald static void sm_pdu_handler(uint8_t packet_type, hci_con_handle_t con_handle, uint8_t *packet, uint16_t size){
4366f9bda154SMatthias Ringwald 
4367f9bda154SMatthias Ringwald     if ((packet_type == HCI_EVENT_PACKET) && (packet[0] == L2CAP_EVENT_CAN_SEND_NOW)){
4368f9bda154SMatthias Ringwald         sm_run();
4369f9bda154SMatthias Ringwald     }
4370f9bda154SMatthias Ringwald 
4371f9bda154SMatthias Ringwald     uint8_t sm_pdu_code = sm_pdu_validate_and_get_opcode(packet_type, packet, size);
4372f9bda154SMatthias Ringwald     if (sm_pdu_code == 0) return;
43733deb3ec6SMatthias Ringwald 
4374711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
43753deb3ec6SMatthias Ringwald     if (!sm_conn) return;
43763deb3ec6SMatthias Ringwald 
43774c1d1092SMatthias Ringwald     if (sm_pdu_code == SM_CODE_PAIRING_FAILED){
437868a18fb9SMatthias Ringwald         sm_reencryption_complete(sm_conn, ERROR_CODE_AUTHENTICATION_FAILURE);
43790ccf6c9cSMatthias Ringwald         sm_pairing_complete(sm_conn, ERROR_CODE_AUTHENTICATION_FAILURE, packet[1]);
4380accbde80SMatthias Ringwald         sm_done_for_handle(con_handle);
43813deb3ec6SMatthias Ringwald         sm_conn->sm_engine_state = sm_conn->sm_role ? SM_RESPONDER_IDLE : SM_INITIATOR_CONNECTED;
43823deb3ec6SMatthias Ringwald         return;
43833deb3ec6SMatthias Ringwald     }
43843deb3ec6SMatthias Ringwald 
43854c1d1092SMatthias Ringwald     if (sm_pdu_code == SM_CODE_KEYPRESS_NOTIFICATION){
43863d7fe1e9SMatthias Ringwald         uint8_t buffer[5];
43873d7fe1e9SMatthias Ringwald         buffer[0] = SM_EVENT_KEYPRESS_NOTIFICATION;
43883d7fe1e9SMatthias Ringwald         buffer[1] = 3;
43893d7fe1e9SMatthias Ringwald         little_endian_store_16(buffer, 2, con_handle);
43903d7fe1e9SMatthias Ringwald         buffer[4] = packet[1];
43913d7fe1e9SMatthias Ringwald         sm_dispatch_event(HCI_EVENT_PACKET, 0, buffer, sizeof(buffer));
43923d7fe1e9SMatthias Ringwald         return;
43933d7fe1e9SMatthias Ringwald     }
43943d7fe1e9SMatthias Ringwald 
4395*6e46ecceSMatthias Ringwald     log_debug("sm_pdu_handler: state %u, pdu 0x%02x", sm_conn->sm_engine_state, sm_pdu_code);
4396*6e46ecceSMatthias Ringwald 
4397*6e46ecceSMatthias Ringwald     int err;
4398*6e46ecceSMatthias Ringwald     uint8_t max_encryption_key_size;
4399*6e46ecceSMatthias Ringwald     UNUSED(err);
4400*6e46ecceSMatthias Ringwald 
44013deb3ec6SMatthias Ringwald     switch (sm_conn->sm_engine_state){
44023deb3ec6SMatthias Ringwald 
4403c8d0ff33SMatthias Ringwald         // a sm timeout requires a new physical connection
44043deb3ec6SMatthias Ringwald         case SM_GENERAL_TIMEOUT:
44053deb3ec6SMatthias Ringwald             return;
44063deb3ec6SMatthias Ringwald 
440742134bc6SMatthias Ringwald #ifdef ENABLE_LE_CENTRAL
440842134bc6SMatthias Ringwald 
44093deb3ec6SMatthias Ringwald         // Initiator
44103deb3ec6SMatthias Ringwald         case SM_INITIATOR_CONNECTED:
44114c1d1092SMatthias Ringwald             if ((sm_pdu_code != SM_CODE_SECURITY_REQUEST) || (sm_conn->sm_role)){
44123deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44133deb3ec6SMatthias Ringwald                 break;
44143deb3ec6SMatthias Ringwald             }
441536f0defaSMatthias Ringwald             sm_initiator_connected_handle_security_request(sm_conn, packet);
4416dc8ca372SMatthias Ringwald             break;
44173deb3ec6SMatthias Ringwald 
44183deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH1_W4_PAIRING_RESPONSE:
4419aacfafc3SMatthias Ringwald             // Core 5, Vol 3, Part H, 2.4.6:
4420aacfafc3SMatthias Ringwald             // "The master shall ignore the slave’s Security Request if the master has sent a Pairing Request
4421aacfafc3SMatthias Ringwald             //  without receiving a Pairing Response from the slave or if the master has initiated encryption mode setup."
4422aacfafc3SMatthias Ringwald             if (sm_pdu_code == SM_CODE_SECURITY_REQUEST){
4423aacfafc3SMatthias Ringwald                 log_info("Ignoring Security Request");
4424aacfafc3SMatthias Ringwald                 break;
4425aacfafc3SMatthias Ringwald             }
4426aacfafc3SMatthias Ringwald 
4427aacfafc3SMatthias Ringwald             // all other pdus are incorrect
44284c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RESPONSE){
44293deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44303deb3ec6SMatthias Ringwald                 break;
44313deb3ec6SMatthias Ringwald             }
44320af429c6SMatthias Ringwald 
44333deb3ec6SMatthias Ringwald             // store pairing request
44346535961aSMatthias Ringwald             (void)memcpy(&setup->sm_s_pres, packet,
44356535961aSMatthias Ringwald                          sizeof(sm_pairing_packet_t));
4436afbd946dSMatthias Ringwald 
4437afbd946dSMatthias Ringwald             // validate encryption key size
4438afbd946dSMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(setup->sm_s_pres);
4439afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4440afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4441afbd946dSMatthias Ringwald                 break;
4442afbd946dSMatthias Ringwald             }
4443afbd946dSMatthias Ringwald 
44443deb3ec6SMatthias Ringwald             err = sm_stk_generation_init(sm_conn);
44450af429c6SMatthias Ringwald 
44460af429c6SMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
44470af429c6SMatthias Ringwald             if (0 < test_pairing_failure && test_pairing_failure < SM_REASON_DHKEY_CHECK_FAILED){
44480af429c6SMatthias Ringwald                 log_info("testing_support: abort with pairing failure %u", test_pairing_failure);
44490af429c6SMatthias Ringwald                 err = test_pairing_failure;
44500af429c6SMatthias Ringwald             }
44510af429c6SMatthias Ringwald #endif
44520af429c6SMatthias Ringwald 
44539305033eSMatthias Ringwald             if (err != 0){
4454f4935286SMatthias Ringwald                 sm_pairing_error(sm_conn, err);
44553deb3ec6SMatthias Ringwald                 break;
44563deb3ec6SMatthias Ringwald             }
4457b41539d5SMatthias Ringwald 
4458b41539d5SMatthias Ringwald             // generate random number first, if we need to show passkey
4459b41539d5SMatthias Ringwald             if (setup->sm_stk_generation_method == PK_RESP_INPUT){
4460f3582630SMatthias 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);
4461b41539d5SMatthias Ringwald                 break;
4462b41539d5SMatthias Ringwald             }
4463b41539d5SMatthias Ringwald 
4464136d331aSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4465136d331aSMatthias Ringwald             if (setup->sm_use_secure_connections){
44668cba5ca3SMatthias Ringwald                 // SC Numeric Comparison will trigger user response after public keys & nonces have been exchanged
44678cba5ca3SMatthias Ringwald                 if (setup->sm_stk_generation_method == JUST_WORKS){
4468136d331aSMatthias Ringwald                     sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
4469136d331aSMatthias Ringwald                     sm_trigger_user_response(sm_conn);
4470136d331aSMatthias Ringwald                     if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
4471c6b7cbd9SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
4472136d331aSMatthias Ringwald                     }
44738cba5ca3SMatthias Ringwald                 } else {
4474c6b7cbd9SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
44758cba5ca3SMatthias Ringwald                 }
4476136d331aSMatthias Ringwald                 break;
4477136d331aSMatthias Ringwald             }
4478136d331aSMatthias Ringwald #endif
44793deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
44803deb3ec6SMatthias Ringwald             sm_trigger_user_response(sm_conn);
44813deb3ec6SMatthias Ringwald             // response_idle == nothing <--> sm_trigger_user_response() did not require response
44823deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_IDLE){
4483f3582630SMatthias 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);
44843deb3ec6SMatthias Ringwald             }
44853deb3ec6SMatthias Ringwald             break;
44863deb3ec6SMatthias Ringwald 
44873deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH2_W4_PAIRING_CONFIRM:
44884c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
44893deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
44903deb3ec6SMatthias Ringwald                 break;
44913deb3ec6SMatthias Ringwald             }
44923deb3ec6SMatthias Ringwald 
44933deb3ec6SMatthias Ringwald             // store s_confirm
44949c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
4495192365feSMatthias Ringwald 
4496aa9b34e5SMatthias Ringwald             // abort if s_confirm matches m_confirm
4497aa9b34e5SMatthias Ringwald             if (memcmp(setup->sm_local_confirm, setup->sm_peer_confirm, 16) == 0){
4498aa9b34e5SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4499aa9b34e5SMatthias Ringwald                 break;
4500aa9b34e5SMatthias Ringwald             }
4501aa9b34e5SMatthias Ringwald 
4502192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4503192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4504192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4505192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4506192365feSMatthias Ringwald             }
4507192365feSMatthias Ringwald #endif
45083deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_SEND_PAIRING_RANDOM;
45093deb3ec6SMatthias Ringwald             break;
45103deb3ec6SMatthias Ringwald 
45113deb3ec6SMatthias Ringwald         case SM_INITIATOR_PH2_W4_PAIRING_RANDOM:
45124c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
45133deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
45143deb3ec6SMatthias Ringwald                 break;;
45153deb3ec6SMatthias Ringwald             }
45163deb3ec6SMatthias Ringwald 
45173deb3ec6SMatthias Ringwald             // received random value
45189c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_random);
45193deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
45203deb3ec6SMatthias Ringwald             break;
4521dc542de1SMatthias Ringwald 
4522e2a5eb63SMatthias Ringwald         case SM_INITIATOR_PH4_HAS_LTK:
4523dc542de1SMatthias Ringwald         case SM_PH4_W4_CONNECTION_ENCRYPTED:
4524dc542de1SMatthias Ringwald             // ignore Security Request, see SM_INITIATOR_PH1_W4_PAIRING_RESPONSE above
4525dc542de1SMatthias Ringwald             if (sm_pdu_code != SM_CODE_SECURITY_REQUEST){
4526dc542de1SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4527dc542de1SMatthias Ringwald             }
4528dc542de1SMatthias Ringwald             break;
452942134bc6SMatthias Ringwald #endif
45303deb3ec6SMatthias Ringwald 
453142134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
45323deb3ec6SMatthias Ringwald         // Responder
45333deb3ec6SMatthias Ringwald         case SM_RESPONDER_IDLE:
45343deb3ec6SMatthias Ringwald         case SM_RESPONDER_SEND_SECURITY_REQUEST:
45353deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH1_W4_PAIRING_REQUEST:
45364c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
45373deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
45383deb3ec6SMatthias Ringwald                 break;;
45393deb3ec6SMatthias Ringwald             }
45403deb3ec6SMatthias Ringwald 
45413deb3ec6SMatthias Ringwald             // store pairing request
4542212d735eSMatthias Ringwald             (void)memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
4543212d735eSMatthias Ringwald 
4544afbd946dSMatthias Ringwald             // validation encryption key size
4545afbd946dSMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(sm_conn->sm_m_preq);
4546afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4547afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4548afbd946dSMatthias Ringwald                 break;
4549afbd946dSMatthias Ringwald             }
4550afbd946dSMatthias Ringwald 
4551212d735eSMatthias Ringwald             // check if IRK completed
4552212d735eSMatthias Ringwald             switch (sm_conn->sm_irk_lookup_state){
4553212d735eSMatthias Ringwald                 case IRK_LOOKUP_SUCCEEDED:
4554212d735eSMatthias Ringwald                 case IRK_LOOKUP_FAILED:
45553deb3ec6SMatthias Ringwald                     sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED;
45563deb3ec6SMatthias Ringwald                     break;
4557212d735eSMatthias Ringwald                 default:
4558212d735eSMatthias Ringwald                     sm_conn->sm_engine_state = SM_RESPONDER_PH1_PAIRING_REQUEST_RECEIVED_W4_IRK;
4559212d735eSMatthias Ringwald                     break;
4560212d735eSMatthias Ringwald             }
4561212d735eSMatthias Ringwald             break;
456242134bc6SMatthias Ringwald #endif
45633deb3ec6SMatthias Ringwald 
456427c32905SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
4565c6b7cbd9SMatthias Ringwald         case SM_SC_W4_PUBLIC_KEY_COMMAND:
45664c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_PUBLIC_KEY){
456727c32905SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
456827c32905SMatthias Ringwald                 break;
456927c32905SMatthias Ringwald             }
4570bccf5e67SMatthias Ringwald 
4571e53be891SMatthias Ringwald             // store public key for DH Key calculation
4572fc5bff5fSMatthias Ringwald             reverse_256(&packet[01], &setup->sm_peer_q[0]);
4573fc5bff5fSMatthias Ringwald             reverse_256(&packet[33], &setup->sm_peer_q[32]);
4574bccf5e67SMatthias Ringwald 
457502658749SMatthias Ringwald             // CVE-2020-26558: abort pairing if remote uses the same public key
457602658749SMatthias Ringwald             if (memcmp(&setup->sm_peer_q, ec_q, 64) == 0){
457702658749SMatthias Ringwald                 log_info("Remote PK matches ours");
457802658749SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
457902658749SMatthias Ringwald                 break;
458002658749SMatthias Ringwald             }
458102658749SMatthias Ringwald 
4582d1a1f6a4SMatthias Ringwald             // validate public key
4583d1a1f6a4SMatthias Ringwald             err = btstack_crypto_ecc_p256_validate_public_key(setup->sm_peer_q);
45849305033eSMatthias Ringwald             if (err != 0){
458502658749SMatthias Ringwald                 log_info("sm: peer public key invalid %x", err);
4586349d0adbSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_DHKEY_CHECK_FAILED);
4587bccf5e67SMatthias Ringwald                 break;
4588bccf5e67SMatthias Ringwald             }
4589891bb64aSMatthias Ringwald 
4590d1a1f6a4SMatthias Ringwald             // start calculating dhkey
4591f3582630SMatthias 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);
45923cf37b8cSMatthias Ringwald 
459365a9a04eSMatthias Ringwald 
459465a9a04eSMatthias Ringwald             log_info("public key received, generation method %u", setup->sm_stk_generation_method);
459542134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
4596136d331aSMatthias Ringwald                 // responder
4597c6b7cbd9SMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
4598136d331aSMatthias Ringwald             } else {
4599136d331aSMatthias Ringwald                 // initiator
4600a1e31e9cSMatthias Ringwald                 // stk generation method
4601a1e31e9cSMatthias Ringwald                 // passkey entry: notify app to show passkey or to request passkey
4602a1e31e9cSMatthias Ringwald                 switch (setup->sm_stk_generation_method){
4603a1e31e9cSMatthias Ringwald                     case JUST_WORKS:
460447fb4255SMatthias Ringwald                     case NUMERIC_COMPARISON:
4605c6b7cbd9SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_W4_CONFIRMATION;
4606a1e31e9cSMatthias Ringwald                         break;
4607a1e31e9cSMatthias Ringwald                     case PK_RESP_INPUT:
460807036a04SMatthias Ringwald                         sm_sc_start_calculating_local_confirm(sm_conn);
460907036a04SMatthias Ringwald                         break;
461007036a04SMatthias Ringwald                     case PK_INIT_INPUT:
461147fb4255SMatthias Ringwald                     case PK_BOTH_INPUT:
461207036a04SMatthias Ringwald                         if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
461307036a04SMatthias Ringwald                             sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
461407036a04SMatthias Ringwald                             break;
461507036a04SMatthias Ringwald                         }
4616b35a3de2SMatthias Ringwald                         sm_sc_start_calculating_local_confirm(sm_conn);
4617a1e31e9cSMatthias Ringwald                         break;
4618a1e31e9cSMatthias Ringwald                     case OOB:
4619d1a1f6a4SMatthias Ringwald                         // generate Nx
46204acf7b7bSMatthias Ringwald                         log_info("Generate Na");
46216ca80073SMatthias 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);
4622a1e31e9cSMatthias Ringwald                         break;
46237bbeb3adSMilanka Ringwald                     default:
46247bbeb3adSMilanka Ringwald                         btstack_assert(false);
46257bbeb3adSMilanka Ringwald                         break;
4626a1e31e9cSMatthias Ringwald                 }
4627136d331aSMatthias Ringwald             }
462827c32905SMatthias Ringwald             break;
4629e53be891SMatthias Ringwald 
4630c6b7cbd9SMatthias Ringwald         case SM_SC_W4_CONFIRMATION:
46314c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
463245a61d50SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
463345a61d50SMatthias Ringwald                 break;
463445a61d50SMatthias Ringwald             }
463545a61d50SMatthias Ringwald             // received confirm value
463645a61d50SMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
463745a61d50SMatthias Ringwald 
4638192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4639192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4640192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4641192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4642192365feSMatthias Ringwald             }
4643192365feSMatthias Ringwald #endif
464442134bc6SMatthias Ringwald             if (IS_RESPONDER(sm_conn->sm_role)){
464545a61d50SMatthias Ringwald                 // responder
464607036a04SMatthias Ringwald                 if (sm_passkey_used(setup->sm_stk_generation_method)){
464707036a04SMatthias Ringwald                     if (setup->sm_user_response != SM_USER_RESPONSE_PASSKEY){
464807036a04SMatthias Ringwald                         // still waiting for passkey
464907036a04SMatthias Ringwald                         sm_conn->sm_engine_state = SM_SC_W4_USER_RESPONSE;
465007036a04SMatthias Ringwald                         break;
465107036a04SMatthias Ringwald                     }
465207036a04SMatthias Ringwald                 }
4653b35a3de2SMatthias Ringwald                 sm_sc_start_calculating_local_confirm(sm_conn);
465445a61d50SMatthias Ringwald             } else {
465545a61d50SMatthias Ringwald                 // initiator
4656945888f5SMatthias Ringwald                 if (sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method)){
46576ca80073SMatthias 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);
4658f1c1783eSMatthias Ringwald                 } else {
4659c6b7cbd9SMatthias Ringwald                     sm_conn->sm_engine_state = SM_SC_SEND_PAIRING_RANDOM;
466045a61d50SMatthias Ringwald                 }
4661f1c1783eSMatthias Ringwald             }
466245a61d50SMatthias Ringwald             break;
466345a61d50SMatthias Ringwald 
4664c6b7cbd9SMatthias Ringwald         case SM_SC_W4_PAIRING_RANDOM:
46654c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
4666e53be891SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4667136d331aSMatthias Ringwald                 break;
4668e53be891SMatthias Ringwald             }
4669e53be891SMatthias Ringwald 
4670e53be891SMatthias Ringwald             // received random value
4671e53be891SMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_nonce);
4672e53be891SMatthias Ringwald 
46735a293e6eSMatthias Ringwald             // validate confirm value if Cb = f4(Pkb, Pka, Nb, z)
4674ae451ec5SMatthias Ringwald             // only check for JUST WORK/NC in initiator role OR passkey entry
4675d686b2d0SMatthias Ringwald             log_info("SM_SC_W4_PAIRING_RANDOM, responder: %u, just works: %u, passkey used %u, passkey entry %u",
4676d686b2d0SMatthias Ringwald                      IS_RESPONDER(sm_conn->sm_role), sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method),
4677d686b2d0SMatthias Ringwald                      sm_passkey_used(setup->sm_stk_generation_method), sm_passkey_entry(setup->sm_stk_generation_method));
467865a9a04eSMatthias Ringwald             if ( (!IS_RESPONDER(sm_conn->sm_role) && sm_just_works_or_numeric_comparison(setup->sm_stk_generation_method))
4679d686b2d0SMatthias Ringwald             ||   (sm_passkey_entry(setup->sm_stk_generation_method)) ) {
4680688a08f9SMatthias Ringwald                  sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
4681ae451ec5SMatthias Ringwald                  break;
46825a293e6eSMatthias Ringwald             }
46836f52a196SMatthias Ringwald 
46844acf7b7bSMatthias Ringwald             // OOB
46854acf7b7bSMatthias Ringwald             if (setup->sm_stk_generation_method == OOB){
46864acf7b7bSMatthias Ringwald 
46874acf7b7bSMatthias Ringwald                 // setup local random, set to zero if remote did not receive our data
46884acf7b7bSMatthias Ringwald                 log_info("Received nonce, setup local random ra/rb for dhkey check");
46894acf7b7bSMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
46904ea43905SMatthias Ringwald                     if (sm_pairing_packet_get_oob_data_flag(setup->sm_m_preq) == 0u){
46914acf7b7bSMatthias Ringwald                         log_info("Reset rb as A does not have OOB data");
46924acf7b7bSMatthias Ringwald                         memset(setup->sm_rb, 0, 16);
46934acf7b7bSMatthias Ringwald                     } else {
46946535961aSMatthias Ringwald                         (void)memcpy(setup->sm_rb, sm_sc_oob_random, 16);
46954acf7b7bSMatthias Ringwald                         log_info("Use stored rb");
46964acf7b7bSMatthias Ringwald                         log_info_hexdump(setup->sm_rb, 16);
46974acf7b7bSMatthias Ringwald                     }
46984acf7b7bSMatthias Ringwald                 }  else {
46994ea43905SMatthias Ringwald                     if (sm_pairing_packet_get_oob_data_flag(setup->sm_s_pres) == 0u){
47004acf7b7bSMatthias Ringwald                         log_info("Reset ra as B does not have OOB data");
47014acf7b7bSMatthias Ringwald                         memset(setup->sm_ra, 0, 16);
47024acf7b7bSMatthias Ringwald                     } else {
47036535961aSMatthias Ringwald                         (void)memcpy(setup->sm_ra, sm_sc_oob_random, 16);
47044acf7b7bSMatthias Ringwald                         log_info("Use stored ra");
47054acf7b7bSMatthias Ringwald                         log_info_hexdump(setup->sm_ra, 16);
47064acf7b7bSMatthias Ringwald                     }
47074acf7b7bSMatthias Ringwald                 }
47084acf7b7bSMatthias Ringwald 
4709a680ba6bSMatthias Ringwald                 // validate confirm value if Cb = f4(PKb, Pkb, rb, 0) for OOB if data received
47104acf7b7bSMatthias Ringwald                 if (setup->sm_have_oob_data){
4711a680ba6bSMatthias Ringwald                      sm_conn->sm_engine_state = SM_SC_W2_CMAC_FOR_CHECK_CONFIRMATION;
4712a680ba6bSMatthias Ringwald                      break;
4713a680ba6bSMatthias Ringwald                 }
47144acf7b7bSMatthias Ringwald             }
4715a680ba6bSMatthias Ringwald 
4716a680ba6bSMatthias Ringwald             // TODO: we only get here for Responder role with JW/NC
4717688a08f9SMatthias Ringwald             sm_sc_state_after_receiving_random(sm_conn);
4718e53be891SMatthias Ringwald             break;
4719e53be891SMatthias Ringwald 
4720901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_G2:
4721901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_G2:
47223cf37b8cSMatthias Ringwald         case SM_SC_W4_CALCULATE_DHKEY:
4723901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_SALT:
4724901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_SALT:
4725901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_MACKEY:
4726901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_MACKEY:
4727901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F5_LTK:
4728901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F5_LTK:
4729901c000fSMatthias Ringwald         case SM_SC_W2_CALCULATE_F6_FOR_DHKEY_CHECK:
4730c6b7cbd9SMatthias Ringwald         case SM_SC_W4_DHKEY_CHECK_COMMAND:
4731901c000fSMatthias Ringwald         case SM_SC_W4_CALCULATE_F6_FOR_DHKEY_CHECK:
4732d08147dfSMatthias Ringwald         case SM_SC_W4_USER_RESPONSE:
47334c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_DHKEY_CHECK){
4734e53be891SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4735e53be891SMatthias Ringwald                 break;
4736e53be891SMatthias Ringwald             }
4737e53be891SMatthias Ringwald             // store DHKey Check
4738901c000fSMatthias Ringwald             setup->sm_state_vars |= SM_STATE_VAR_DHKEY_COMMAND_RECEIVED;
4739e53be891SMatthias Ringwald             reverse_128(&packet[01], setup->sm_peer_dhkey_check);
4740446a8c36SMatthias Ringwald 
4741901c000fSMatthias Ringwald             // have we been only waiting for dhkey check command?
4742901c000fSMatthias Ringwald             if (sm_conn->sm_engine_state == SM_SC_W4_DHKEY_CHECK_COMMAND){
4743019005a0SMatthias Ringwald                 sm_conn->sm_engine_state = SM_SC_W2_CALCULATE_F6_TO_VERIFY_DHKEY_CHECK;
4744bd57ffebSMatthias Ringwald             }
4745bd57ffebSMatthias Ringwald             break;
474627c32905SMatthias Ringwald #endif
474727c32905SMatthias Ringwald 
474842134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
47493deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH1_W4_PAIRING_CONFIRM:
47504c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_CONFIRM){
47513deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
475227c32905SMatthias Ringwald                 break;
47533deb3ec6SMatthias Ringwald             }
47543deb3ec6SMatthias Ringwald 
47553deb3ec6SMatthias Ringwald             // received confirm value
47569c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_confirm);
47573deb3ec6SMatthias Ringwald 
4758192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
4759192365feSMatthias Ringwald             if (test_pairing_failure == SM_REASON_CONFIRM_VALUE_FAILED){
4760192365feSMatthias Ringwald                 log_info("testing_support: reset confirm value");
4761192365feSMatthias Ringwald                 memset(setup->sm_peer_confirm, 0, 16);
4762192365feSMatthias Ringwald             }
4763192365feSMatthias Ringwald #endif
47643deb3ec6SMatthias Ringwald             // notify client to hide shown passkey
47653deb3ec6SMatthias Ringwald             if (setup->sm_stk_generation_method == PK_INIT_INPUT){
47665611a760SMatthias 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);
47673deb3ec6SMatthias Ringwald             }
47683deb3ec6SMatthias Ringwald 
47693deb3ec6SMatthias Ringwald             // handle user cancel pairing?
47703deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_DECLINE){
4771f4935286SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_PASSKEY_ENTRY_FAILED);
47723deb3ec6SMatthias Ringwald                 break;
47733deb3ec6SMatthias Ringwald             }
47743deb3ec6SMatthias Ringwald 
47753deb3ec6SMatthias Ringwald             // wait for user action?
47763deb3ec6SMatthias Ringwald             if (setup->sm_user_response == SM_USER_RESPONSE_PENDING){
47773deb3ec6SMatthias Ringwald                 sm_conn->sm_engine_state = SM_PH1_W4_USER_RESPONSE;
47783deb3ec6SMatthias Ringwald                 break;
47793deb3ec6SMatthias Ringwald             }
47803deb3ec6SMatthias Ringwald 
47813deb3ec6SMatthias Ringwald             // calculate and send local_confirm
4782f3582630SMatthias 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);
47833deb3ec6SMatthias Ringwald             break;
47843deb3ec6SMatthias Ringwald 
47853deb3ec6SMatthias Ringwald         case SM_RESPONDER_PH2_W4_PAIRING_RANDOM:
47864c1d1092SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RANDOM){
47873deb3ec6SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
47883deb3ec6SMatthias Ringwald                 break;;
47893deb3ec6SMatthias Ringwald             }
47903deb3ec6SMatthias Ringwald 
47913deb3ec6SMatthias Ringwald             // received random value
47929c80e4ccSMatthias Ringwald             reverse_128(&packet[1], setup->sm_peer_random);
47933deb3ec6SMatthias Ringwald             sm_conn->sm_engine_state = SM_PH2_C1_GET_ENC_C;
47943deb3ec6SMatthias Ringwald             break;
479542134bc6SMatthias Ringwald #endif
47963deb3ec6SMatthias Ringwald 
4797672dc582SMatthias Ringwald         case SM_PH2_W4_CONNECTION_ENCRYPTED:
47983deb3ec6SMatthias Ringwald         case SM_PH3_RECEIVE_KEYS:
47994c1d1092SMatthias Ringwald             switch(sm_pdu_code){
48003deb3ec6SMatthias Ringwald                 case SM_CODE_ENCRYPTION_INFORMATION:
48013deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_ENCRYPTION_INFORMATION;
48029c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_ltk);
48033deb3ec6SMatthias Ringwald                     break;
48043deb3ec6SMatthias Ringwald 
48053deb3ec6SMatthias Ringwald                 case SM_CODE_MASTER_IDENTIFICATION:
48063deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_MASTER_IDENTIFICATION;
4807f8fbdce0SMatthias Ringwald                     setup->sm_peer_ediv = little_endian_read_16(packet, 1);
48089c80e4ccSMatthias Ringwald                     reverse_64(&packet[3], setup->sm_peer_rand);
48093deb3ec6SMatthias Ringwald                     break;
48103deb3ec6SMatthias Ringwald 
48113deb3ec6SMatthias Ringwald                 case SM_CODE_IDENTITY_INFORMATION:
48123deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
48139c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_irk);
48143deb3ec6SMatthias Ringwald                     break;
48153deb3ec6SMatthias Ringwald 
48163deb3ec6SMatthias Ringwald                 case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
48173deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
48183deb3ec6SMatthias Ringwald                     setup->sm_peer_addr_type = packet[1];
4819724d70a2SMatthias Ringwald                     reverse_bd_addr(&packet[2], setup->sm_peer_address);
48203deb3ec6SMatthias Ringwald                     break;
48213deb3ec6SMatthias Ringwald 
48223deb3ec6SMatthias Ringwald                 case SM_CODE_SIGNING_INFORMATION:
48233deb3ec6SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
48249c80e4ccSMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_csrk);
48253deb3ec6SMatthias Ringwald                     break;
48263deb3ec6SMatthias Ringwald                 default:
48273deb3ec6SMatthias Ringwald                     // Unexpected PDU
48283deb3ec6SMatthias Ringwald                     log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
48293deb3ec6SMatthias Ringwald                     break;
48303deb3ec6SMatthias Ringwald             }
48313deb3ec6SMatthias Ringwald             // done with key distribution?
483261d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
48333deb3ec6SMatthias Ringwald 
48343deb3ec6SMatthias Ringwald                 sm_key_distribution_handle_all_received(sm_conn);
48353deb3ec6SMatthias Ringwald 
483642134bc6SMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
48376f7422f1SMatthias Ringwald                     sm_key_distribution_complete_responder(sm_conn);
48383deb3ec6SMatthias Ringwald                 } else {
4839625f00b2SMatthias Ringwald                     if (setup->sm_use_secure_connections){
4840625f00b2SMatthias Ringwald                         sm_conn->sm_engine_state = SM_PH3_DISTRIBUTE_KEYS;
4841bbf8db22SMatthias Ringwald                     } else {
4842f3582630SMatthias 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);
4843625f00b2SMatthias Ringwald                     }
48443deb3ec6SMatthias Ringwald                 }
48453deb3ec6SMatthias Ringwald             }
48463deb3ec6SMatthias Ringwald             break;
4847c18be159SMatthias Ringwald 
4848c18be159SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
4849b322498eSMatthias Ringwald 
4850b322498eSMatthias Ringwald         case SM_BR_EDR_W4_ENCRYPTION_COMPLETE:
4851b322498eSMatthias Ringwald             // GAP/DM/LEP/BI-02-C - reject CTKD if P-192 encryption is used
4852b322498eSMatthias Ringwald             if (sm_pdu_code == SM_CODE_PAIRING_REQUEST){
4853b322498eSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED);
4854b322498eSMatthias Ringwald             }
4855b322498eSMatthias Ringwald             break;
4856b322498eSMatthias Ringwald 
4857c18be159SMatthias Ringwald         case SM_BR_EDR_INITIATOR_W4_PAIRING_RESPONSE:
4858553c9408SMatthias Ringwald 
4859553c9408SMatthias Ringwald             // dedicated bonding complete
4860f82b8f4bSMatthias Ringwald             hci_dedicated_bonding_defer_disconnect(sm_conn->sm_handle, false);
4861553c9408SMatthias Ringwald 
4862c18be159SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_RESPONSE){
4863c18be159SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4864c18be159SMatthias Ringwald                 break;
4865c18be159SMatthias Ringwald             }
4866c18be159SMatthias Ringwald             // store pairing response
4867c18be159SMatthias Ringwald             (void)memcpy(&setup->sm_s_pres, packet, sizeof(sm_pairing_packet_t));
4868c18be159SMatthias Ringwald 
4869c18be159SMatthias Ringwald             // validate encryption key size
4870afbd946dSMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(setup->sm_s_pres);
4871afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4872afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4873afbd946dSMatthias Ringwald                 break;
4874afbd946dSMatthias Ringwald             }
4875afbd946dSMatthias Ringwald             sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(max_encryption_key_size);
4876c18be159SMatthias Ringwald             // SC Only mandates 128 bit key size
4877c18be159SMatthias Ringwald             if (sm_sc_only_mode && (sm_conn->sm_actual_encryption_key_size < 16)) {
4878c18be159SMatthias Ringwald                 sm_conn->sm_actual_encryption_key_size  = 0;
4879c18be159SMatthias Ringwald             }
4880c18be159SMatthias Ringwald             if (sm_conn->sm_actual_encryption_key_size == 0){
4881c18be159SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_ENCRYPTION_KEY_SIZE);
4882c18be159SMatthias Ringwald                 break;
4883c18be159SMatthias Ringwald             }
4884c18be159SMatthias Ringwald 
4885c18be159SMatthias Ringwald             // prepare key exchange, LTK is derived locally
4886c18be159SMatthias Ringwald             sm_setup_key_distribution(sm_pairing_packet_get_initiator_key_distribution(setup->sm_s_pres) & ~SM_KEYDIST_ENC_KEY,
4887c18be159SMatthias Ringwald                                       sm_pairing_packet_get_responder_key_distribution(setup->sm_s_pres) & ~SM_KEYDIST_ENC_KEY);
4888c18be159SMatthias Ringwald 
4889c18be159SMatthias Ringwald             // skip receive if there are none
489061d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
4891c18be159SMatthias Ringwald                 // distribute keys in run handles 'no keys to send'
4892c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
4893c18be159SMatthias Ringwald             } else {
4894c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_RECEIVE_KEYS;
4895c18be159SMatthias Ringwald             }
4896c18be159SMatthias Ringwald             break;
4897c18be159SMatthias Ringwald 
4898c18be159SMatthias Ringwald         case SM_BR_EDR_RESPONDER_W4_PAIRING_REQUEST:
4899c18be159SMatthias Ringwald             if (sm_pdu_code != SM_CODE_PAIRING_REQUEST){
4900c18be159SMatthias Ringwald                 sm_pdu_received_in_wrong_state(sm_conn);
4901c18be159SMatthias Ringwald                 break;
4902c18be159SMatthias Ringwald             }
4903afbd946dSMatthias Ringwald 
4904c18be159SMatthias Ringwald             // store pairing request
4905c18be159SMatthias Ringwald             (void)memcpy(&sm_conn->sm_m_preq, packet, sizeof(sm_pairing_packet_t));
4906afbd946dSMatthias Ringwald 
4907c18be159SMatthias Ringwald             // validate encryption key size
4908f5217d52SMatthias Ringwald             max_encryption_key_size = sm_pairing_packet_get_max_encryption_key_size(sm_conn->sm_m_preq);
4909afbd946dSMatthias Ringwald             if ((max_encryption_key_size < 7) || (max_encryption_key_size > 16)){
4910afbd946dSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_INVALID_PARAMETERS);
4911afbd946dSMatthias Ringwald                 break;
4912afbd946dSMatthias Ringwald             }
4913afbd946dSMatthias Ringwald             sm_conn->sm_actual_encryption_key_size = sm_calc_actual_encryption_key_size(max_encryption_key_size);
4914c18be159SMatthias Ringwald             // SC Only mandates 128 bit key size
4915c18be159SMatthias Ringwald             if (sm_sc_only_mode && (sm_conn->sm_actual_encryption_key_size < 16)) {
4916c18be159SMatthias Ringwald                 sm_conn->sm_actual_encryption_key_size  = 0;
4917c18be159SMatthias Ringwald             }
4918c18be159SMatthias Ringwald             if (sm_conn->sm_actual_encryption_key_size == 0){
4919c18be159SMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_ENCRYPTION_KEY_SIZE);
4920c18be159SMatthias Ringwald                 break;
4921c18be159SMatthias Ringwald             }
4922c18be159SMatthias Ringwald             // trigger response
49236a718a5eSMatthias Ringwald             if (sm_ctkd_from_classic(sm_conn)){
4924c18be159SMatthias Ringwald                 sm_conn->sm_engine_state = SM_BR_EDR_RESPONDER_PAIRING_REQUEST_RECEIVED;
49256a718a5eSMatthias Ringwald             } else {
49266a718a5eSMatthias Ringwald                 sm_pairing_error(sm_conn, SM_REASON_CROSS_TRANSPORT_KEY_DERIVATION_NOT_ALLOWED);
49276a718a5eSMatthias Ringwald             }
4928c18be159SMatthias Ringwald             break;
4929c18be159SMatthias Ringwald 
4930c18be159SMatthias Ringwald         case SM_BR_EDR_RECEIVE_KEYS:
4931c18be159SMatthias Ringwald             switch(sm_pdu_code){
4932c18be159SMatthias Ringwald                 case SM_CODE_IDENTITY_INFORMATION:
4933c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_INFORMATION;
4934c18be159SMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_irk);
4935c18be159SMatthias Ringwald                     break;
4936c18be159SMatthias Ringwald                 case SM_CODE_IDENTITY_ADDRESS_INFORMATION:
4937c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_IDENTITY_ADDRESS_INFORMATION;
4938c18be159SMatthias Ringwald                     setup->sm_peer_addr_type = packet[1];
4939c18be159SMatthias Ringwald                     reverse_bd_addr(&packet[2], setup->sm_peer_address);
4940c18be159SMatthias Ringwald                     break;
4941c18be159SMatthias Ringwald                 case SM_CODE_SIGNING_INFORMATION:
4942c18be159SMatthias Ringwald                     setup->sm_key_distribution_received_set |= SM_KEYDIST_FLAG_SIGNING_IDENTIFICATION;
4943c18be159SMatthias Ringwald                     reverse_128(&packet[1], setup->sm_peer_csrk);
4944c18be159SMatthias Ringwald                     break;
4945c18be159SMatthias Ringwald                 default:
4946c18be159SMatthias Ringwald                     // Unexpected PDU
4947c18be159SMatthias Ringwald                     log_info("Unexpected PDU %u in SM_PH3_RECEIVE_KEYS", packet[0]);
4948c18be159SMatthias Ringwald                     break;
4949c18be159SMatthias Ringwald             }
4950c18be159SMatthias Ringwald 
4951c18be159SMatthias Ringwald             // all keys received
495261d1a45eSMatthias Ringwald             if (sm_key_distribution_all_received()){
4953c18be159SMatthias Ringwald                 if (IS_RESPONDER(sm_conn->sm_role)){
4954c18be159SMatthias Ringwald                     // responder -> keys exchanged, derive LE LTK
4955c18be159SMatthias Ringwald                     sm_ctkd_start_from_br_edr(sm_conn);
4956c18be159SMatthias Ringwald                 } else {
4957c18be159SMatthias Ringwald                     // initiator -> send our keys if any
4958c18be159SMatthias Ringwald                     sm_conn->sm_engine_state = SM_BR_EDR_DISTRIBUTE_KEYS;
4959c18be159SMatthias Ringwald                 }
4960c18be159SMatthias Ringwald             }
4961c18be159SMatthias Ringwald             break;
4962c18be159SMatthias Ringwald #endif
4963c18be159SMatthias Ringwald 
49643deb3ec6SMatthias Ringwald         default:
49653deb3ec6SMatthias Ringwald             // Unexpected PDU
49663deb3ec6SMatthias Ringwald             log_info("Unexpected PDU %u in state %u", packet[0], sm_conn->sm_engine_state);
49672d095694SMatthias Ringwald             sm_pdu_received_in_wrong_state(sm_conn);
49683deb3ec6SMatthias Ringwald             break;
49693deb3ec6SMatthias Ringwald     }
49703deb3ec6SMatthias Ringwald 
497170b44dd4SMatthias Ringwald     // try to send next pdu
497270b44dd4SMatthias Ringwald     sm_trigger_run();
49733deb3ec6SMatthias Ringwald }
49743deb3ec6SMatthias Ringwald 
49753deb3ec6SMatthias Ringwald // Security Manager Client API
4976a680ba6bSMatthias Ringwald void sm_register_oob_data_callback( int (*get_oob_data_callback)(uint8_t address_type, bd_addr_t addr, uint8_t * oob_data)){
49773deb3ec6SMatthias Ringwald     sm_get_oob_data = get_oob_data_callback;
49783deb3ec6SMatthias Ringwald }
49793deb3ec6SMatthias Ringwald 
49804acf7b7bSMatthias 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)){
4981a680ba6bSMatthias Ringwald     sm_get_sc_oob_data = get_sc_oob_data_callback;
4982a680ba6bSMatthias Ringwald }
4983a680ba6bSMatthias Ringwald 
4984b96d60a6SMatthias 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)){
4985b96d60a6SMatthias Ringwald     sm_get_ltk_callback = get_ltk_callback;
4986b96d60a6SMatthias Ringwald }
4987b96d60a6SMatthias Ringwald 
498889a78d34SMatthias Ringwald void sm_add_event_handler(btstack_packet_callback_registration_t * callback_handler){
498989a78d34SMatthias Ringwald     btstack_linked_list_add_tail(&sm_event_handlers, (btstack_linked_item_t*) callback_handler);
499089a78d34SMatthias Ringwald }
499189a78d34SMatthias Ringwald 
499267f708e0SMatthias Ringwald void sm_remove_event_handler(btstack_packet_callback_registration_t * callback_handler){
499367f708e0SMatthias Ringwald     btstack_linked_list_remove(&sm_event_handlers, (btstack_linked_item_t*) callback_handler);
499467f708e0SMatthias Ringwald }
499567f708e0SMatthias Ringwald 
49963deb3ec6SMatthias Ringwald void sm_set_accepted_stk_generation_methods(uint8_t accepted_stk_generation_methods){
49973deb3ec6SMatthias Ringwald     sm_accepted_stk_generation_methods = accepted_stk_generation_methods;
49983deb3ec6SMatthias Ringwald }
49993deb3ec6SMatthias Ringwald 
50003deb3ec6SMatthias Ringwald void sm_set_encryption_key_size_range(uint8_t min_size, uint8_t max_size){
50013deb3ec6SMatthias Ringwald 	sm_min_encryption_key_size = min_size;
50023deb3ec6SMatthias Ringwald 	sm_max_encryption_key_size = max_size;
50033deb3ec6SMatthias Ringwald }
50043deb3ec6SMatthias Ringwald 
50053deb3ec6SMatthias Ringwald void sm_set_authentication_requirements(uint8_t auth_req){
500698d95509SMatthias Ringwald #ifndef ENABLE_LE_SECURE_CONNECTIONS
500798d95509SMatthias Ringwald     if (auth_req & SM_AUTHREQ_SECURE_CONNECTION){
500898d95509SMatthias Ringwald         log_error("ENABLE_LE_SECURE_CONNECTIONS not defined, but requested by app. Dropping SC flag");
500998d95509SMatthias Ringwald         auth_req &= ~SM_AUTHREQ_SECURE_CONNECTION;
501098d95509SMatthias Ringwald     }
501198d95509SMatthias Ringwald #endif
50123deb3ec6SMatthias Ringwald     sm_auth_req = auth_req;
50133deb3ec6SMatthias Ringwald }
50143deb3ec6SMatthias Ringwald 
50153deb3ec6SMatthias Ringwald void sm_set_io_capabilities(io_capability_t io_capability){
50163deb3ec6SMatthias Ringwald     sm_io_capabilities = io_capability;
50173deb3ec6SMatthias Ringwald }
50183deb3ec6SMatthias Ringwald 
501942134bc6SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
5020728f6757SMatthias Ringwald void sm_set_request_security(bool enable){
50213deb3ec6SMatthias Ringwald     sm_slave_request_security = enable;
50223deb3ec6SMatthias Ringwald }
502342134bc6SMatthias Ringwald #endif
50243deb3ec6SMatthias Ringwald 
50253deb3ec6SMatthias Ringwald void sm_set_er(sm_key_t er){
50266535961aSMatthias Ringwald     (void)memcpy(sm_persistent_er, er, 16);
50273deb3ec6SMatthias Ringwald }
50283deb3ec6SMatthias Ringwald 
50293deb3ec6SMatthias Ringwald void sm_set_ir(sm_key_t ir){
50306535961aSMatthias Ringwald     (void)memcpy(sm_persistent_ir, ir, 16);
50313deb3ec6SMatthias Ringwald }
50323deb3ec6SMatthias Ringwald 
50333deb3ec6SMatthias Ringwald // Testing support only
50343deb3ec6SMatthias Ringwald void sm_test_set_irk(sm_key_t irk){
50356535961aSMatthias Ringwald     (void)memcpy(sm_persistent_irk, irk, 16);
5036103fa6b0SMatthias Ringwald     dkg_state = DKG_CALC_DHK;
5037841468bbSMatthias Ringwald     test_use_fixed_local_irk = true;
50383deb3ec6SMatthias Ringwald }
50393deb3ec6SMatthias Ringwald 
50403deb3ec6SMatthias Ringwald void sm_test_use_fixed_local_csrk(void){
5041841468bbSMatthias Ringwald     test_use_fixed_local_csrk = true;
50423deb3ec6SMatthias Ringwald }
50433deb3ec6SMatthias Ringwald 
5044d1a1f6a4SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
5045d1a1f6a4SMatthias Ringwald static void sm_ec_generated(void * arg){
5046d1a1f6a4SMatthias Ringwald     UNUSED(arg);
5047d1a1f6a4SMatthias Ringwald     ec_key_generation_state = EC_KEY_GENERATION_DONE;
504834b6528fSMatthias Ringwald     // trigger pairing if pending for ec key
504970b44dd4SMatthias Ringwald     sm_trigger_run();
5050d1a1f6a4SMatthias Ringwald }
5051674e5b4aSMatthias Ringwald static void sm_ec_generate_new_key(void) {
505234b6528fSMatthias Ringwald     log_info("sm: generate new ec key");
5053db88441fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS_DEBUG_KEY
5054db88441fSMatthias Ringwald     // LE Secure Connections Debug Key
5055db88441fSMatthias Ringwald     const uint8_t debug_key_public[64] = {
5056db88441fSMatthias Ringwald         0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c, 0x5e, 0x2c, 0x83, 0xa7, 0xe9, 0xf9, 0xa5, 0xb9,
5057db88441fSMatthias Ringwald         0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb, 0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6,
5058db88441fSMatthias Ringwald         0xdc, 0x80, 0x9c, 0x49, 0x65, 0x2a, 0xeb, 0x6d, 0x63, 0x32, 0x9a, 0xbf, 0x5a, 0x52, 0x15, 0x5c,
5059db88441fSMatthias Ringwald         0x76, 0x63, 0x45, 0xc2, 0x8f, 0xed, 0x30, 0x24, 0x74, 0x1c, 0x8e, 0xd0, 0x15, 0x89, 0xd2, 0x8b
5060db88441fSMatthias Ringwald     };
5061db88441fSMatthias Ringwald     const uint8_t debug_key_private[32] = {
5062db88441fSMatthias Ringwald         0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3, 0xe3, 0xd2, 0x10, 0x3f, 0x50,
5063db88441fSMatthias Ringwald         0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99, 0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd
5064db88441fSMatthias Ringwald     };
5065db88441fSMatthias Ringwald     if (sm_sc_debug_keys_enabled) {
5066db88441fSMatthias Ringwald         memcpy(ec_q, debug_key_public, 64);
5067db88441fSMatthias Ringwald         btstack_crypto_ecc_p256_set_key(debug_key_public, debug_key_private);
5068db88441fSMatthias Ringwald         ec_key_generation_state = EC_KEY_GENERATION_DONE;
5069db88441fSMatthias Ringwald     } else
5070db88441fSMatthias Ringwald #endif
5071db88441fSMatthias Ringwald     {
5072674e5b4aSMatthias Ringwald         ec_key_generation_state = EC_KEY_GENERATION_ACTIVE;
5073674e5b4aSMatthias Ringwald         btstack_crypto_ecc_p256_generate_key(&sm_crypto_ecc_p256_request, ec_q, &sm_ec_generated, NULL);
5074674e5b4aSMatthias Ringwald     }
5075db88441fSMatthias Ringwald }
5076d1a1f6a4SMatthias Ringwald #endif
5077d1a1f6a4SMatthias Ringwald 
5078192365feSMatthias Ringwald #ifdef ENABLE_TESTING_SUPPORT
5079192365feSMatthias Ringwald void sm_test_set_pairing_failure(int reason){
5080192365feSMatthias Ringwald     test_pairing_failure = reason;
5081192365feSMatthias Ringwald }
5082192365feSMatthias Ringwald #endif
5083192365feSMatthias Ringwald 
50847887cd92SMatthias Ringwald static void sm_state_reset(void) {
50857f775357SMatthias Ringwald #ifdef USE_CMAC_ENGINE
50867f775357SMatthias Ringwald     sm_cmac_active  = 0;
50877f775357SMatthias Ringwald #endif
50887f775357SMatthias Ringwald     dkg_state = DKG_W4_WORKING;
50897f775357SMatthias Ringwald     rau_state = RAU_IDLE;
50907f775357SMatthias Ringwald     sm_aes128_state = SM_AES128_IDLE;
50917f775357SMatthias Ringwald     sm_address_resolution_test = -1;    // no private address to resolve yet
50927f775357SMatthias Ringwald     sm_address_resolution_mode = ADDRESS_RESOLUTION_IDLE;
50937f775357SMatthias Ringwald     sm_address_resolution_general_queue = NULL;
50947f775357SMatthias Ringwald     sm_active_connection_handle = HCI_CON_HANDLE_INVALID;
5095cbdd51cfSMatthias Ringwald     sm_persistent_keys_random_active = false;
50967f775357SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
509715211b85SMatthias Ringwald     ec_key_generation_state = EC_KEY_GENERATION_IDLE;
50987f775357SMatthias Ringwald #endif
50997f775357SMatthias Ringwald }
51007f775357SMatthias Ringwald 
51013deb3ec6SMatthias Ringwald void sm_init(void){
51022d2d4d3cSMatthias Ringwald 
51032d2d4d3cSMatthias Ringwald     if (sm_initialized) return;
51042d2d4d3cSMatthias Ringwald 
5105899e6e02SMatthias Ringwald     // set default ER and IR values (should be unique - set by app or sm later using TLV)
5106899e6e02SMatthias Ringwald     sm_er_ir_set_default();
5107899e6e02SMatthias Ringwald 
51083deb3ec6SMatthias Ringwald     // defaults
51093deb3ec6SMatthias Ringwald     sm_accepted_stk_generation_methods = SM_STK_GENERATION_METHOD_JUST_WORKS
51103deb3ec6SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_OOB
5111b4343428SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_PASSKEY
5112b4343428SMatthias Ringwald                                        | SM_STK_GENERATION_METHOD_NUMERIC_COMPARISON;
5113b4343428SMatthias Ringwald 
51143deb3ec6SMatthias Ringwald     sm_max_encryption_key_size = 16;
51153deb3ec6SMatthias Ringwald     sm_min_encryption_key_size = 7;
51163deb3ec6SMatthias Ringwald 
51175ce1359eSMatthias Ringwald     sm_fixed_passkey_in_display_role = 0xffffffffU;
51181979f09cSMatthias Ringwald     sm_reconstruct_ltk_without_le_device_db_entry = true;
5119caf15bf3SMatthias Ringwald 
51203deb3ec6SMatthias Ringwald     gap_random_adress_update_period = 15 * 60 * 1000L;
51213deb3ec6SMatthias Ringwald 
5122841468bbSMatthias Ringwald     test_use_fixed_local_csrk = false;
51233deb3ec6SMatthias Ringwald 
51247f775357SMatthias Ringwald     // other
512584c0c5c7SMatthias Ringwald     btstack_run_loop_set_timer_handler(&sm_run_timer, &sm_run_timer_handler);
512684c0c5c7SMatthias Ringwald 
5127a036ae12SMatthias Ringwald     // register for HCI Events
5128e03e489aSMatthias Ringwald     hci_event_callback_registration.callback = &sm_event_packet_handler;
5129e03e489aSMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
5130e03e489aSMatthias Ringwald 
5131bad51150SMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
5132a036ae12SMatthias Ringwald     // register for L2CAP events
5133a036ae12SMatthias Ringwald     l2cap_event_callback_registration.callback = &sm_event_packet_handler;
5134a036ae12SMatthias Ringwald     l2cap_add_event_handler(&l2cap_event_callback_registration);
5135bad51150SMatthias Ringwald #endif
5136a036ae12SMatthias Ringwald 
5137d1a1f6a4SMatthias Ringwald     //
5138d1a1f6a4SMatthias Ringwald     btstack_crypto_init();
5139d1a1f6a4SMatthias Ringwald 
514051bd74d1SMatthias Ringwald     // init le_device_db
514151bd74d1SMatthias Ringwald     le_device_db_init();
514251bd74d1SMatthias Ringwald 
5143b170b20fSMatthias Ringwald     // and L2CAP PDUs + L2CAP_EVENT_CAN_SEND_NOW
5144e03e489aSMatthias Ringwald     l2cap_register_fixed_channel(sm_pdu_handler, L2CAP_CID_SECURITY_MANAGER_PROTOCOL);
5145384eabd3SMatthias Ringwald #ifdef ENABLE_CLASSIC
5146384eabd3SMatthias Ringwald     l2cap_register_fixed_channel(sm_pdu_handler, L2CAP_CID_BR_EDR_SECURITY_MANAGER);
5147384eabd3SMatthias Ringwald #endif
514827c32905SMatthias Ringwald 
51497f775357SMatthias Ringwald     // state
51507f775357SMatthias Ringwald     sm_state_reset();
51512d2d4d3cSMatthias Ringwald 
51522d2d4d3cSMatthias Ringwald     sm_initialized = true;
51533deb3ec6SMatthias Ringwald }
51543deb3ec6SMatthias Ringwald 
515515537ea4SMatthias Ringwald void sm_deinit(void){
515615537ea4SMatthias Ringwald     sm_initialized = false;
515715537ea4SMatthias Ringwald     btstack_run_loop_remove_timer(&sm_run_timer);
515892f8d6b6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined (ENABLE_LE_SECURE_CONNECTION_DEBUG_KEY)
5159db88441fSMatthias Ringwald     sm_sc_debug_keys_enabled = false;
5160db88441fSMatthias Ringwald #endif
516115537ea4SMatthias Ringwald }
516215537ea4SMatthias Ringwald 
51634b8c611fSMatthias Ringwald void sm_use_fixed_passkey_in_display_role(uint32_t passkey){
51644b8c611fSMatthias Ringwald     sm_fixed_passkey_in_display_role = passkey;
5165caf15bf3SMatthias Ringwald }
5166caf15bf3SMatthias Ringwald 
51676c39055aSMatthias Ringwald void sm_allow_ltk_reconstruction_without_le_device_db_entry(int allow){
51681979f09cSMatthias Ringwald     sm_reconstruct_ltk_without_le_device_db_entry = allow != 0;
51696c39055aSMatthias Ringwald }
51706c39055aSMatthias Ringwald 
5171711e6c80SMatthias Ringwald static sm_connection_t * sm_get_connection_for_handle(hci_con_handle_t con_handle){
5172711e6c80SMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(con_handle);
51733deb3ec6SMatthias Ringwald     if (!hci_con) return NULL;
51743deb3ec6SMatthias Ringwald     return &hci_con->sm_connection;
51753deb3ec6SMatthias Ringwald }
51763deb3ec6SMatthias Ringwald 
5177916ea5b2SMatthias Ringwald static void sm_cache_ltk(sm_connection_t * connection, const sm_key_t ltk){
5178916ea5b2SMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_handle(connection->sm_handle);
5179916ea5b2SMatthias Ringwald     btstack_assert(hci_con != NULL);
5180916ea5b2SMatthias Ringwald     memcpy(hci_con->link_key, ltk, 16);
5181f728bb7bSMatthias Ringwald     hci_con->link_key_type = COMBINATION_KEY;
5182916ea5b2SMatthias Ringwald }
5183916ea5b2SMatthias Ringwald 
518477e2e5edSMatthias Ringwald #ifdef ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
518577e2e5edSMatthias Ringwald static sm_connection_t * sm_get_connection_for_bd_addr_and_type(bd_addr_t address, bd_addr_type_t addr_type){
518677e2e5edSMatthias Ringwald     hci_connection_t * hci_con = hci_connection_for_bd_addr_and_type(address, addr_type);
518777e2e5edSMatthias Ringwald     if (!hci_con) return NULL;
518877e2e5edSMatthias Ringwald     return &hci_con->sm_connection;
518977e2e5edSMatthias Ringwald }
519077e2e5edSMatthias Ringwald #endif
519177e2e5edSMatthias Ringwald 
51926bc3aba4SMatthias Ringwald // @deprecated: map onto sm_request_pairing
5193711e6c80SMatthias Ringwald void sm_send_security_request(hci_con_handle_t con_handle){
5194711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
51953deb3ec6SMatthias Ringwald     if (!sm_conn) return;
51966bc3aba4SMatthias Ringwald     if (!IS_RESPONDER(sm_conn->sm_role)) return;
51976bc3aba4SMatthias Ringwald     sm_request_pairing(con_handle);
51983deb3ec6SMatthias Ringwald }
51993deb3ec6SMatthias Ringwald 
52003deb3ec6SMatthias Ringwald // request pairing
5201711e6c80SMatthias Ringwald void sm_request_pairing(hci_con_handle_t con_handle){
5202711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52033deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52043deb3ec6SMatthias Ringwald 
52057af5dcd5SMatthias Ringwald     bool have_ltk;
52067af5dcd5SMatthias Ringwald     uint8_t ltk[16];
52072d68601cSMatthias Ringwald     bool auth_required;
52082d68601cSMatthias Ringwald     int authenticated;
52092d68601cSMatthias Ringwald     bool trigger_reencryption;
52103deb3ec6SMatthias Ringwald     log_info("sm_request_pairing in role %u, state %u", sm_conn->sm_role, sm_conn->sm_engine_state);
521142134bc6SMatthias Ringwald     if (IS_RESPONDER(sm_conn->sm_role)){
521224c20dc4SMatthias Ringwald         switch (sm_conn->sm_engine_state){
521324c20dc4SMatthias Ringwald             case SM_GENERAL_IDLE:
521424c20dc4SMatthias Ringwald             case SM_RESPONDER_IDLE:
52157af5dcd5SMatthias Ringwald                 switch (sm_conn->sm_irk_lookup_state){
52167af5dcd5SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
52177af5dcd5SMatthias Ringwald                         le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, NULL, NULL, NULL);
52187af5dcd5SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
52197af5dcd5SMatthias Ringwald                         log_info("have ltk %u", have_ltk);
52207af5dcd5SMatthias Ringwald                         if (have_ltk){
52215f3874afSMatthias Ringwald                             sm_conn->sm_pairing_requested = true;
522224c20dc4SMatthias Ringwald                             sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
52237af5dcd5SMatthias Ringwald                             sm_reencryption_started(sm_conn);
52247af5dcd5SMatthias Ringwald                             break;
52257af5dcd5SMatthias Ringwald                         }
52267af5dcd5SMatthias Ringwald                         /* fall through */
52277af5dcd5SMatthias Ringwald 
52287af5dcd5SMatthias Ringwald                     case IRK_LOOKUP_FAILED:
52295f3874afSMatthias Ringwald                         sm_conn->sm_pairing_requested = true;
52307af5dcd5SMatthias Ringwald                         sm_conn->sm_engine_state = SM_RESPONDER_SEND_SECURITY_REQUEST;
52317af5dcd5SMatthias Ringwald                         sm_pairing_started(sm_conn);
52327af5dcd5SMatthias Ringwald                         break;
52337af5dcd5SMatthias Ringwald                     default:
52347af5dcd5SMatthias Ringwald                         log_info("irk lookup pending");
52355f3874afSMatthias Ringwald                         sm_conn->sm_pairing_requested = true;
52367af5dcd5SMatthias Ringwald                         break;
52377af5dcd5SMatthias Ringwald                 }
523824c20dc4SMatthias Ringwald                 break;
523924c20dc4SMatthias Ringwald             default:
524024c20dc4SMatthias Ringwald                 break;
524124c20dc4SMatthias Ringwald         }
52423deb3ec6SMatthias Ringwald     } else {
52433deb3ec6SMatthias Ringwald         // used as a trigger to start central/master/initiator security procedures
5244175b7faaSMatthias Ringwald         switch (sm_conn->sm_engine_state){
5245175b7faaSMatthias Ringwald             case SM_INITIATOR_CONNECTED:
52463deb3ec6SMatthias Ringwald                 switch (sm_conn->sm_irk_lookup_state){
52473deb3ec6SMatthias Ringwald                     case IRK_LOOKUP_SUCCEEDED:
52482d68601cSMatthias Ringwald                         le_device_db_encryption_get(sm_conn->sm_le_db_index, NULL, NULL, ltk, NULL, &authenticated, NULL, NULL);
5249f53ec649SMatthias Ringwald                         have_ltk = !sm_is_null_key(ltk);
52502d68601cSMatthias Ringwald                         auth_required = sm_auth_req & SM_AUTHREQ_MITM_PROTECTION;
52512d68601cSMatthias Ringwald                         // re-encrypt is sufficient if we have ltk and that is either already authenticated or we don't require authentication
52522d68601cSMatthias Ringwald                         trigger_reencryption = have_ltk && ((authenticated != 0) || (auth_required == false));
52532d68601cSMatthias Ringwald                         log_info("have ltk %u, authenticated %u, auth required %u => reencrypt %u", have_ltk, authenticated, auth_required, trigger_reencryption);
52542d68601cSMatthias Ringwald                         if (trigger_reencryption){
52555f3874afSMatthias Ringwald                             sm_conn->sm_pairing_requested = true;
52565567aa60SMatthias Ringwald                             sm_conn->sm_engine_state = SM_INITIATOR_PH4_HAS_LTK;
5257c245ca32SMatthias Ringwald                             break;
5258f53ec649SMatthias Ringwald                         }
5259cf373d3aSMatthias Ringwald                         /* fall through */
5260c245ca32SMatthias Ringwald 
526134c39fbdSMatthias Ringwald                     case IRK_LOOKUP_FAILED:
52623deb3ec6SMatthias Ringwald                         sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
52633deb3ec6SMatthias Ringwald                         break;
52643deb3ec6SMatthias Ringwald                     default:
5265d1a1f6a4SMatthias Ringwald                         log_info("irk lookup pending");
52665f3874afSMatthias Ringwald                         sm_conn->sm_pairing_requested = true;
52673deb3ec6SMatthias Ringwald                         break;
52683deb3ec6SMatthias Ringwald                 }
5269175b7faaSMatthias Ringwald                 break;
5270cb6d7eb0SMatthias Ringwald             case SM_GENERAL_REENCRYPTION_FAILED:
5271cb6d7eb0SMatthias Ringwald                 sm_conn->sm_engine_state = SM_INITIATOR_PH1_W2_SEND_PAIRING_REQUEST;
5272cb6d7eb0SMatthias Ringwald                 break;
5273175b7faaSMatthias Ringwald             case SM_GENERAL_IDLE:
52745f3874afSMatthias Ringwald                 sm_conn->sm_pairing_requested = true;
5275175b7faaSMatthias Ringwald                 break;
5276175b7faaSMatthias Ringwald             default:
5277175b7faaSMatthias Ringwald                 break;
52783deb3ec6SMatthias Ringwald         }
52793deb3ec6SMatthias Ringwald     }
528070b44dd4SMatthias Ringwald     sm_trigger_run();
52813deb3ec6SMatthias Ringwald }
52823deb3ec6SMatthias Ringwald 
52833deb3ec6SMatthias Ringwald // called by client app on authorization request
5284711e6c80SMatthias Ringwald void sm_authorization_decline(hci_con_handle_t con_handle){
5285711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52863deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52873deb3ec6SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_DECLINED;
5288589f5a99SMatthias 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);
52893deb3ec6SMatthias Ringwald }
52903deb3ec6SMatthias Ringwald 
5291711e6c80SMatthias Ringwald void sm_authorization_grant(hci_con_handle_t con_handle){
5292711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
52933deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
52943deb3ec6SMatthias Ringwald     sm_conn->sm_connection_authorization_state = AUTHORIZATION_GRANTED;
5295589f5a99SMatthias 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);
52963deb3ec6SMatthias Ringwald }
52973deb3ec6SMatthias Ringwald 
52983deb3ec6SMatthias Ringwald // GAP Bonding API
52993deb3ec6SMatthias Ringwald 
5300711e6c80SMatthias Ringwald void sm_bonding_decline(hci_con_handle_t con_handle){
5301711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53023deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53033deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_DECLINE;
53040af429c6SMatthias Ringwald     log_info("decline, state %u", sm_conn->sm_engine_state);
53050af429c6SMatthias Ringwald     switch(sm_conn->sm_engine_state){
53060af429c6SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
53070af429c6SMatthias Ringwald         case SM_SC_W4_USER_RESPONSE:
53080af429c6SMatthias Ringwald         case SM_SC_W4_CONFIRMATION:
53090af429c6SMatthias Ringwald         case SM_SC_W4_PUBLIC_KEY_COMMAND:
53100af429c6SMatthias Ringwald #endif
53110af429c6SMatthias Ringwald         case SM_PH1_W4_USER_RESPONSE:
5312de2fd182SMatthias Ringwald             switch (setup->sm_stk_generation_method){
5313de2fd182SMatthias Ringwald                 case PK_RESP_INPUT:
5314de2fd182SMatthias Ringwald                 case PK_INIT_INPUT:
531547fb4255SMatthias Ringwald                 case PK_BOTH_INPUT:
53160af429c6SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_PASSKEY_ENTRY_FAILED);
5317de2fd182SMatthias Ringwald                     break;
531847fb4255SMatthias Ringwald                 case NUMERIC_COMPARISON:
5319de2fd182SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_NUMERIC_COMPARISON_FAILED);
5320de2fd182SMatthias Ringwald                     break;
5321de2fd182SMatthias Ringwald                 case JUST_WORKS:
5322de2fd182SMatthias Ringwald                 case OOB:
5323de2fd182SMatthias Ringwald                     sm_pairing_error(sm_conn, SM_REASON_UNSPECIFIED_REASON);
5324de2fd182SMatthias Ringwald                     break;
53257bbeb3adSMilanka Ringwald                 default:
53267bbeb3adSMilanka Ringwald                     btstack_assert(false);
53277bbeb3adSMilanka Ringwald                     break;
5328de2fd182SMatthias Ringwald             }
53290af429c6SMatthias Ringwald             break;
53300af429c6SMatthias Ringwald         default:
53310af429c6SMatthias Ringwald             break;
53323deb3ec6SMatthias Ringwald     }
533370b44dd4SMatthias Ringwald     sm_trigger_run();
53343deb3ec6SMatthias Ringwald }
53353deb3ec6SMatthias Ringwald 
5336711e6c80SMatthias Ringwald void sm_just_works_confirm(hci_con_handle_t con_handle){
5337711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53383deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53393deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_CONFIRM;
53403deb3ec6SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_PH1_W4_USER_RESPONSE){
5341136d331aSMatthias Ringwald         if (setup->sm_use_secure_connections){
5342c6b7cbd9SMatthias Ringwald             sm_conn->sm_engine_state = SM_SC_SEND_PUBLIC_KEY_COMMAND;
5343bbf8db22SMatthias Ringwald         } else {
5344f3582630SMatthias 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);
5345136d331aSMatthias Ringwald         }
53463deb3ec6SMatthias Ringwald     }
53470346c37cSMatthias Ringwald 
53480346c37cSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
5349c6b7cbd9SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_USER_RESPONSE){
5350dc300847SMatthias Ringwald         sm_sc_prepare_dhkey_check(sm_conn);
5351446a8c36SMatthias Ringwald     }
53520346c37cSMatthias Ringwald #endif
53530346c37cSMatthias Ringwald 
535470b44dd4SMatthias Ringwald     sm_trigger_run();
53553deb3ec6SMatthias Ringwald }
53563deb3ec6SMatthias Ringwald 
5357c8c46d51SMatthias Ringwald void sm_numeric_comparison_confirm(hci_con_handle_t con_handle){
5358c8c46d51SMatthias Ringwald     // for now, it's the same
5359c8c46d51SMatthias Ringwald     sm_just_works_confirm(con_handle);
5360c8c46d51SMatthias Ringwald }
5361c8c46d51SMatthias Ringwald 
5362711e6c80SMatthias Ringwald void sm_passkey_input(hci_con_handle_t con_handle, uint32_t passkey){
5363711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53643deb3ec6SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53653deb3ec6SMatthias Ringwald     sm_reset_tk();
5366f8fbdce0SMatthias Ringwald     big_endian_store_32(setup->sm_tk, 12, passkey);
53673deb3ec6SMatthias Ringwald     setup->sm_user_response = SM_USER_RESPONSE_PASSKEY;
53683deb3ec6SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_PH1_W4_USER_RESPONSE){
5369f3582630SMatthias 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);
53703deb3ec6SMatthias Ringwald     }
53711c516d8fSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
53726535961aSMatthias Ringwald     (void)memcpy(setup->sm_ra, setup->sm_tk, 16);
53736535961aSMatthias Ringwald     (void)memcpy(setup->sm_rb, setup->sm_tk, 16);
537407036a04SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_SC_W4_USER_RESPONSE){
537507036a04SMatthias Ringwald         sm_sc_start_calculating_local_confirm(sm_conn);
537607036a04SMatthias Ringwald     }
53771c516d8fSMatthias Ringwald #endif
537870b44dd4SMatthias Ringwald     sm_trigger_run();
53793deb3ec6SMatthias Ringwald }
53803deb3ec6SMatthias Ringwald 
53813d7fe1e9SMatthias Ringwald void sm_keypress_notification(hci_con_handle_t con_handle, uint8_t action){
53823d7fe1e9SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
53833d7fe1e9SMatthias Ringwald     if (!sm_conn) return;     // wrong connection
53843d7fe1e9SMatthias Ringwald     if (action > SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED) return;
5385dd4a08fbSMatthias Ringwald     uint8_t num_actions = setup->sm_keypress_notification >> 5;
53864ea43905SMatthias Ringwald     uint8_t flags = setup->sm_keypress_notification & 0x1fu;
5387dd4a08fbSMatthias Ringwald     switch (action){
5388dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_ENTRY_STARTED:
5389dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_ENTRY_COMPLETED:
53904ea43905SMatthias Ringwald             flags |= (1u << action);
5391dd4a08fbSMatthias Ringwald             break;
5392dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_CLEARED:
5393dd4a08fbSMatthias Ringwald             // clear counter, keypress & erased flags + set passkey cleared
53944ea43905SMatthias Ringwald             flags = (flags & 0x19u) | (1u << SM_KEYPRESS_PASSKEY_CLEARED);
5395dd4a08fbSMatthias Ringwald             break;
5396dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_DIGIT_ENTERED:
53971d80f1e6SMatthias Ringwald             if ((flags & (1u << SM_KEYPRESS_PASSKEY_DIGIT_ERASED)) != 0u){
5398dd4a08fbSMatthias Ringwald                 // erase actions queued
5399dd4a08fbSMatthias Ringwald                 num_actions--;
54004ea43905SMatthias Ringwald                 if (num_actions == 0u){
5401dd4a08fbSMatthias Ringwald                     // clear counter, keypress & erased flags
54024ea43905SMatthias Ringwald                     flags &= 0x19u;
5403dd4a08fbSMatthias Ringwald                 }
5404dd4a08fbSMatthias Ringwald                 break;
5405dd4a08fbSMatthias Ringwald             }
5406dd4a08fbSMatthias Ringwald             num_actions++;
54074ea43905SMatthias Ringwald             flags |= (1u << SM_KEYPRESS_PASSKEY_DIGIT_ENTERED);
5408dd4a08fbSMatthias Ringwald             break;
5409dd4a08fbSMatthias Ringwald         case SM_KEYPRESS_PASSKEY_DIGIT_ERASED:
54101d80f1e6SMatthias Ringwald             if ((flags & (1u << SM_KEYPRESS_PASSKEY_DIGIT_ENTERED)) != 0u){
5411dd4a08fbSMatthias Ringwald                 // enter actions queued
5412dd4a08fbSMatthias Ringwald                 num_actions--;
54134ea43905SMatthias Ringwald                 if (num_actions == 0u){
5414dd4a08fbSMatthias Ringwald                     // clear counter, keypress & erased flags
54154ea43905SMatthias Ringwald                     flags &= 0x19u;
5416dd4a08fbSMatthias Ringwald                 }
5417dd4a08fbSMatthias Ringwald                 break;
5418dd4a08fbSMatthias Ringwald             }
5419dd4a08fbSMatthias Ringwald             num_actions++;
54204ea43905SMatthias Ringwald             flags |= (1u << SM_KEYPRESS_PASSKEY_DIGIT_ERASED);
5421dd4a08fbSMatthias Ringwald             break;
5422dd4a08fbSMatthias Ringwald         default:
5423dd4a08fbSMatthias Ringwald             break;
5424dd4a08fbSMatthias Ringwald     }
5425dd4a08fbSMatthias Ringwald     setup->sm_keypress_notification = (num_actions << 5) | flags;
542670b44dd4SMatthias Ringwald     sm_trigger_run();
54273d7fe1e9SMatthias Ringwald }
54283d7fe1e9SMatthias Ringwald 
5429c59d0c92SMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
5430d1a1f6a4SMatthias Ringwald static void sm_handle_random_result_oob(void * arg){
5431d1a1f6a4SMatthias Ringwald     UNUSED(arg);
5432d1a1f6a4SMatthias Ringwald     sm_sc_oob_state = SM_SC_OOB_W2_CALC_CONFIRM;
543370b44dd4SMatthias Ringwald     sm_trigger_run();
5434d1a1f6a4SMatthias Ringwald }
5435c59d0c92SMatthias Ringwald uint8_t sm_generate_sc_oob_data(void (*callback)(const uint8_t * confirm_value, const uint8_t * random_value)){
54368334d3d8SMatthias Ringwald 
54378334d3d8SMatthias Ringwald     static btstack_crypto_random_t   sm_crypto_random_oob_request;
54388334d3d8SMatthias Ringwald 
5439c59d0c92SMatthias Ringwald     if (sm_sc_oob_state != SM_SC_OOB_IDLE) return ERROR_CODE_COMMAND_DISALLOWED;
5440c59d0c92SMatthias Ringwald     sm_sc_oob_callback = callback;
5441d1a1f6a4SMatthias Ringwald     sm_sc_oob_state = SM_SC_OOB_W4_RANDOM;
5442d1a1f6a4SMatthias Ringwald     btstack_crypto_random_generate(&sm_crypto_random_oob_request, sm_sc_oob_random, 16, &sm_handle_random_result_oob, NULL);
5443c59d0c92SMatthias Ringwald     return 0;
5444c59d0c92SMatthias Ringwald }
5445c59d0c92SMatthias Ringwald #endif
5446c59d0c92SMatthias Ringwald 
54473deb3ec6SMatthias Ringwald /**
5448ba394633SMatthias Ringwald  * @brief Get Identity Resolving state
5449ba394633SMatthias Ringwald  * @param con_handle
5450ba394633SMatthias Ringwald  * @return irk_lookup_state_t
5451ba394633SMatthias Ringwald  */
5452ba394633SMatthias Ringwald irk_lookup_state_t sm_identity_resolving_state(hci_con_handle_t con_handle){
5453ba394633SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
5454ba394633SMatthias Ringwald     if (!sm_conn) return IRK_LOOKUP_IDLE;
5455ba394633SMatthias Ringwald     return sm_conn->sm_irk_lookup_state;
5456ba394633SMatthias Ringwald }
5457ba394633SMatthias Ringwald 
5458ba394633SMatthias Ringwald /**
54593deb3ec6SMatthias Ringwald  * @brief Identify device in LE Device DB
54603deb3ec6SMatthias Ringwald  * @param handle
54616b65794dSMilanka Ringwald  * @return index from le_device_db or -1 if not found/identified
54623deb3ec6SMatthias Ringwald  */
5463711e6c80SMatthias Ringwald int sm_le_device_index(hci_con_handle_t con_handle ){
5464711e6c80SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
54653deb3ec6SMatthias Ringwald     if (!sm_conn) return -1;
54663deb3ec6SMatthias Ringwald     return sm_conn->sm_le_db_index;
54673deb3ec6SMatthias Ringwald }
54683deb3ec6SMatthias Ringwald 
5469916ea5b2SMatthias Ringwald uint8_t sm_get_ltk(hci_con_handle_t con_handle, sm_key_t ltk){
5470916ea5b2SMatthias Ringwald     hci_connection_t * hci_connection = hci_connection_for_handle(con_handle);
5471916ea5b2SMatthias Ringwald     if (hci_connection == NULL){
5472916ea5b2SMatthias Ringwald         return ERROR_CODE_UNKNOWN_CONNECTION_IDENTIFIER;
5473916ea5b2SMatthias Ringwald     }
5474f728bb7bSMatthias Ringwald     if (hci_connection->link_key_type == INVALID_LINK_KEY){
5475916ea5b2SMatthias Ringwald         return ERROR_CODE_PIN_OR_KEY_MISSING;
5476916ea5b2SMatthias Ringwald     }
5477916ea5b2SMatthias Ringwald     memcpy(ltk, hci_connection->link_key, 16);
5478916ea5b2SMatthias Ringwald     return ERROR_CODE_SUCCESS;
5479916ea5b2SMatthias Ringwald }
5480916ea5b2SMatthias Ringwald 
54818f57b085SMatthias Ringwald static int gap_random_address_type_requires_updates(void){
548247ba4de1SMatthias Ringwald     switch (gap_random_adress_type){
548347ba4de1SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_OFF:
548447ba4de1SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_STATIC:
548547ba4de1SMatthias Ringwald             return 0;
548647ba4de1SMatthias Ringwald         default:
54878f57b085SMatthias Ringwald             return 1;
54888f57b085SMatthias Ringwald     }
548947ba4de1SMatthias Ringwald }
5490d70217a2SMatthias Ringwald 
549133373e40SMatthias Ringwald static uint8_t own_address_type(void){
5492b95a5a35SMatthias Ringwald     switch (gap_random_adress_type){
5493b95a5a35SMatthias Ringwald         case GAP_RANDOM_ADDRESS_TYPE_OFF:
5494b95a5a35SMatthias Ringwald             return BD_ADDR_TYPE_LE_PUBLIC;
5495b95a5a35SMatthias Ringwald         default:
5496b95a5a35SMatthias Ringwald             return BD_ADDR_TYPE_LE_RANDOM;
5497b95a5a35SMatthias Ringwald     }
549833373e40SMatthias Ringwald }
54998f57b085SMatthias Ringwald 
55003deb3ec6SMatthias Ringwald // GAP LE API
55013deb3ec6SMatthias Ringwald void gap_random_address_set_mode(gap_random_address_type_t random_address_type){
55023deb3ec6SMatthias Ringwald     gap_random_address_update_stop();
55033deb3ec6SMatthias Ringwald     gap_random_adress_type = random_address_type;
5504b95a5a35SMatthias Ringwald     hci_le_set_own_address_type(own_address_type());
55058f57b085SMatthias Ringwald     if (!gap_random_address_type_requires_updates()) return;
55063deb3ec6SMatthias Ringwald     gap_random_address_update_start();
55073deb3ec6SMatthias Ringwald     gap_random_address_trigger();
55083deb3ec6SMatthias Ringwald }
55093deb3ec6SMatthias Ringwald 
55103deb3ec6SMatthias Ringwald gap_random_address_type_t gap_random_address_get_mode(void){
55113deb3ec6SMatthias Ringwald     return gap_random_adress_type;
55123deb3ec6SMatthias Ringwald }
55133deb3ec6SMatthias Ringwald 
55143deb3ec6SMatthias Ringwald void gap_random_address_set_update_period(int period_ms){
55153deb3ec6SMatthias Ringwald     gap_random_adress_update_period = period_ms;
55168f57b085SMatthias Ringwald     if (!gap_random_address_type_requires_updates()) return;
55173deb3ec6SMatthias Ringwald     gap_random_address_update_stop();
55183deb3ec6SMatthias Ringwald     gap_random_address_update_start();
55193deb3ec6SMatthias Ringwald }
55203deb3ec6SMatthias Ringwald 
5521667ba9d1SMatthias Ringwald void gap_random_address_set(const bd_addr_t addr){
55228f57b085SMatthias Ringwald     gap_random_address_set_mode(GAP_RANDOM_ADDRESS_TYPE_STATIC);
55236535961aSMatthias Ringwald     (void)memcpy(sm_random_address, addr, 6);
552463d302e8SMatthias Ringwald     // assert msb bits are set to '11'
552563d302e8SMatthias Ringwald     sm_random_address[0] |= 0xc0;
552663d302e8SMatthias Ringwald     hci_le_random_address_set(sm_random_address);
55277e252622SMatthias Ringwald }
55287e252622SMatthias Ringwald 
5529d70217a2SMatthias Ringwald #ifdef ENABLE_LE_PERIPHERAL
55303deb3ec6SMatthias Ringwald /*
55313deb3ec6SMatthias Ringwald  * @brief Set Advertisement Paramters
55323deb3ec6SMatthias Ringwald  * @param adv_int_min
55333deb3ec6SMatthias Ringwald  * @param adv_int_max
55343deb3ec6SMatthias Ringwald  * @param adv_type
55353deb3ec6SMatthias Ringwald  * @param direct_address_type
55363deb3ec6SMatthias Ringwald  * @param direct_address
55373deb3ec6SMatthias Ringwald  * @param channel_map
55383deb3ec6SMatthias Ringwald  * @param filter_policy
55393deb3ec6SMatthias Ringwald  *
55403deb3ec6SMatthias Ringwald  * @note own_address_type is used from gap_random_address_set_mode
55413deb3ec6SMatthias Ringwald  */
55423deb3ec6SMatthias Ringwald void gap_advertisements_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type,
55433deb3ec6SMatthias Ringwald     uint8_t direct_address_typ, bd_addr_t direct_address, uint8_t channel_map, uint8_t filter_policy){
5544b95a5a35SMatthias Ringwald     hci_le_advertisements_set_params(adv_int_min, adv_int_max, adv_type,
55453deb3ec6SMatthias Ringwald         direct_address_typ, direct_address, channel_map, filter_policy);
55463deb3ec6SMatthias Ringwald }
5547d70217a2SMatthias Ringwald #endif
5548dcd6c9b5SMatthias Ringwald 
5549c7ceba59SMatthias Ringwald bool gap_reconnect_security_setup_active(hci_con_handle_t con_handle){
5550dcd6c9b5SMatthias Ringwald     sm_connection_t * sm_conn = sm_get_connection_for_handle(con_handle);
5551dcd6c9b5SMatthias Ringwald      // wrong connection
5552c7ceba59SMatthias Ringwald     if (!sm_conn) return false;
5553dcd6c9b5SMatthias Ringwald     // already encrypted
5554c7ceba59SMatthias Ringwald     if (sm_conn->sm_connection_encrypted) return false;
5555dcd6c9b5SMatthias Ringwald     // irk status?
5556dcd6c9b5SMatthias Ringwald     switch(sm_conn->sm_irk_lookup_state){
5557dcd6c9b5SMatthias Ringwald         case IRK_LOOKUP_FAILED:
5558dcd6c9b5SMatthias Ringwald             // done, cannot setup encryption
5559c7ceba59SMatthias Ringwald             return false;
5560dcd6c9b5SMatthias Ringwald         case IRK_LOOKUP_SUCCEEDED:
5561dcd6c9b5SMatthias Ringwald             break;
5562dcd6c9b5SMatthias Ringwald         default:
5563dcd6c9b5SMatthias Ringwald             // IR Lookup pending
5564c7ceba59SMatthias Ringwald             return true;
5565dcd6c9b5SMatthias Ringwald     }
5566f0674e22SMatthias Ringwald     // IRK Lookup Succeeded, re-encryption should be initiated. When done, state gets reset or indicates failure
5567c7ceba59SMatthias Ringwald     if (sm_conn->sm_engine_state == SM_GENERAL_REENCRYPTION_FAILED) return false;
5568c7ceba59SMatthias Ringwald     if (sm_conn->sm_role != 0){
5569b15d5ceaSMatthias Ringwald         return sm_conn->sm_engine_state != SM_RESPONDER_IDLE;
5570b15d5ceaSMatthias Ringwald     } else {
5571dcd6c9b5SMatthias Ringwald         return sm_conn->sm_engine_state != SM_INITIATOR_CONNECTED;
5572dcd6c9b5SMatthias Ringwald     }
5573b15d5ceaSMatthias Ringwald }
55743cdbe9dbSMatthias Ringwald 
55753cdbe9dbSMatthias Ringwald void sm_set_secure_connections_only_mode(bool enable){
55763cdbe9dbSMatthias Ringwald #ifdef ENABLE_LE_SECURE_CONNECTIONS
55773cdbe9dbSMatthias Ringwald     sm_sc_only_mode = enable;
55783cdbe9dbSMatthias Ringwald #else
55793cdbe9dbSMatthias Ringwald     // SC Only mode not possible without support for SC
55803cdbe9dbSMatthias Ringwald     btstack_assert(enable == false);
55813cdbe9dbSMatthias Ringwald #endif
55823cdbe9dbSMatthias Ringwald }
5583052bbdc5SMatthias Ringwald 
558492f8d6b6SMatthias Ringwald #if defined(ENABLE_LE_SECURE_CONNECTIONS) && defined (ENABLE_LE_SECURE_CONNECTION_DEBUG_KEY)
5585db88441fSMatthias Ringwald void sm_test_enable_secure_connections_debug_keys(void) {
5586db88441fSMatthias Ringwald     log_info("Enable LE Secure Connection Debug Keys for testing");
5587db88441fSMatthias Ringwald     sm_sc_debug_keys_enabled = true;
5588db88441fSMatthias Ringwald     // set debug key
5589db88441fSMatthias Ringwald     sm_ec_generate_new_key();
5590db88441fSMatthias Ringwald }
5591db88441fSMatthias Ringwald #endif
5592db88441fSMatthias Ringwald 
5593052bbdc5SMatthias Ringwald const uint8_t * gap_get_persistent_irk(void){
5594052bbdc5SMatthias Ringwald     return sm_persistent_irk;
5595052bbdc5SMatthias Ringwald }
55964f384501SMatthias Ringwald 
55974f384501SMatthias Ringwald void gap_delete_bonding(bd_addr_type_t address_type, bd_addr_t address){
559822cb578bSMatthias Ringwald     int index = sm_le_device_db_index_lookup(address_type, address);
559922cb578bSMatthias Ringwald     if (index >= 0){
560022cb578bSMatthias Ringwald         sm_remove_le_device_db_entry(index);
56014f384501SMatthias Ringwald     }
56024f384501SMatthias Ringwald }
5603