• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include "securec.h"
21 #include "nimble/ble.h"
22 #include "nimble/nimble_opt.h"
23 #include "host/ble_sm.h"
24 #include "ble_hs_priv.h"
25 
26 #if MYNEWT_VAL(BLE_SM_LEGACY)
27 
28 /**
29  * Create some shortened names for the passkey actions so that the table is
30  * easier to read.
31  */
32 #define IOACT_NONE  BLE_SM_IOACT_NONE
33 #define IOACT_OOB   BLE_SM_IOACT_OOB
34 #define IOACT_INPUT BLE_SM_IOACT_INPUT
35 #define IOACT_DISP  BLE_SM_IOACT_DISP
36 
37 /* This is the initiator passkey action action dpeneding on the io
38  * capabilties of both parties
39  */
40 static const uint8_t ble_sm_lgcy_init_ioa[5][5] = {
41     {IOACT_NONE,    IOACT_NONE,   IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
42     {IOACT_NONE,    IOACT_NONE,   IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
43     {IOACT_DISP,    IOACT_DISP,   IOACT_INPUT, IOACT_NONE, IOACT_DISP},
44     {IOACT_NONE,    IOACT_NONE,   IOACT_NONE,  IOACT_NONE, IOACT_NONE},
45     {IOACT_DISP,    IOACT_DISP,   IOACT_INPUT, IOACT_NONE, IOACT_DISP},
46 };
47 
48 /* This is the responder passkey action action depending on the io
49  * capabilities of both parties
50  */
51 static const uint8_t ble_sm_lgcy_resp_ioa[5][5] = {
52     {IOACT_NONE,    IOACT_NONE,   IOACT_DISP,  IOACT_NONE, IOACT_DISP},
53     {IOACT_NONE,    IOACT_NONE,   IOACT_DISP,  IOACT_NONE, IOACT_DISP},
54     {IOACT_INPUT,   IOACT_INPUT,  IOACT_INPUT, IOACT_NONE, IOACT_INPUT},
55     {IOACT_NONE,    IOACT_NONE,   IOACT_NONE,  IOACT_NONE, IOACT_NONE},
56     {IOACT_INPUT,   IOACT_INPUT,  IOACT_DISP,  IOACT_NONE, IOACT_INPUT},
57 };
58 
ble_sm_lgcy_io_action(struct ble_sm_proc * proc,uint8_t * action)59 int ble_sm_lgcy_io_action(struct ble_sm_proc *proc, uint8_t *action)
60 {
61     struct ble_sm_pair_cmd *pair_req, *pair_rsp;
62     pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
63     pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
64 
65     if (pair_req->oob_data_flag == BLE_SM_PAIR_OOB_YES &&
66             pair_rsp->oob_data_flag == BLE_SM_PAIR_OOB_YES) {
67         *action = BLE_SM_IOACT_OOB;
68     } else if (!(pair_req->authreq & BLE_SM_PAIR_AUTHREQ_MITM) &&
69               !(pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_MITM)) {
70         *action = BLE_SM_IOACT_NONE;
71     } else if (pair_req->io_cap >= BLE_SM_IO_CAP_RESERVED ||
72               pair_rsp->io_cap >= BLE_SM_IO_CAP_RESERVED) {
73         *action = BLE_SM_IOACT_NONE;
74     } else if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
75         *action = ble_sm_lgcy_init_ioa[pair_rsp->io_cap][pair_req->io_cap];
76     } else {
77         *action = ble_sm_lgcy_resp_ioa[pair_rsp->io_cap][pair_req->io_cap];
78     }
79 
80     switch (*action) {
81         case BLE_SM_IOACT_NONE:
82             proc->pair_alg = BLE_SM_PAIR_ALG_JW;
83             break;
84 
85         case BLE_SM_IOACT_OOB:
86             proc->pair_alg = BLE_SM_PAIR_ALG_OOB;
87             proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
88             break;
89 
90         case BLE_SM_IOACT_INPUT:
91         case BLE_SM_IOACT_DISP:
92             proc->pair_alg = BLE_SM_PAIR_ALG_PASSKEY;
93             proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
94             break;
95 
96         default:
97             BLE_HS_DBG_ASSERT(0);
98             return BLE_HS_EINVAL;
99     }
100 
101     return 0;
102 }
103 
ble_sm_lgcy_confirm_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)104 void ble_sm_lgcy_confirm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
105 {
106     struct ble_sm_pair_confirm *cmd;
107     struct os_mbuf *txom;
108     uint8_t ia[6];
109     uint8_t ra[6];
110     uint8_t iat;
111     uint8_t rat;
112     int rc;
113     cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_CONFIRM, sizeof(*cmd), &txom);
114     if (cmd == NULL) {
115         rc = BLE_HS_ENOMEM;
116         goto err;
117     }
118 
119     ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
120     rc = ble_sm_alg_c1(proc->tk, ble_sm_our_pair_rand(proc), proc->pair_req,
121                        proc->pair_rsp, iat, rat, ia, ra, cmd->value);
122     if (rc != 0) {
123         goto err;
124     }
125 
126     rc = ble_sm_tx(proc->conn_handle, txom);
127     if (rc != 0) {
128         goto err;
129     }
130 
131     if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
132         proc->state = BLE_SM_PROC_STATE_RANDOM;
133     }
134 
135     return;
136 err:
137 
138     if (txom) {
139         os_mbuf_free_chain(txom);
140     }
141 
142     res->app_status = rc;
143     res->enc_cb = 1;
144     res->sm_err = BLE_SM_ERR_UNSPECIFIED;
145 }
146 
ble_sm_gen_stk(struct ble_sm_proc * proc)147 static int ble_sm_gen_stk(struct ble_sm_proc *proc)
148 {
149     uint8_t key[16];
150     int rc;
151     rc = ble_sm_alg_s1(proc->tk, proc->rands, proc->randm, key);
152     if (rc != 0) {
153         return rc;
154     }
155 
156     memcpy_s(proc->ltk, sizeof(proc->ltk), key, proc->key_size);
157     /* Ensure proper key size */
158     memset_s(proc->ltk + proc->key_size, sizeof(proc->ltk + proc->key_size), 0, sizeof key - proc->key_size);
159     return 0;
160 }
161 
ble_sm_lgcy_random_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)162 void ble_sm_lgcy_random_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
163 {
164     struct ble_sm_pair_random *cmd;
165     struct os_mbuf *txom;
166     int rc;
167     cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_RANDOM, sizeof(*cmd), &txom);
168     if (cmd == NULL) {
169         res->app_status = BLE_HS_ENOMEM;
170         res->enc_cb = 1;
171         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
172         return;
173     }
174 
175     memcpy_s(cmd->value, sizeof(cmd->value), ble_sm_our_pair_rand(proc), 16); // 16:size
176     rc = ble_sm_tx(proc->conn_handle, txom);
177     if (rc != 0) {
178         res->app_status = rc;
179         res->enc_cb = 1;
180         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
181         return;
182     }
183 
184     if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
185         proc->state = BLE_SM_PROC_STATE_LTK_START;
186     }
187 }
188 
ble_sm_lgcy_random_rx(struct ble_sm_proc * proc,struct ble_sm_result * res)189 void ble_sm_lgcy_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
190 {
191     uint8_t confirm_val[16];
192     uint8_t ia[6];
193     uint8_t ra[6];
194     uint8_t iat;
195     uint8_t rat;
196     int rc;
197     ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
198     rc = ble_sm_alg_c1(proc->tk, ble_sm_peer_pair_rand(proc), proc->pair_req,
199                        proc->pair_rsp, iat, rat, ia, ra, confirm_val);
200     if (rc != 0) {
201         res->app_status = rc;
202         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
203         res->enc_cb = 1;
204         return;
205     }
206 
207     if (memcmp(proc->confirm_peer, confirm_val, 16) != 0) { // 16:size
208         /* Random number mismatch. */
209         res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH);
210         res->sm_err = BLE_SM_ERR_CONFIRM_MISMATCH;
211         res->enc_cb = 1;
212         return;
213     }
214 
215     /* Generate the key. */
216     rc = ble_sm_gen_stk(proc);
217     if (rc != 0) {
218         res->app_status = rc;
219         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
220         res->enc_cb = 1;
221         return;
222     }
223 
224     if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
225         /* Send the start-encrypt HCI command to the controller.   For
226          * short-term key generation, we always set ediv and rand to 0.
227          * (Vol. 3, part H, 2.4.4.1).
228          */
229         proc->state = BLE_SM_PROC_STATE_ENC_START;
230     }
231 
232     res->execute = 1;
233 }
234 
235 #endif