1/******************************************************************************
2 *
3 *  Copyright (C) 2008-2012 Broadcom Corporation
4 *
5 *  Licensed under the Apache License, Version 2.0 (the "License");
6 *  you may not use this file except in compliance with the License.
7 *  You may obtain a copy of the License at:
8 *
9 *  http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 *
17 ******************************************************************************/
18
19/******************************************************************************
20 *
21 *  This file contains the implementation of the SMP interface used by
22 *  applications that can run over an SMP.
23 *
24 ******************************************************************************/
25#include <string.h>
26
27#include "bt_target.h"
28#if SMP_INCLUDED == TRUE
29    #include "smp_int.h"
30    #include "smp_api.h"
31    #include "l2cdefs.h"
32    #include "l2c_int.h"
33    #include "btm_int.h"
34    #include "hcimsgs.h"
35
36    #include "btu.h"
37
38
39/*******************************************************************************
40**
41** Function         SMP_Init
42**
43** Description      This function initializes the SMP unit.
44**
45** Returns          void
46**
47*******************************************************************************/
48void SMP_Init(void)
49{
50
51    SMP_TRACE_EVENT0 ("SMP_Init");
52    memset(&smp_cb, 0, sizeof(tSMP_CB));
53
54#if defined(SMP_INITIAL_TRACE_LEVEL)
55    smp_cb.trace_level = SMP_INITIAL_TRACE_LEVEL;
56#else
57    smp_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
58#endif
59
60    smp_l2cap_if_init();
61}
62
63
64/*******************************************************************************
65**
66** Function         SMP_SetTraceLevel
67**
68** Description      This function sets the trace level for SMP.  If called with
69**                  a value of 0xFF, it simply returns the current trace level.
70**
71**                  Input Parameters:
72**                      level:  The level to set the GATT tracing to:
73**                      0xff-returns the current setting.
74**                      0-turns off tracing.
75**                      >= 1-Errors.
76**                      >= 2-Warnings.
77**                      >= 3-APIs.
78**                      >= 4-Events.
79**                      >= 5-Debug.
80**
81** Returns          The new or current trace level
82**
83*******************************************************************************/
84SMP_API extern UINT8 SMP_SetTraceLevel (UINT8 new_level)
85{
86    if (new_level != 0xFF)
87        smp_cb.trace_level = new_level;
88
89    return(smp_cb.trace_level);
90}
91
92
93/*******************************************************************************
94**
95** Function         SMP_Register
96**
97** Description      This function register for the SMP services callback.
98**
99** Returns          void
100**
101*******************************************************************************/
102BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback)
103{
104    SMP_TRACE_EVENT1 ("SMP_Register state=%d", smp_cb.state);
105
106    if (smp_cb.p_callback != NULL)
107    {
108        SMP_TRACE_ERROR0 ("SMP_Register: duplicate registration, overwrite it");
109    }
110    smp_cb.p_callback = p_cback;
111
112    return(TRUE);
113
114}
115
116/*******************************************************************************
117**
118** Function         SMP_Pair
119**
120** Description      This function call to perform a SMP pairing with peer device.
121**                  Device support one SMP pairing at one time.
122**
123** Parameters       bd_addr - peer device bd address.
124**
125** Returns          None
126**
127*******************************************************************************/
128tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
129{
130    tSMP_CB   *p_cb = &smp_cb;
131    UINT8     status = SMP_PAIR_INTERNAL_ERR;
132
133    BTM_TRACE_EVENT2 ("SMP_Pair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
134    if (p_cb->state != SMP_ST_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
135    {
136        /* pending security on going, reject this one */
137        return SMP_BUSY;
138    }
139    else
140    {
141        p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
142
143        memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
144
145        if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr))
146        {
147            SMP_TRACE_ERROR0("SMP_Pair: L2C connect fixed channel failed.");
148            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
149            return status;
150        }
151
152        return SMP_STARTED;
153    }
154}
155
156
157/*******************************************************************************
158**
159** Function         SMP_PairCancel
160**
161** Description      This function call to cancel a SMP pairing with peer device.
162**
163** Parameters       bd_addr - peer device bd address.
164**
165** Returns          TRUE - Pairining is cancelled
166**
167*******************************************************************************/
168BOOLEAN SMP_PairCancel (BD_ADDR bd_addr)
169{
170    tSMP_CB   *p_cb = &smp_cb;
171    UINT8     err_code = SMP_PAIR_FAIL_UNKNOWN;
172    BOOLEAN   status = FALSE;
173
174    BTM_TRACE_EVENT2 ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
175    if ( (p_cb->state != SMP_ST_IDLE)  &&
176         (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) )
177    {
178        p_cb->is_pair_cancel = TRUE;
179        SMP_TRACE_DEBUG0("Cancel Pairing: set fail reason Unknown");
180        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &err_code);
181        status = TRUE;
182    }
183
184    return status;
185}
186/*******************************************************************************
187**
188** Function         SMP_SecurityGrant
189**
190** Description      This function is called to grant security process.
191**
192** Parameters       bd_addr - peer device bd address.
193**                  res     - result of the operation SMP_SUCCESS if success.
194**                            Otherwise, SMP_REPEATED_ATTEMPTS is too many attempts.
195**
196** Returns          None
197**
198*******************************************************************************/
199void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res)
200{
201    SMP_TRACE_EVENT0 ("SMP_SecurityGrant ");
202    if (smp_cb.state != SMP_ST_WAIT_APP_RSP ||
203        smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
204        memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
205        return;
206
207    smp_sm_event(&smp_cb, SMP_API_SEC_GRANT_EVT, &res);
208}
209
210/*******************************************************************************
211**
212** Function         SMP_PasskeyReply
213**
214** Description      This function is called after Security Manager submitted
215**                  passkey request to the application.
216**
217** Parameters:      bd_addr      - Address of the device for which passkey was requested
218**                  res          - result of the operation SMP_SUCCESS if success
219**                  passkey - numeric value in the range of
220**                  BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
221**
222*******************************************************************************/
223void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
224{
225    tSMP_CB *p_cb = & smp_cb;
226    UINT8   failure = SMP_PASSKEY_ENTRY_FAIL;
227    tBTM_SEC_DEV_REC *p_dev_rec;
228
229    SMP_TRACE_EVENT2 ("SMP_PasskeyReply: Key: %d  Result:%d",
230                      passkey, res);
231
232    /* If timeout already expired or has been canceled, ignore the reply */
233    if (p_cb->cb_evt != SMP_PASSKEY_REQ_EVT)
234    {
235        SMP_TRACE_WARNING1 ("SMP_PasskeyReply() - Wrong State: %d", p_cb->state);
236        return;
237    }
238
239    if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
240    {
241        SMP_TRACE_ERROR0 ("SMP_PasskeyReply() - Wrong BD Addr");
242        return;
243    }
244
245    if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
246    {
247        SMP_TRACE_ERROR0 ("SMP_PasskeyReply() - no dev CB");
248        return;
249    }
250
251
252    if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS)
253    {
254        SMP_TRACE_WARNING1 ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey);
255        /* send pairing failure */
256        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
257
258    }
259    else
260    {
261        smp_convert_string_to_tk(p_cb->tk, passkey);
262    }
263
264    return;
265}
266
267/*******************************************************************************
268**
269** Function         SMP_OobDataReply
270**
271** Description      This function is called to provide the OOB data for
272**                  SMP in response to SMP_OOB_REQ_EVT
273**
274** Parameters:      bd_addr     - Address of the peer device
275**                  res         - result of the operation SMP_SUCCESS if success
276**                  p_data      - simple pairing Randomizer  C.
277**
278*******************************************************************************/
279void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data)
280{
281    tSMP_CB *p_cb = & smp_cb;
282    UINT8   failure = SMP_OOB_FAIL;
283    tSMP_KEY        key;
284
285    SMP_TRACE_EVENT2 ("SMP_OobDataReply State: %d  res:%d",
286                      smp_cb.state, res);
287
288    /* If timeout already expired or has been canceled, ignore the reply */
289    if (p_cb->state != SMP_ST_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
290        return;
291
292    if (res != SMP_SUCCESS || len == 0 || !p_data)
293    {
294        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
295    }
296    else
297    {
298        if (len > BT_OCTET16_LEN)
299            len = BT_OCTET16_LEN;
300
301        memcpy(p_cb->tk, p_data, len);
302
303        key.key_type    = SMP_KEY_TYPE_TK;
304        key.p_data      = p_cb->tk;
305
306        smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &key);
307    }
308}
309
310/*******************************************************************************
311**
312** Function         SMP_Encrypt
313**
314** Description      This function is called to encrypt the data with the specified
315**                  key
316**
317** Parameters:      key                 - Pointer to key key[0] conatins the MSB
318**                  key_len             - key length
319**                  plain_text          - Pointer to data to be encrypted
320**                                        plain_text[0] conatins the MSB
321**                  pt_len              - plain text length
322**                  p_out                - output of the encrypted texts
323**
324**  Returns         Boolean - request is successful
325*******************************************************************************/
326BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len,
327                     UINT8 *plain_text, UINT8 pt_len,
328                     tSMP_ENC *p_out)
329
330{
331    BOOLEAN status=FALSE;
332    status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
333    return status;
334}
335#endif /* SMP_INCLUDED */
336
337
338