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 #include <errno.h>
22*042d53a7SEvalZero #include "nimble/ble.h"
23*042d53a7SEvalZero #include "nimble/nimble_opt.h"
24*042d53a7SEvalZero #include "host/ble_sm.h"
25*042d53a7SEvalZero #include "ble_hs_priv.h"
26*042d53a7SEvalZero
27*042d53a7SEvalZero #if MYNEWT_VAL(BLE_SM_LEGACY)
28*042d53a7SEvalZero
29*042d53a7SEvalZero /**
30*042d53a7SEvalZero * Create some shortened names for the passkey actions so that the table is
31*042d53a7SEvalZero * easier to read.
32*042d53a7SEvalZero */
33*042d53a7SEvalZero #define IOACT_NONE BLE_SM_IOACT_NONE
34*042d53a7SEvalZero #define IOACT_OOB BLE_SM_IOACT_OOB
35*042d53a7SEvalZero #define IOACT_INPUT BLE_SM_IOACT_INPUT
36*042d53a7SEvalZero #define IOACT_DISP BLE_SM_IOACT_DISP
37*042d53a7SEvalZero
38*042d53a7SEvalZero /* This is the initiator passkey action action dpeneding on the io
39*042d53a7SEvalZero * capabilties of both parties
40*042d53a7SEvalZero */
41*042d53a7SEvalZero static const uint8_t ble_sm_lgcy_init_ioa[5 /*resp*/ ][5 /*init*/ ] =
42*042d53a7SEvalZero {
43*042d53a7SEvalZero {IOACT_NONE, IOACT_NONE, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
44*042d53a7SEvalZero {IOACT_NONE, IOACT_NONE, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
45*042d53a7SEvalZero {IOACT_DISP, IOACT_DISP, IOACT_INPUT, IOACT_NONE, IOACT_DISP},
46*042d53a7SEvalZero {IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE},
47*042d53a7SEvalZero {IOACT_DISP, IOACT_DISP, IOACT_INPUT, IOACT_NONE, IOACT_DISP},
48*042d53a7SEvalZero };
49*042d53a7SEvalZero
50*042d53a7SEvalZero /* This is the responder passkey action action depending on the io
51*042d53a7SEvalZero * capabilities of both parties
52*042d53a7SEvalZero */
53*042d53a7SEvalZero static const uint8_t ble_sm_lgcy_resp_ioa[5 /*resp*/ ][5 /*init*/ ] =
54*042d53a7SEvalZero {
55*042d53a7SEvalZero {IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
56*042d53a7SEvalZero {IOACT_NONE, IOACT_NONE, IOACT_DISP, IOACT_NONE, IOACT_DISP},
57*042d53a7SEvalZero {IOACT_INPUT, IOACT_INPUT, IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
58*042d53a7SEvalZero {IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE, IOACT_NONE},
59*042d53a7SEvalZero {IOACT_INPUT, IOACT_INPUT, IOACT_DISP, IOACT_NONE, IOACT_INPUT},
60*042d53a7SEvalZero };
61*042d53a7SEvalZero
62*042d53a7SEvalZero int
ble_sm_lgcy_io_action(struct ble_sm_proc * proc,uint8_t * action)63*042d53a7SEvalZero ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action)
64*042d53a7SEvalZero {
65*042d53a7SEvalZero struct ble_sm_pair_cmd *pair_req, *pair_rsp;
66*042d53a7SEvalZero
67*042d53a7SEvalZero pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
68*042d53a7SEvalZero pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
69*042d53a7SEvalZero
70*042d53a7SEvalZero if (pair_req->oob_data_flag == BLE_SM_PAIR_OOB_YES &&
71*042d53a7SEvalZero pair_rsp->oob_data_flag == BLE_SM_PAIR_OOB_YES) {
72*042d53a7SEvalZero *action = BLE_SM_IOACT_OOB;
73*042d53a7SEvalZero } else if (!(pair_req->authreq & BLE_SM_PAIR_AUTHREQ_MITM) &&
74*042d53a7SEvalZero !(pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_MITM)) {
75*042d53a7SEvalZero
76*042d53a7SEvalZero *action = BLE_SM_IOACT_NONE;
77*042d53a7SEvalZero } else if (pair_req->io_cap >= BLE_SM_IO_CAP_RESERVED ||
78*042d53a7SEvalZero pair_rsp->io_cap >= BLE_SM_IO_CAP_RESERVED) {
79*042d53a7SEvalZero *action = BLE_SM_IOACT_NONE;
80*042d53a7SEvalZero } else if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
81*042d53a7SEvalZero *action = ble_sm_lgcy_init_ioa[pair_rsp->io_cap][pair_req->io_cap];
82*042d53a7SEvalZero } else {
83*042d53a7SEvalZero *action = ble_sm_lgcy_resp_ioa[pair_rsp->io_cap][pair_req->io_cap];
84*042d53a7SEvalZero }
85*042d53a7SEvalZero
86*042d53a7SEvalZero switch (*action) {
87*042d53a7SEvalZero case BLE_SM_IOACT_NONE:
88*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_JW;
89*042d53a7SEvalZero break;
90*042d53a7SEvalZero
91*042d53a7SEvalZero case BLE_SM_IOACT_OOB:
92*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_OOB;
93*042d53a7SEvalZero proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
94*042d53a7SEvalZero break;
95*042d53a7SEvalZero
96*042d53a7SEvalZero case BLE_SM_IOACT_INPUT:
97*042d53a7SEvalZero case BLE_SM_IOACT_DISP:
98*042d53a7SEvalZero proc->pair_alg = BLE_SM_PAIR_ALG_PASSKEY;
99*042d53a7SEvalZero proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
100*042d53a7SEvalZero break;
101*042d53a7SEvalZero
102*042d53a7SEvalZero default:
103*042d53a7SEvalZero BLE_HS_DBG_ASSERT(0);
104*042d53a7SEvalZero return BLE_HS_EINVAL;
105*042d53a7SEvalZero }
106*042d53a7SEvalZero
107*042d53a7SEvalZero return 0;
108*042d53a7SEvalZero }
109*042d53a7SEvalZero
110*042d53a7SEvalZero void
ble_sm_lgcy_confirm_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)111*042d53a7SEvalZero ble_sm_lgcy_confirm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
112*042d53a7SEvalZero {
113*042d53a7SEvalZero struct ble_sm_pair_confirm *cmd;
114*042d53a7SEvalZero struct os_mbuf *txom;
115*042d53a7SEvalZero uint8_t ia[6];
116*042d53a7SEvalZero uint8_t ra[6];
117*042d53a7SEvalZero uint8_t iat;
118*042d53a7SEvalZero uint8_t rat;
119*042d53a7SEvalZero int rc;
120*042d53a7SEvalZero
121*042d53a7SEvalZero cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_CONFIRM, sizeof(*cmd), &txom);
122*042d53a7SEvalZero if (cmd == NULL) {
123*042d53a7SEvalZero rc = BLE_HS_ENOMEM;
124*042d53a7SEvalZero goto err;
125*042d53a7SEvalZero }
126*042d53a7SEvalZero
127*042d53a7SEvalZero ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
128*042d53a7SEvalZero
129*042d53a7SEvalZero rc = ble_sm_alg_c1(proc->tk, ble_sm_our_pair_rand(proc), proc->pair_req,
130*042d53a7SEvalZero proc->pair_rsp, iat, rat, ia, ra, cmd->value);
131*042d53a7SEvalZero if (rc != 0) {
132*042d53a7SEvalZero goto err;
133*042d53a7SEvalZero }
134*042d53a7SEvalZero
135*042d53a7SEvalZero rc = ble_sm_tx(proc->conn_handle, txom);
136*042d53a7SEvalZero if (rc != 0) {
137*042d53a7SEvalZero goto err;
138*042d53a7SEvalZero }
139*042d53a7SEvalZero
140*042d53a7SEvalZero if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
141*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_RANDOM;
142*042d53a7SEvalZero }
143*042d53a7SEvalZero
144*042d53a7SEvalZero return;
145*042d53a7SEvalZero
146*042d53a7SEvalZero err:
147*042d53a7SEvalZero if (txom) {
148*042d53a7SEvalZero os_mbuf_free_chain(txom);
149*042d53a7SEvalZero }
150*042d53a7SEvalZero
151*042d53a7SEvalZero res->app_status = rc;
152*042d53a7SEvalZero res->enc_cb = 1;
153*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
154*042d53a7SEvalZero }
155*042d53a7SEvalZero
156*042d53a7SEvalZero static int
ble_sm_gen_stk(struct ble_sm_proc * proc)157*042d53a7SEvalZero ble_sm_gen_stk(struct ble_sm_proc *proc)
158*042d53a7SEvalZero {
159*042d53a7SEvalZero uint8_t key[16];
160*042d53a7SEvalZero int rc;
161*042d53a7SEvalZero
162*042d53a7SEvalZero rc = ble_sm_alg_s1(proc->tk, proc->rands, proc->randm, key);
163*042d53a7SEvalZero if (rc != 0) {
164*042d53a7SEvalZero return rc;
165*042d53a7SEvalZero }
166*042d53a7SEvalZero
167*042d53a7SEvalZero memcpy(proc->ltk, key, proc->key_size);
168*042d53a7SEvalZero
169*042d53a7SEvalZero /* Ensure proper key size */
170*042d53a7SEvalZero memset(proc->ltk + proc->key_size, 0, sizeof key - proc->key_size);
171*042d53a7SEvalZero
172*042d53a7SEvalZero return 0;
173*042d53a7SEvalZero }
174*042d53a7SEvalZero
175*042d53a7SEvalZero void
ble_sm_lgcy_random_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)176*042d53a7SEvalZero ble_sm_lgcy_random_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
177*042d53a7SEvalZero {
178*042d53a7SEvalZero struct ble_sm_pair_random *cmd;
179*042d53a7SEvalZero struct os_mbuf *txom;
180*042d53a7SEvalZero int rc;
181*042d53a7SEvalZero
182*042d53a7SEvalZero cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_RANDOM, sizeof(*cmd), &txom);
183*042d53a7SEvalZero if (cmd == NULL) {
184*042d53a7SEvalZero res->app_status = BLE_HS_ENOMEM;
185*042d53a7SEvalZero res->enc_cb = 1;
186*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
187*042d53a7SEvalZero return;
188*042d53a7SEvalZero }
189*042d53a7SEvalZero
190*042d53a7SEvalZero memcpy(cmd->value, ble_sm_our_pair_rand(proc), 16);
191*042d53a7SEvalZero
192*042d53a7SEvalZero rc = ble_sm_tx(proc->conn_handle, txom);
193*042d53a7SEvalZero if (rc != 0) {
194*042d53a7SEvalZero res->app_status = rc;
195*042d53a7SEvalZero res->enc_cb = 1;
196*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
197*042d53a7SEvalZero return;
198*042d53a7SEvalZero }
199*042d53a7SEvalZero
200*042d53a7SEvalZero if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
201*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_LTK_START;
202*042d53a7SEvalZero }
203*042d53a7SEvalZero }
204*042d53a7SEvalZero
205*042d53a7SEvalZero void
ble_sm_lgcy_random_rx(struct ble_sm_proc * proc,struct ble_sm_result * res)206*042d53a7SEvalZero ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
207*042d53a7SEvalZero {
208*042d53a7SEvalZero uint8_t confirm_val[16];
209*042d53a7SEvalZero uint8_t ia[6];
210*042d53a7SEvalZero uint8_t ra[6];
211*042d53a7SEvalZero uint8_t iat;
212*042d53a7SEvalZero uint8_t rat;
213*042d53a7SEvalZero int rc;
214*042d53a7SEvalZero
215*042d53a7SEvalZero ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
216*042d53a7SEvalZero
217*042d53a7SEvalZero rc = ble_sm_alg_c1(proc->tk, ble_sm_peer_pair_rand(proc), proc->pair_req,
218*042d53a7SEvalZero proc->pair_rsp, iat, rat, ia, ra, confirm_val);
219*042d53a7SEvalZero if (rc != 0) {
220*042d53a7SEvalZero res->app_status = rc;
221*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
222*042d53a7SEvalZero res->enc_cb = 1;
223*042d53a7SEvalZero return;
224*042d53a7SEvalZero }
225*042d53a7SEvalZero
226*042d53a7SEvalZero if (memcmp(proc->confirm_peer, confirm_val, 16) != 0) {
227*042d53a7SEvalZero /* Random number mismatch. */
228*042d53a7SEvalZero res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH);
229*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_CONFIRM_MISMATCH;
230*042d53a7SEvalZero res->enc_cb = 1;
231*042d53a7SEvalZero return;
232*042d53a7SEvalZero }
233*042d53a7SEvalZero
234*042d53a7SEvalZero /* Generate the key. */
235*042d53a7SEvalZero rc = ble_sm_gen_stk(proc);
236*042d53a7SEvalZero if (rc != 0) {
237*042d53a7SEvalZero res->app_status = rc;
238*042d53a7SEvalZero res->sm_err = BLE_SM_ERR_UNSPECIFIED;
239*042d53a7SEvalZero res->enc_cb = 1;
240*042d53a7SEvalZero return;
241*042d53a7SEvalZero }
242*042d53a7SEvalZero
243*042d53a7SEvalZero if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
244*042d53a7SEvalZero /* Send the start-encrypt HCI command to the controller. For
245*042d53a7SEvalZero * short-term key generation, we always set ediv and rand to 0.
246*042d53a7SEvalZero * (Vol. 3, part H, 2.4.4.1).
247*042d53a7SEvalZero */
248*042d53a7SEvalZero proc->state = BLE_SM_PROC_STATE_ENC_START;
249*042d53a7SEvalZero }
250*042d53a7SEvalZero
251*042d53a7SEvalZero res->execute = 1;
252*042d53a7SEvalZero }
253*042d53a7SEvalZero
254*042d53a7SEvalZero #endif
255