xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_sm_lgcy.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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