1*042d53a7SEvalZero /*
2*042d53a7SEvalZero * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero * or more contributor license agreements. See the NOTICE file
4*042d53a7SEvalZero * distributed with this work for additional information
5*042d53a7SEvalZero * regarding copyright ownership. The ASF licenses this file
6*042d53a7SEvalZero * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero * with the License. You may obtain a copy of the License at
9*042d53a7SEvalZero *
10*042d53a7SEvalZero * http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero *
12*042d53a7SEvalZero * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero * software distributed under the License is distributed on an
14*042d53a7SEvalZero * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero * KIND, either express or implied. See the License for the
16*042d53a7SEvalZero * specific language governing permissions and limitations
17*042d53a7SEvalZero * under the License.
18*042d53a7SEvalZero */
19*042d53a7SEvalZero
20*042d53a7SEvalZero #include <string.h>
21*042d53a7SEvalZero
22*042d53a7SEvalZero #include "nimble/nimble_opt.h"
23*042d53a7SEvalZero #include "host/ble_sm.h"
24*042d53a7SEvalZero #include "ble_hs_priv.h"
25*042d53a7SEvalZero #include "ble_sm_priv.h"
26*042d53a7SEvalZero
27*042d53a7SEvalZero #if MYNEWT_VAL(BLE_SM_SC)
28*042d53a7SEvalZero
29*042d53a7SEvalZero #define BLE_SM_SC_PASSKEY_BYTES 4
30*042d53a7SEvalZero #define BLE_SM_SC_PASSKEY_BITS 20
31*042d53a7SEvalZero
32*042d53a7SEvalZero static uint8_t ble_sm_sc_pub_key[64];
33*042d53a7SEvalZero static uint8_t ble_sm_sc_priv_key[32];
34*042d53a7SEvalZero
35*042d53a7SEvalZero /**
36*042d53a7SEvalZero * Whether our public-private key pair has been generated. We generate it on
37*042d53a7SEvalZero * startup for now until we have a non-volatile storage mechanism.
38*042d53a7SEvalZero */
39*042d53a7SEvalZero static uint8_t ble_sm_sc_keys_generated;
40*042d53a7SEvalZero
41*042d53a7SEvalZero /**
42*042d53a7SEvalZero * Create some shortened names for the passkey actions so that the table is
43*042d53a7SEvalZero * easier to read.
44*042d53a7SEvalZero */
45*042d53a7SEvalZero #define IOACT_NONE BLE_SM_IOACT_NONE
46*042d53a7SEvalZero #define IOACT_OOB BLE_SM_IOACT_OOB
47*042d53a7SEvalZero #define IOACT_INPUT BLE_SM_IOACT_INPUT
48*042d53a7SEvalZero #define IOACT_DISP BLE_SM_IOACT_DISP
49*042d53a7SEvalZero #define IOACT_NUMCMP BLE_SM_IOACT_NUMCMP
50*042d53a7SEvalZero
51*042d53a7SEvalZero /**
52*042d53a7SEvalZero * This table expresses the required initiator IO action. Inputs are:
53*042d53a7SEvalZero * o Responder IO capabilities (from pair response).
54*042d53a7SEvalZero * o Initiator IO capabilities (from pair request).
55*042d53a7SEvalZero */
56*042d53a7SEvalZero static const uint8_t ble_sm_sc_init_ioa[5 /*resp*/ ][5 /*init*/ ] =
57*042d53a7SEvalZero {
58*042d53a7SEvalZero /* init */
59*042d53a7SEvalZero /*r*/ {IOACT_NONE, IOACT_NONE, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
60*042d53a7SEvalZero /*e*/ {IOACT_NONE, IOACT_NUMCMP, IOACT_INPUT, IOACT_NONE, IOACT_NUMCMP},
61*042d53a7SEvalZero /*s*/ {IOACT_DISP, IOACT_DISP, IOACT_INPUT, IOACT_NONE, IOACT_DISP},
62*042d53a7SEvalZero /*p*/ {IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE},
63*042d53a7SEvalZero {IOACT_DISP, IOACT_NUMCMP, IOACT_INPUT, IOACT_NONE, IOACT_NUMCMP},
64*042d53a7SEvalZero };
65*042d53a7SEvalZero
66*042d53a7SEvalZero /**
67*042d53a7SEvalZero * This table expresses the required responder IO action. Inputs are:
68*042d53a7SEvalZero * o Responder IO capabilities (from pair response).
69*042d53a7SEvalZero * o Initiator IO capabilities (from pair request).
70*042d53a7SEvalZero */
71*042d53a7SEvalZero static const uint8_t ble_sm_sc_resp_ioa[5 /*resp*/ ][5 /*init*/ ] =
72*042d53a7SEvalZero {
73*042d53a7SEvalZero /* init */
74*042d53a7SEvalZero /*r*/ {IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
75*042d53a7SEvalZero /*e*/ {IOACT_NONE, IOACT_NUMCMP, IOACT_DISP, IOACT_NONE, IOACT_NUMCMP},
76*042d53a7SEvalZero /*s*/ {IOACT_INPUT, IOACT_INPUT, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
77*042d53a7SEvalZero /*p*/ {IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE},
78*042d53a7SEvalZero {IOACT_INPUT, IOACT_NUMCMP, IOACT_DISP, IOACT_NONE, IOACT_NUMCMP},
79*042d53a7SEvalZero };
80*042d53a7SEvalZero
81*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
82*042d53a7SEvalZero
83*042d53a7SEvalZero static uint8_t ble_sm_dbg_sc_pub_key[64];
84*042d53a7SEvalZero static uint8_t ble_sm_dbg_sc_priv_key[32];
85*042d53a7SEvalZero static uint8_t ble_sm_dbg_sc_keys_set;
86*042d53a7SEvalZero
87*042d53a7SEvalZero void
ble_sm_dbg_set_sc_keys(uint8_t * pubkey,uint8_t * privkey)88*042d53a7SEvalZero ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey)
89*042d53a7SEvalZero {
90*042d53a7SEvalZero memcpy(ble_sm_dbg_sc_pub_key, pubkey,
91*042d53a7SEvalZero sizeof ble_sm_dbg_sc_pub_key);
92*042d53a7SEvalZero memcpy(ble_sm_dbg_sc_priv_key, privkey,
93*042d53a7SEvalZero sizeof ble_sm_dbg_sc_priv_key);
94*042d53a7SEvalZero ble_sm_dbg_sc_keys_set = 1;
95*042d53a7SEvalZero }
96*042d53a7SEvalZero
97*042d53a7SEvalZero #endif
98*042d53a7SEvalZero
99*042d53a7SEvalZero int
ble_sm_sc_io_action(struct ble_sm_proc * proc,uint8_t * action)100*042d53a7SEvalZero ble_sm_sc_io_action(struct ble_sm_proc *proc, uint8_t *action)
101*042d53a7SEvalZero {
102*042d53a7SEvalZero struct ble_sm_pair_cmd *pair_req, *pair_rsp;
103*042d53a7SEvalZero
104*042d53a7SEvalZero pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
105*042d53a7SEvalZero pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
106*042d53a7SEvalZero
107*042d53a7SEvalZero if (pair_req->oob_data_flag == BLE_SM_PAIR_OOB_YES ||
108*042d53a7SEvalZero pair_rsp->oob_data_flag == BLE_SM_PAIR_OOB_YES) {
109*042d53a7SEvalZero *action = BLE_SM_IOACT_OOB;
110*042d53a7SEvalZero } else if (!(pair_req->authreq & BLE_SM_PAIR_AUTHREQ_MITM) &&
111*042d53a7SEvalZero !(pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_MITM)) {
112*042d53a7SEvalZero
113*042d53a7SEvalZero *action = BLE_SM_IOACT_NONE;
114*042d53a7SEvalZero } else if (pair_req->io_cap >= BLE_SM_IO_CAP_RESERVED ||
115*042d53a7SEvalZero pair_rsp->io_cap >= BLE_SM_IO_CAP_RESERVED) {
116*042d53a7SEvalZero *action = BLE_SM_IOACT_NONE;
117*042d53a7SEvalZero } else if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
118*042d53a7SEvalZero *action = ble_sm_sc_init_ioa[pair_rsp->io_cap][pair_req->io_cap];
119*042d53a7SEvalZero } else {
120*042d53a7SEvalZero *action = ble_sm_sc_resp_ioa[pair_rsp->io_cap][pair_req->io_cap];
121*042d53a7SEvalZero }
122*042d53a7SEvalZero
123*042d53a7SEvalZero switch (*action) {
124*042d53a7SEvalZero case BLE_SM_IOACT_NONE:
125*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_JW;
126*042d53a7SEvalZero break;
127*042d53a7SEvalZero
128*042d53a7SEvalZero case BLE_SM_IOACT_OOB:
129*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_OOB;
130*042d53a7SEvalZero proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
131*042d53a7SEvalZero break;
132*042d53a7SEvalZero
133*042d53a7SEvalZero case BLE_SM_IOACT_INPUT:
134*042d53a7SEvalZero case BLE_SM_IOACT_DISP:
135*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_PASSKEY;
136*042d53a7SEvalZero proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
137*042d53a7SEvalZero break;
138*042d53a7SEvalZero
139*042d53a7SEvalZero case BLE_SM_IOACT_NUMCMP:
140*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_NUMCMP;
141*042d53a7SEvalZero proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
142*042d53a7SEvalZero break;
143*042d53a7SEvalZero
144*042d53a7SEvalZero default:
145*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
146*042d53a7SEvalZero return BLE_HS_EINVAL;
147*042d53a7SEvalZero }
148*042d53a7SEvalZero
149*042d53a7SEvalZero return 0;
150*042d53a7SEvalZero }
151*042d53a7SEvalZero
152*042d53a7SEvalZero static int
ble_sm_gen_pub_priv(uint8_t * pub,uint8_t * priv)153*042d53a7SEvalZero ble_sm_gen_pub_priv(uint8_t *pub, uint8_t *priv)
154*042d53a7SEvalZero {
155*042d53a7SEvalZero int rc;
156*042d53a7SEvalZero
157*042d53a7SEvalZero #if MYNEWT_VAL(BLE_HS_DEBUG)
158*042d53a7SEvalZero if (ble_sm_dbg_sc_keys_set) {
159*042d53a7SEvalZero ble_sm_dbg_sc_keys_set = 0;
160*042d53a7SEvalZero memcpy(pub, ble_sm_dbg_sc_pub_key, sizeof ble_sm_dbg_sc_pub_key);
161*042d53a7SEvalZero memcpy(priv, ble_sm_dbg_sc_priv_key, sizeof ble_sm_dbg_sc_priv_key);
162*042d53a7SEvalZero return 0;
163*042d53a7SEvalZero }
164*042d53a7SEvalZero #endif
165*042d53a7SEvalZero
166*042d53a7SEvalZero rc = ble_sm_alg_gen_key_pair(pub, priv);
167*042d53a7SEvalZero if (rc != 0) {
168*042d53a7SEvalZero return rc;
169*042d53a7SEvalZero }
170*042d53a7SEvalZero
171*042d53a7SEvalZero return 0;
172*042d53a7SEvalZero }
173*042d53a7SEvalZero
174*042d53a7SEvalZero static int
ble_sm_sc_ensure_keys_generated(void)175*042d53a7SEvalZero ble_sm_sc_ensure_keys_generated(void)
176*042d53a7SEvalZero {
177*042d53a7SEvalZero int rc;
178*042d53a7SEvalZero
179*042d53a7SEvalZero if (!ble_sm_sc_keys_generated) {
180*042d53a7SEvalZero rc = ble_sm_gen_pub_priv(ble_sm_sc_pub_key, ble_sm_sc_priv_key);
181*042d53a7SEvalZero if (rc != 0) {
182*042d53a7SEvalZero return rc;
183*042d53a7SEvalZero }
184*042d53a7SEvalZero
185*042d53a7SEvalZero ble_sm_sc_keys_generated = 1;
186*042d53a7SEvalZero }
187*042d53a7SEvalZero
188*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "our pubkey=");
189*042d53a7SEvalZero ble_hs_log_flat_buf(&ble_sm_sc_pub_key, 64);
190*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "\n");
191*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "our privkey=");
192*042d53a7SEvalZero ble_hs_log_flat_buf(&ble_sm_sc_priv_key, 32);
193*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "\n");
194*042d53a7SEvalZero
195*042d53a7SEvalZero return 0;
196*042d53a7SEvalZero }
197*042d53a7SEvalZero
198*042d53a7SEvalZero /* Initiator does not send a confirm when pairing algorithm is any of:
199*042d53a7SEvalZero * o just works
200*042d53a7SEvalZero * o numeric comparison
201*042d53a7SEvalZero * (vol. 3, part H, 2.3.5.6.2)
202*042d53a7SEvalZero */
203*042d53a7SEvalZero static int
ble_sm_sc_initiator_txes_confirm(struct ble_sm_proc * proc)204*042d53a7SEvalZero ble_sm_sc_initiator_txes_confirm(struct ble_sm_proc *proc)
205*042d53a7SEvalZero {
206*042d53a7SEvalZero BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_SC);
207*042d53a7SEvalZero
208*042d53a7SEvalZero return proc->pair_alg != BLE_SM_PAIR_ALG_JW &&
209*042d53a7SEvalZero proc->pair_alg != BLE_SM_PAIR_ALG_NUMCMP;
210*042d53a7SEvalZero }
211*042d53a7SEvalZero
212*042d53a7SEvalZero /* Responder does not verify the initiator's random number when pairing
213*042d53a7SEvalZero * algorithm is any of:
214*042d53a7SEvalZero * o just works
215*042d53a7SEvalZero * o numeric comparison
216*042d53a7SEvalZero * (vol. 3, part H, 2.3.5.6.2)
217*042d53a7SEvalZero */
218*042d53a7SEvalZero static int
ble_sm_sc_responder_verifies_random(struct ble_sm_proc * proc)219*042d53a7SEvalZero ble_sm_sc_responder_verifies_random(struct ble_sm_proc *proc)
220*042d53a7SEvalZero {
221*042d53a7SEvalZero BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_SC);
222*042d53a7SEvalZero
223*042d53a7SEvalZero return proc->pair_alg != BLE_SM_PAIR_ALG_JW &&
224*042d53a7SEvalZero proc->pair_alg != BLE_SM_PAIR_ALG_NUMCMP;
225*042d53a7SEvalZero }
226*042d53a7SEvalZero
227*042d53a7SEvalZero /**
228*042d53a7SEvalZero * Generates the Ri byte used in the confirm message. On success, the byte is
229*042d53a7SEvalZero * written to the supplied procedure object.
230*042d53a7SEvalZero */
231*042d53a7SEvalZero static int
ble_sm_sc_gen_ri(struct ble_sm_proc * proc)232*042d53a7SEvalZero ble_sm_sc_gen_ri(struct ble_sm_proc *proc)
233*042d53a7SEvalZero {
234*042d53a7SEvalZero int byte;
235*042d53a7SEvalZero int bit;
236*042d53a7SEvalZero int rc;
237*042d53a7SEvalZero
238*042d53a7SEvalZero switch (proc->pair_alg) {
239*042d53a7SEvalZero case BLE_SM_PAIR_ALG_JW:
240*042d53a7SEvalZero case BLE_SM_PAIR_ALG_NUMCMP:
241*042d53a7SEvalZero proc->ri = 0;
242*042d53a7SEvalZero return 0;
243*042d53a7SEvalZero
244*042d53a7SEvalZero case BLE_SM_PAIR_ALG_PASSKEY:
245*042d53a7SEvalZero BLE_HS_DBG_ASSERT(proc->passkey_bits_exchanged <
246*042d53a7SEvalZero BLE_SM_SC_PASSKEY_BITS);
247*042d53a7SEvalZero
248*042d53a7SEvalZero byte = proc->passkey_bits_exchanged / 8;
249*042d53a7SEvalZero bit = proc->passkey_bits_exchanged % 8;
250*042d53a7SEvalZero proc->ri = 0x80 | !!(proc->tk[byte] & (1 << bit));
251*042d53a7SEvalZero
252*042d53a7SEvalZero proc->passkey_bits_exchanged++;
253*042d53a7SEvalZero
254*042d53a7SEvalZero return 0;
255*042d53a7SEvalZero
256*042d53a7SEvalZero case BLE_SM_PAIR_ALG_OOB:
257*042d53a7SEvalZero rc = ble_hs_hci_util_rand(&proc->ri, 1);
258*042d53a7SEvalZero return rc;
259*042d53a7SEvalZero
260*042d53a7SEvalZero default:
261*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
262*042d53a7SEvalZero return BLE_HS_EUNKNOWN;
263*042d53a7SEvalZero }
264*042d53a7SEvalZero }
265*042d53a7SEvalZero
266*042d53a7SEvalZero void
ble_sm_sc_confirm_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)267*042d53a7SEvalZero ble_sm_sc_confirm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
268*042d53a7SEvalZero {
269*042d53a7SEvalZero struct ble_sm_pair_confirm *cmd;
270*042d53a7SEvalZero struct os_mbuf *txom;
271*042d53a7SEvalZero int rc;
272*042d53a7SEvalZero
273*042d53a7SEvalZero rc = ble_sm_sc_gen_ri(proc);
274*042d53a7SEvalZero if (rc != 0) {
275*042d53a7SEvalZero res->app_status = rc;
276*042d53a7SEvalZero res->enc_cb = 1;
277*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
278*042d53a7SEvalZero return;
279*042d53a7SEvalZero }
280*042d53a7SEvalZero
281*042d53a7SEvalZero cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_CONFIRM, sizeof(*cmd), &txom);
282*042d53a7SEvalZero if (cmd == NULL) {
283*042d53a7SEvalZero rc = BLE_HS_ENOMEM;
284*042d53a7SEvalZero res->app_status = rc;
285*042d53a7SEvalZero res->enc_cb = 1;
286*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
287*042d53a7SEvalZero return;
288*042d53a7SEvalZero }
289*042d53a7SEvalZero
290*042d53a7SEvalZero rc = ble_sm_alg_f4(ble_sm_sc_pub_key, proc->pub_key_peer.x,
291*042d53a7SEvalZero ble_sm_our_pair_rand(proc), proc->ri, cmd->value);
292*042d53a7SEvalZero if (rc != 0) {
293*042d53a7SEvalZero os_mbuf_free_chain(txom);
294*042d53a7SEvalZero res->app_status = rc;
295*042d53a7SEvalZero res->enc_cb = 1;
296*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
297*042d53a7SEvalZero return;
298*042d53a7SEvalZero }
299*042d53a7SEvalZero
300*042d53a7SEvalZero rc = ble_sm_tx(proc->conn_handle, txom);
301*042d53a7SEvalZero if (rc != 0) {
302*042d53a7SEvalZero res->app_status = rc;
303*042d53a7SEvalZero res->enc_cb = 1;
304*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
305*042d53a7SEvalZero return;
306*042d53a7SEvalZero }
307*042d53a7SEvalZero
308*042d53a7SEvalZero if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
309*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_RANDOM;
310*042d53a7SEvalZero }
311*042d53a7SEvalZero }
312*042d53a7SEvalZero
313*042d53a7SEvalZero static void
ble_sm_sc_gen_numcmp(struct ble_sm_proc * proc,struct ble_sm_result * res)314*042d53a7SEvalZero ble_sm_sc_gen_numcmp(struct ble_sm_proc *proc, struct ble_sm_result *res)
315*042d53a7SEvalZero {
316*042d53a7SEvalZero uint8_t *pka;
317*042d53a7SEvalZero uint8_t *pkb;
318*042d53a7SEvalZero
319*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
320*042d53a7SEvalZero pka = ble_sm_sc_pub_key;
321*042d53a7SEvalZero pkb = proc->pub_key_peer.x;
322*042d53a7SEvalZero } else {
323*042d53a7SEvalZero pka = proc->pub_key_peer.x;
324*042d53a7SEvalZero pkb = ble_sm_sc_pub_key;
325*042d53a7SEvalZero }
326*042d53a7SEvalZero res->app_status = ble_sm_alg_g2(pka, pkb, proc->randm, proc->rands,
327*042d53a7SEvalZero &res->passkey_params.numcmp);
328*042d53a7SEvalZero if (res->app_status != 0) {
329*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
330*042d53a7SEvalZero res->enc_cb = 1;
331*042d53a7SEvalZero }
332*042d53a7SEvalZero }
333*042d53a7SEvalZero
334*042d53a7SEvalZero /**
335*042d53a7SEvalZero * Advances the supplied procedure object to the next state after it has
336*042d53a7SEvalZero * completed the random state.
337*042d53a7SEvalZero */
338*042d53a7SEvalZero static int
ble_sm_sc_random_advance(struct ble_sm_proc * proc)339*042d53a7SEvalZero ble_sm_sc_random_advance(struct ble_sm_proc *proc)
340*042d53a7SEvalZero {
341*042d53a7SEvalZero int rc;
342*042d53a7SEvalZero
343*042d53a7SEvalZero if (proc->pair_alg != BLE_SM_PAIR_ALG_PASSKEY ||
344*042d53a7SEvalZero proc->passkey_bits_exchanged >= BLE_SM_SC_PASSKEY_BITS) {
345*042d53a7SEvalZero
346*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_DHKEY_CHECK;
347*042d53a7SEvalZero } else {
348*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_CONFIRM;
349*042d53a7SEvalZero rc = ble_sm_gen_pair_rand(ble_sm_our_pair_rand(proc));
350*042d53a7SEvalZero if (rc != 0) {
351*042d53a7SEvalZero return rc;
352*042d53a7SEvalZero }
353*042d53a7SEvalZero }
354*042d53a7SEvalZero
355*042d53a7SEvalZero return 0;
356*042d53a7SEvalZero }
357*042d53a7SEvalZero
358*042d53a7SEvalZero void
ble_sm_sc_random_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)359*042d53a7SEvalZero ble_sm_sc_random_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
360*042d53a7SEvalZero {
361*042d53a7SEvalZero struct ble_sm_pair_random *cmd;
362*042d53a7SEvalZero struct os_mbuf *txom;
363*042d53a7SEvalZero uint8_t ioact;
364*042d53a7SEvalZero int rc;
365*042d53a7SEvalZero
366*042d53a7SEvalZero cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_RANDOM, sizeof(*cmd), &txom);
367*042d53a7SEvalZero if (cmd == NULL) {
368*042d53a7SEvalZero rc = BLE_HS_ENOMEM;
369*042d53a7SEvalZero res->enc_cb = 1;
370*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
371*042d53a7SEvalZero return;
372*042d53a7SEvalZero }
373*042d53a7SEvalZero
374*042d53a7SEvalZero memcpy(cmd->value, ble_sm_our_pair_rand(proc), 16);
375*042d53a7SEvalZero
376*042d53a7SEvalZero rc = ble_sm_tx(proc->conn_handle, txom);
377*042d53a7SEvalZero if (rc != 0) {
378*042d53a7SEvalZero res->app_status = rc;
379*042d53a7SEvalZero res->enc_cb = 1;
380*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
381*042d53a7SEvalZero return;
382*042d53a7SEvalZero }
383*042d53a7SEvalZero
384*042d53a7SEvalZero if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
385*042d53a7SEvalZero rc = ble_sm_sc_random_advance(proc);
386*042d53a7SEvalZero if (rc != 0) {
387*042d53a7SEvalZero res->app_status = rc;
388*042d53a7SEvalZero res->enc_cb = 1;
389*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
390*042d53a7SEvalZero return;
391*042d53a7SEvalZero }
392*042d53a7SEvalZero
393*042d53a7SEvalZero rc = ble_sm_sc_io_action(proc, &ioact);
394*042d53a7SEvalZero BLE_HS_DBG_ASSERT(rc == 0);
395*042d53a7SEvalZero
396*042d53a7SEvalZero if (ble_sm_ioact_state(ioact) == proc->state &&
397*042d53a7SEvalZero !(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
398*042d53a7SEvalZero
399*042d53a7SEvalZero res->passkey_params.action = ioact;
400*042d53a7SEvalZero BLE_HS_DBG_ASSERT(ioact == BLE_SM_IOACT_NUMCMP);
401*042d53a7SEvalZero ble_sm_sc_gen_numcmp(proc, res);
402*042d53a7SEvalZero }
403*042d53a7SEvalZero }
404*042d53a7SEvalZero }
405*042d53a7SEvalZero
406*042d53a7SEvalZero void
ble_sm_sc_random_rx(struct ble_sm_proc * proc,struct ble_sm_result * res)407*042d53a7SEvalZero ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
408*042d53a7SEvalZero {
409*042d53a7SEvalZero uint8_t confirm_val[16];
410*042d53a7SEvalZero uint8_t ia[6];
411*042d53a7SEvalZero uint8_t ra[6];
412*042d53a7SEvalZero uint8_t ioact;
413*042d53a7SEvalZero uint8_t iat;
414*042d53a7SEvalZero uint8_t rat;
415*042d53a7SEvalZero int rc;
416*042d53a7SEvalZero
417*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR ||
418*042d53a7SEvalZero ble_sm_sc_responder_verifies_random(proc)) {
419*042d53a7SEvalZero
420*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "tk=");
421*042d53a7SEvalZero ble_hs_log_flat_buf(proc->tk, 16);
422*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "\n");
423*042d53a7SEvalZero
424*042d53a7SEvalZero rc = ble_sm_alg_f4(proc->pub_key_peer.x, ble_sm_sc_pub_key,
425*042d53a7SEvalZero ble_sm_peer_pair_rand(proc), proc->ri,
426*042d53a7SEvalZero confirm_val);
427*042d53a7SEvalZero if (rc != 0) {
428*042d53a7SEvalZero res->app_status = rc;
429*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
430*042d53a7SEvalZero res->enc_cb = 1;
431*042d53a7SEvalZero return;
432*042d53a7SEvalZero }
433*042d53a7SEvalZero
434*042d53a7SEvalZero if (memcmp(proc->confirm_peer, confirm_val, 16) != 0) {
435*042d53a7SEvalZero /* Random number mismatch. */
436*042d53a7SEvalZero res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH);
437*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_CONFIRM_MISMATCH;
438*042d53a7SEvalZero res->enc_cb = 1;
439*042d53a7SEvalZero return;
440*042d53a7SEvalZero }
441*042d53a7SEvalZero }
442*042d53a7SEvalZero
443*042d53a7SEvalZero /* Calculate the mac key and ltk. */
444*042d53a7SEvalZero ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
445*042d53a7SEvalZero rc = ble_sm_alg_f5(proc->dhkey, proc->randm, proc->rands,
446*042d53a7SEvalZero iat, ia, rat, ra, proc->mackey, proc->ltk);
447*042d53a7SEvalZero if (rc != 0) {
448*042d53a7SEvalZero res->app_status = rc;
449*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
450*042d53a7SEvalZero res->enc_cb = 1;
451*042d53a7SEvalZero return;
452*042d53a7SEvalZero }
453*042d53a7SEvalZero
454*042d53a7SEvalZero /* Ensure proper key size */
455*042d53a7SEvalZero memset(proc->ltk + proc->key_size, 0, sizeof proc->ltk - proc->key_size);
456*042d53a7SEvalZero
457*042d53a7SEvalZero /* Ensure the ltk gets persisted when the pairing procedure succeeds. */
458*042d53a7SEvalZero memcpy(proc->our_keys.ltk, proc->ltk, sizeof proc->our_keys.ltk);
459*042d53a7SEvalZero proc->our_keys.ltk_valid = 1;
460*042d53a7SEvalZero proc->our_keys.ediv = 0;
461*042d53a7SEvalZero proc->our_keys.rand_val = 0;
462*042d53a7SEvalZero proc->our_keys.ediv_rand_valid = 1;
463*042d53a7SEvalZero
464*042d53a7SEvalZero memcpy(proc->peer_keys.ltk, proc->ltk, sizeof proc->peer_keys.ltk);
465*042d53a7SEvalZero proc->peer_keys.ltk_valid = 1;
466*042d53a7SEvalZero proc->peer_keys.ediv = 0;
467*042d53a7SEvalZero proc->peer_keys.rand_val = 0;
468*042d53a7SEvalZero proc->peer_keys.ediv_rand_valid = 1;
469*042d53a7SEvalZero
470*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
471*042d53a7SEvalZero ble_sm_sc_random_advance(proc);
472*042d53a7SEvalZero int rc;
473*042d53a7SEvalZero
474*042d53a7SEvalZero rc = ble_sm_sc_io_action(proc, &ioact);
475*042d53a7SEvalZero if (rc != 0) {
476*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
477*042d53a7SEvalZero }
478*042d53a7SEvalZero
479*042d53a7SEvalZero if (ble_sm_ioact_state(ioact) == proc->state &&
480*042d53a7SEvalZero !(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
481*042d53a7SEvalZero
482*042d53a7SEvalZero res->passkey_params.action = ioact;
483*042d53a7SEvalZero BLE_HS_DBG_ASSERT(ioact == BLE_SM_IOACT_NUMCMP);
484*042d53a7SEvalZero ble_sm_sc_gen_numcmp(proc, res);
485*042d53a7SEvalZero } else {
486*042d53a7SEvalZero res->execute = 1;
487*042d53a7SEvalZero }
488*042d53a7SEvalZero } else {
489*042d53a7SEvalZero res->execute = 1;
490*042d53a7SEvalZero }
491*042d53a7SEvalZero }
492*042d53a7SEvalZero
493*042d53a7SEvalZero void
ble_sm_sc_public_key_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)494*042d53a7SEvalZero ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
495*042d53a7SEvalZero void *arg)
496*042d53a7SEvalZero {
497*042d53a7SEvalZero struct ble_sm_public_key *cmd;
498*042d53a7SEvalZero struct os_mbuf *txom;
499*042d53a7SEvalZero uint8_t ioact;
500*042d53a7SEvalZero
501*042d53a7SEvalZero res->app_status = ble_sm_sc_ensure_keys_generated();
502*042d53a7SEvalZero if (res->app_status != 0) {
503*042d53a7SEvalZero res->enc_cb = 1;
504*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
505*042d53a7SEvalZero return;
506*042d53a7SEvalZero }
507*042d53a7SEvalZero
508*042d53a7SEvalZero cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_PUBLIC_KEY, sizeof(*cmd), &txom);
509*042d53a7SEvalZero if (!cmd) {
510*042d53a7SEvalZero res->app_status = BLE_HS_ENOMEM;
511*042d53a7SEvalZero res->enc_cb = 1;
512*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
513*042d53a7SEvalZero return;
514*042d53a7SEvalZero }
515*042d53a7SEvalZero
516*042d53a7SEvalZero memcpy(cmd->x, ble_sm_sc_pub_key + 0, 32);
517*042d53a7SEvalZero memcpy(cmd->y, ble_sm_sc_pub_key + 32, 32);
518*042d53a7SEvalZero
519*042d53a7SEvalZero res->app_status = ble_sm_tx(proc->conn_handle, txom);
520*042d53a7SEvalZero if (res->app_status != 0) {
521*042d53a7SEvalZero res->enc_cb = 1;
522*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
523*042d53a7SEvalZero return;
524*042d53a7SEvalZero }
525*042d53a7SEvalZero
526*042d53a7SEvalZero if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
527*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_CONFIRM;
528*042d53a7SEvalZero int rc;
529*042d53a7SEvalZero
530*042d53a7SEvalZero rc = ble_sm_sc_io_action(proc, &ioact);
531*042d53a7SEvalZero if (rc != 0) {
532*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
533*042d53a7SEvalZero }
534*042d53a7SEvalZero
535*042d53a7SEvalZero if (ble_sm_ioact_state(ioact) == proc->state) {
536*042d53a7SEvalZero res->passkey_params.action = ioact;
537*042d53a7SEvalZero }
538*042d53a7SEvalZero
539*042d53a7SEvalZero if (ble_sm_proc_can_advance(proc) &&
540*042d53a7SEvalZero !ble_sm_sc_initiator_txes_confirm(proc)) {
541*042d53a7SEvalZero
542*042d53a7SEvalZero res->execute = 1;
543*042d53a7SEvalZero }
544*042d53a7SEvalZero }
545*042d53a7SEvalZero }
546*042d53a7SEvalZero
547*042d53a7SEvalZero void
ble_sm_sc_public_key_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)548*042d53a7SEvalZero ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **om,
549*042d53a7SEvalZero struct ble_sm_result *res)
550*042d53a7SEvalZero {
551*042d53a7SEvalZero struct ble_sm_public_key *cmd;
552*042d53a7SEvalZero struct ble_sm_proc *proc;
553*042d53a7SEvalZero uint8_t ioact;
554*042d53a7SEvalZero int rc;
555*042d53a7SEvalZero
556*042d53a7SEvalZero res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
557*042d53a7SEvalZero if (res->app_status != 0) {
558*042d53a7SEvalZero res->enc_cb = 1;
559*042d53a7SEvalZero return;
560*042d53a7SEvalZero }
561*042d53a7SEvalZero
562*042d53a7SEvalZero res->app_status = ble_sm_sc_ensure_keys_generated();
563*042d53a7SEvalZero if (res->app_status != 0) {
564*042d53a7SEvalZero res->enc_cb = 1;
565*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
566*042d53a7SEvalZero return;
567*042d53a7SEvalZero }
568*042d53a7SEvalZero
569*042d53a7SEvalZero cmd = (struct ble_sm_public_key *)(*om)->om_data;
570*042d53a7SEvalZero BLE_SM_LOG_CMD(0, "public key", conn_handle, ble_sm_public_key_log, cmd);
571*042d53a7SEvalZero
572*042d53a7SEvalZero ble_hs_lock();
573*042d53a7SEvalZero proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PUBLIC_KEY, -1,
574*042d53a7SEvalZero NULL);
575*042d53a7SEvalZero if (proc == NULL) {
576*042d53a7SEvalZero res->app_status = BLE_HS_ENOENT;
577*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
578*042d53a7SEvalZero } else {
579*042d53a7SEvalZero memcpy(&proc->pub_key_peer, cmd, sizeof(*cmd));
580*042d53a7SEvalZero rc = ble_sm_alg_gen_dhkey(proc->pub_key_peer.x,
581*042d53a7SEvalZero proc->pub_key_peer.y,
582*042d53a7SEvalZero ble_sm_sc_priv_key,
583*042d53a7SEvalZero proc->dhkey);
584*042d53a7SEvalZero if (rc != 0) {
585*042d53a7SEvalZero res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_DHKEY);
586*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_DHKEY;
587*042d53a7SEvalZero res->enc_cb = 1;
588*042d53a7SEvalZero } else {
589*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
590*042d53a7SEvalZero int rc;
591*042d53a7SEvalZero
592*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_CONFIRM;
593*042d53a7SEvalZero
594*042d53a7SEvalZero rc = ble_sm_sc_io_action(proc, &ioact);
595*042d53a7SEvalZero if (rc != 0) {
596*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
597*042d53a7SEvalZero }
598*042d53a7SEvalZero
599*042d53a7SEvalZero if (ble_sm_ioact_state(ioact) == proc->state) {
600*042d53a7SEvalZero res->passkey_params.action = ioact;
601*042d53a7SEvalZero }
602*042d53a7SEvalZero
603*042d53a7SEvalZero if (ble_sm_proc_can_advance(proc) &&
604*042d53a7SEvalZero ble_sm_sc_initiator_txes_confirm(proc)) {
605*042d53a7SEvalZero
606*042d53a7SEvalZero res->execute = 1;
607*042d53a7SEvalZero }
608*042d53a7SEvalZero } else {
609*042d53a7SEvalZero res->execute = 1;
610*042d53a7SEvalZero }
611*042d53a7SEvalZero }
612*042d53a7SEvalZero }
613*042d53a7SEvalZero ble_hs_unlock();
614*042d53a7SEvalZero }
615*042d53a7SEvalZero
616*042d53a7SEvalZero static void
ble_sm_sc_dhkey_addrs(struct ble_sm_proc * proc,ble_addr_t * our_addr,ble_addr_t * peer_addr)617*042d53a7SEvalZero ble_sm_sc_dhkey_addrs(struct ble_sm_proc *proc, ble_addr_t *our_addr,
618*042d53a7SEvalZero ble_addr_t *peer_addr)
619*042d53a7SEvalZero {
620*042d53a7SEvalZero struct ble_hs_conn_addrs addrs;
621*042d53a7SEvalZero struct ble_hs_conn *conn;
622*042d53a7SEvalZero
623*042d53a7SEvalZero conn = ble_hs_conn_find_assert(proc->conn_handle);
624*042d53a7SEvalZero
625*042d53a7SEvalZero ble_hs_conn_addrs(conn, &addrs);
626*042d53a7SEvalZero
627*042d53a7SEvalZero *our_addr = addrs.our_ota_addr;
628*042d53a7SEvalZero *peer_addr = addrs.peer_ota_addr;
629*042d53a7SEvalZero }
630*042d53a7SEvalZero
631*042d53a7SEvalZero void
ble_sm_sc_dhkey_check_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)632*042d53a7SEvalZero ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
633*042d53a7SEvalZero void *arg)
634*042d53a7SEvalZero {
635*042d53a7SEvalZero struct ble_sm_dhkey_check *cmd;
636*042d53a7SEvalZero ble_addr_t our_addr;
637*042d53a7SEvalZero ble_addr_t peer_addr;
638*042d53a7SEvalZero struct os_mbuf *txom;
639*042d53a7SEvalZero uint8_t *iocap;
640*042d53a7SEvalZero int rc;
641*042d53a7SEvalZero
642*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
643*042d53a7SEvalZero struct ble_sm_pair_cmd *pair_req;
644*042d53a7SEvalZero
645*042d53a7SEvalZero pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
646*042d53a7SEvalZero iocap = &pair_req->io_cap;
647*042d53a7SEvalZero } else {
648*042d53a7SEvalZero struct ble_sm_pair_cmd *pair_rsp;
649*042d53a7SEvalZero
650*042d53a7SEvalZero pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
651*042d53a7SEvalZero iocap = &pair_rsp->io_cap;
652*042d53a7SEvalZero }
653*042d53a7SEvalZero
654*042d53a7SEvalZero ble_sm_sc_dhkey_addrs(proc, &our_addr, &peer_addr);
655*042d53a7SEvalZero
656*042d53a7SEvalZero cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_DHKEY_CHECK, sizeof(*cmd), &txom);
657*042d53a7SEvalZero if (!cmd) {
658*042d53a7SEvalZero rc = BLE_HS_ENOMEM;
659*042d53a7SEvalZero goto err;
660*042d53a7SEvalZero }
661*042d53a7SEvalZero
662*042d53a7SEvalZero rc = ble_sm_alg_f6(proc->mackey, ble_sm_our_pair_rand(proc),
663*042d53a7SEvalZero ble_sm_peer_pair_rand(proc), proc->tk, iocap,
664*042d53a7SEvalZero our_addr.type, our_addr.val, peer_addr.type,
665*042d53a7SEvalZero peer_addr.val, cmd->value);
666*042d53a7SEvalZero if (rc != 0) {
667*042d53a7SEvalZero os_mbuf_free_chain(txom);
668*042d53a7SEvalZero goto err;
669*042d53a7SEvalZero }
670*042d53a7SEvalZero
671*042d53a7SEvalZero rc = ble_sm_tx(proc->conn_handle, txom);
672*042d53a7SEvalZero if (rc != 0) {
673*042d53a7SEvalZero goto err;
674*042d53a7SEvalZero }
675*042d53a7SEvalZero
676*042d53a7SEvalZero if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
677*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_LTK_START;
678*042d53a7SEvalZero }
679*042d53a7SEvalZero
680*042d53a7SEvalZero return;
681*042d53a7SEvalZero
682*042d53a7SEvalZero err:
683*042d53a7SEvalZero res->app_status = rc;
684*042d53a7SEvalZero res->enc_cb = 1;
685*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
686*042d53a7SEvalZero }
687*042d53a7SEvalZero
688*042d53a7SEvalZero static void
ble_sm_dhkey_check_process(struct ble_sm_proc * proc,struct ble_sm_dhkey_check * cmd,struct ble_sm_result * res)689*042d53a7SEvalZero ble_sm_dhkey_check_process(struct ble_sm_proc *proc,
690*042d53a7SEvalZero struct ble_sm_dhkey_check *cmd,
691*042d53a7SEvalZero struct ble_sm_result *res)
692*042d53a7SEvalZero {
693*042d53a7SEvalZero uint8_t exp_value[16];
694*042d53a7SEvalZero ble_addr_t our_addr;
695*042d53a7SEvalZero ble_addr_t peer_addr;
696*042d53a7SEvalZero uint8_t *iocap;
697*042d53a7SEvalZero uint8_t ioact;
698*042d53a7SEvalZero int rc;
699*042d53a7SEvalZero
700*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
701*042d53a7SEvalZero struct ble_sm_pair_cmd *pair_rsp;
702*042d53a7SEvalZero
703*042d53a7SEvalZero pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
704*042d53a7SEvalZero iocap = &pair_rsp->io_cap;
705*042d53a7SEvalZero } else {
706*042d53a7SEvalZero struct ble_sm_pair_cmd *pair_req;
707*042d53a7SEvalZero
708*042d53a7SEvalZero pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
709*042d53a7SEvalZero iocap = &pair_req->io_cap;
710*042d53a7SEvalZero }
711*042d53a7SEvalZero
712*042d53a7SEvalZero ble_sm_sc_dhkey_addrs(proc, &our_addr, &peer_addr);
713*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "tk=");
714*042d53a7SEvalZero ble_hs_log_flat_buf(proc->tk, 16);
715*042d53a7SEvalZero BLE_HS_LOG(DEBUG, "\n");
716*042d53a7SEvalZero
717*042d53a7SEvalZero res->app_status = ble_sm_alg_f6(proc->mackey,
718*042d53a7SEvalZero ble_sm_peer_pair_rand(proc),
719*042d53a7SEvalZero ble_sm_our_pair_rand(proc),
720*042d53a7SEvalZero proc->tk, iocap,
721*042d53a7SEvalZero peer_addr.type, peer_addr.val,
722*042d53a7SEvalZero our_addr.type, our_addr.val,
723*042d53a7SEvalZero exp_value);
724*042d53a7SEvalZero if (res->app_status != 0) {
725*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
726*042d53a7SEvalZero res->enc_cb = 1;
727*042d53a7SEvalZero return;
728*042d53a7SEvalZero }
729*042d53a7SEvalZero
730*042d53a7SEvalZero if (memcmp(cmd->value, exp_value, 16) != 0) {
731*042d53a7SEvalZero /* Random number mismatch. */
732*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_DHKEY;
733*042d53a7SEvalZero res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_DHKEY);
734*042d53a7SEvalZero res->enc_cb = 1;
735*042d53a7SEvalZero return;
736*042d53a7SEvalZero }
737*042d53a7SEvalZero
738*042d53a7SEvalZero rc = ble_sm_sc_io_action(proc, &ioact);
739*042d53a7SEvalZero if (rc != 0) {
740*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
741*042d53a7SEvalZero }
742*042d53a7SEvalZero
743*042d53a7SEvalZero if (ble_sm_ioact_state(ioact) == proc->state) {
744*042d53a7SEvalZero proc->flags |= BLE_SM_PROC_F_ADVANCE_ON_IO;
745*042d53a7SEvalZero }
746*042d53a7SEvalZero
747*042d53a7SEvalZero if (ble_sm_proc_can_advance(proc)) {
748*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
749*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_ENC_START;
750*042d53a7SEvalZero }
751*042d53a7SEvalZero
752*042d53a7SEvalZero res->execute = 1;
753*042d53a7SEvalZero }
754*042d53a7SEvalZero }
755*042d53a7SEvalZero
756*042d53a7SEvalZero void
ble_sm_sc_dhkey_check_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)757*042d53a7SEvalZero ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **om,
758*042d53a7SEvalZero struct ble_sm_result *res)
759*042d53a7SEvalZero {
760*042d53a7SEvalZero struct ble_sm_dhkey_check *cmd;
761*042d53a7SEvalZero struct ble_sm_proc *proc;
762*042d53a7SEvalZero
763*042d53a7SEvalZero res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
764*042d53a7SEvalZero if (res->app_status != 0) {
765*042d53a7SEvalZero res->enc_cb = 1;
766*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
767*042d53a7SEvalZero return;
768*042d53a7SEvalZero }
769*042d53a7SEvalZero
770*042d53a7SEvalZero cmd = (struct ble_sm_dhkey_check *)(*om)->om_data;
771*042d53a7SEvalZero BLE_SM_LOG_CMD(0, "dhkey check", conn_handle, ble_sm_dhkey_check_log, cmd);
772*042d53a7SEvalZero
773*042d53a7SEvalZero ble_hs_lock();
774*042d53a7SEvalZero proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_DHKEY_CHECK, -1,
775*042d53a7SEvalZero NULL);
776*042d53a7SEvalZero if (proc == NULL) {
777*042d53a7SEvalZero res->app_status = BLE_HS_ENOENT;
778*042d53a7SEvalZero } else {
779*042d53a7SEvalZero ble_sm_dhkey_check_process(proc, cmd, res);
780*042d53a7SEvalZero }
781*042d53a7SEvalZero ble_hs_unlock();
782*042d53a7SEvalZero }
783*042d53a7SEvalZero
784*042d53a7SEvalZero void
ble_sm_sc_init(void)785*042d53a7SEvalZero ble_sm_sc_init(void)
786*042d53a7SEvalZero {
787*042d53a7SEvalZero ble_sm_alg_ecc_init();
788*042d53a7SEvalZero ble_sm_sc_keys_generated = 0;
789*042d53a7SEvalZero }
790*042d53a7SEvalZero
791*042d53a7SEvalZero #endif /* MYNEWT_VAL(BLE_SM_SC) */
792