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