1 /**
2  ****************************************************************************************
3  *
4  * @file smpc_int.h
5  *
6  * @brief Header file - SMPC.
7  *
8  * Copyright (C) RivieraWaves 2009-2016
9  *
10  *
11  ****************************************************************************************
12  */
13 
14 #ifndef SMPC_INT_H_
15 #define SMPC_INT_H_
16 
17 /**
18  ****************************************************************************************
19  * @addtogroup SMP_INT Security Manager Protocol Internal
20  * @ingroup HOST
21  * @brief Security Manager Protocol Internals.
22  * @{
23  *
24  ****************************************************************************************
25  */
26 
27 
28 /*
29  * INCLUDE FILES
30  ****************************************************************************************
31  */
32 #include "rwip_config.h"
33 
34 #if (BLE_SMPC)
35 #include "smpc.h"
36 
37 #include "smp_common.h"
38 
39 #include <stdbool.h>
40 #include <stdint.h>
41 
42 #include "co_bt.h"
43 #include "gap.h"
44 
45 #include "smpc_api.h"
46 
47 /*
48  * DEFINES
49  ****************************************************************************************
50  */
51 
52 /// Minimum Encryption key size
53 #define SMPC_MIN_ENC_SIZE_LEN                   (7)
54 /// Maximum Encryption Key size
55 #define SMPC_MAX_ENC_SIZE_LEN                   (16)
56 
57 
58 /// Pairing Request and Pairing Response PDU Length
59 #define SMPC_CODE_PAIRING_REQ_RESP_LEN          (7)
60 
61 
62 /*
63  * ENUMERATIONS
64  ****************************************************************************************
65  */
66 
67 
68 ///Security Properties for distributed keys(all have the issued STK's properties)
69 enum
70 {
71     ///No security properties
72     SMP_KSEC_NONE = 0x00,
73     ///Unauthenticated no MITM
74     SMP_KSEC_UNAUTH_NO_MITM,
75     ///Authenticated with MITM
76     SMP_KSEC_AUTH_MITM,
77 };
78 
79 /// Repeated Attempts Attack Detection status
80 enum smpc_attempts_status
81 {
82     /// No attack has been detected
83     SMPC_REP_ATTEMPTS_NO_ERROR          = GAP_ERR_NO_ERROR,           // 0x00
84     /// An attack has already been detected, drop the message
85     SMPC_REP_ATTEMPTS_ATTACK,
86     /// An attack has been detected, an indication has been sent to the HL
87     SMPC_REP_ATTEMPS_ATTACK_DETECTED,
88     /// Repeated Attempt detected, need to send a Pairing Failed PDU to the peer device
89     SMPC_REP_ATTEMPT                    = SMP_ERROR_REPEATED_ATTEMPTS   // 0x09
90 };
91 
92 
93 /// STK generation methods
94 enum smpc_method
95 {
96     ///Just Works Method
97     SMPC_METH_JW            = 0x00,
98     ///PassKey Entry Method
99     SMPC_METH_PK,
100     ////OOB Method
101     SMPC_METH_OOB,
102     ////Numeric Comparison
103     SMPC_METH_NC
104 };
105 
106 /// Signature Command Types
107 enum
108 {
109     /// Generate Signature
110     SMPC_SIGN_GEN           = 0x00,
111     /// Verify Signature
112     SMPC_SIGN_VERIF
113 };
114 
115 enum
116 {
117     /// Use of STK in start encryption command
118     SMPC_USE_STK     = 0x00,
119     /// Use of LTK in start encryption command
120     SMPC_USE_LTK
121 };
122 
123 #if (SECURE_CONNECTIONS)
124 enum
125 {
126     SMP_AES_CMAC_KEY_GENERATION = 0x00,
127 
128     SMP_AES_CMAC_BLOCK
129 };
130 
131 /// Keypress Notification types
132 enum smpc_notification_type
133 {
134     /// Passkey entry started
135     SMP_PASSKEY_ENTRY_STARTED = 0x00,
136     /// Passkey digit entered
137     SMP_PASSKEY_DIGIT_ENTERED,
138     /// Passkey digit erased
139     SMP_PASSKEY_DIGIT_ERASED,
140     /// Passkey cleared
141     SMP_PASSKEY_CLEARED,
142     /// Passkey entry completed
143     SMP_PASSKEY_ENTRY_COMPLETED
144 };
145 #endif // (SECURE_CONNECTIONS)
146 /*
147  * STRUCTURES DEFINITION
148  ****************************************************************************************
149  */
150 
151 /*
152  * GLOBAL VARIABLES DEFINITION
153  ****************************************************************************************
154  */
155 
156 
157 /*
158  * MACROS
159  ****************************************************************************************
160  */
161 /// Authentication Request mask
162 #define SMPC_MASK_AUTH_REQ(req)    (req & 0x07)
163 
164 /*
165  * FUNCTION DECLARATIONS
166  ****************************************************************************************
167  */
168 
169 /**
170  ****************************************************************************************
171  * @brief Send a SMPM_USE_ENC_BLOCK_CMD message to the SMPM. Shall be use when the AES_128
172  *        encryption block need to be used.
173  *
174  * @param[in] conidx      Connection Index
175  * @param[in] operand_1   First operand
176  * @param[in] operand_2   Second operand
177  ****************************************************************************************
178  */
179 void smpc_send_use_enc_block_cmd(uint8_t conidx,
180                                  uint8_t *operand_1, uint8_t *operand_2);
181 
182 
183 /**
184  ****************************************************************************************
185  * @brief Send a SMPM_GEN_DH_KEY_CMD message to the SMPM. Shall be use when we need to
186  *        generate a DH KEy
187  *
188  * @param[in] conidx      Connection Index
189  * @param[in] operand_1   X co-ordinate
190  * @param[in] operand_2   Y co-ordinate
191  ****************************************************************************************
192  */
193 
194 void smpc_send_gen_dh_key_cmd(uint8_t conidx,
195                                 uint8_t *operand_1, uint8_t *operand_2);
196 
197 /**
198  ****************************************************************************************
199  * @brief Send a request to the controller to start the encryption procedure.
200  *
201  * @param[in] conidx      Connection Index
202  * @param[in] operand_1   First operand
203  * @param[in] operand_2   Second operand
204  ****************************************************************************************
205  */
206 void smpc_send_start_enc_cmd(uint8_t idx, uint8_t key_type, uint8_t *key,
207                              uint8_t *randnb, uint16_t ediv);
208 
209 /**
210  ****************************************************************************************
211  * @brief Send the LTK provided by the HL to the controller.
212  *
213  * @param[in] idx         Connection Index
214  * @param[in] found       Indicate if the requested LTK has been found by the application
215  * @param[in] key         Found LTK, used only if found is set to true
216  ****************************************************************************************
217  */
218 void smpc_send_ltk_req_rsp(uint8_t idx, bool found, uint8_t *key);
219 
220 /**
221  ****************************************************************************************
222  * @brief Send a SMPC_PAIRING_REQ_IND message to the HL
223  *
224  * @param[in] conidx      Connection Index
225  * @param[in] req_type    Kind of request
226  ****************************************************************************************
227  */
228 void smpc_send_pairing_req_ind(uint8_t conidx, uint8_t req_type);
229 
230 /**
231  ****************************************************************************************
232  * @brief Send a SMPC_PAIRING_IND message to the HL
233  *
234  * @param[in] conidx      Connection Index
235  * @param[in] ind_type    Kind of indication
236  * @param[in] value       Value to indicate (keys, ...)
237  ****************************************************************************************
238  */
239 void smpc_send_pairing_ind(uint8_t conidx, uint8_t ind_type, void *value);
240 
241 /**
242  ****************************************************************************************
243  * @brief Check if the provided pairing features are within the specified range.
244  *
245  * @param[in] pair_feat   Pairing Features values to check
246  *
247  * @param[out] true if features are valid, else false
248  ****************************************************************************************
249  */
250 bool smpc_check_pairing_feat(struct gapc_pairing *pair_feat);
251 
252 /**
253  ****************************************************************************************
254  * @brief Check if an attack by repeated attempts has been triggered by the peer device
255  *
256  * @param[in] conidx   Connection Index
257  ****************************************************************************************
258  */
259 uint8_t smpc_check_repeated_attempts(uint8_t conidx);
260 
261 /**
262  ****************************************************************************************
263  * @brief Compute and check the encryption key size to use during the connection.
264  *
265  * @param[in] conidx   Connection Index
266  *
267  * @param[out] true if the resultant EKS is within the specified range [7-16 bytes], else false
268  ****************************************************************************************
269  */
270 bool smpc_check_max_key_size(uint8_t conidx);
271 
272 /**
273  ****************************************************************************************
274  * @brief Check if the keys distribution scheme is compliant with the required security
275  *        level
276  *
277  * @param[in] conidx      Connection Index
278  * @param[in] sec_level   Security level required by the device.
279  ****************************************************************************************
280  */
281 bool smpc_check_key_distrib(uint8_t conidx, uint8_t sec_level);
282 
283 /**
284  ****************************************************************************************
285  * @brief Apply the XOR operator to the two provided operands
286  *
287  * @param[in|out] result      Buffer which will contain the result of the XOR operation
288  * @param[in]     operand_1   First operand
289  * @param[in]     operand_2   Second operand
290  ****************************************************************************************
291  */
292 void smpc_xor(uint8_t *result, uint8_t *operand_1, uint8_t *operand_2);
293 
294 /**
295  ****************************************************************************************
296  * @brief Generate the L value during a signature verification/generation procedure.
297  *
298  * @param[in] conidx   Connection Index
299  * @param[in] src      Indicate the source of the CSRK which will be used (LOCAL or PEER)
300  ****************************************************************************************
301  */
302 void smpc_generate_l(uint8_t conidx, uint8_t src);
303 
304 /**
305  ****************************************************************************************
306  * @brief Generate one of the Ci value during a signature verification/generation procedure.
307  *
308  * @param[in] conidx   Connection Index
309  * @param[in] src      Indicate the source of the CSRK which will be used (LOCAL or PEER)
310  * @param[in] ci1      Previous computed Ci value
311  * @param[in] mi       16-byte block used to generate the ci value
312  ****************************************************************************************
313  */
314 void smpc_generate_ci(uint8_t conidx, uint8_t src, uint8_t *ci1, uint8_t *mi);
315 
316 /**
317  ****************************************************************************************
318  * @brief Generate the random value exchanged during the pairing procedure (phase 2)
319  *
320  * @param[in] conidx   Connection Index
321  * @param[in] state    New state of the SMPC task.
322  ****************************************************************************************
323  */
324 void smpc_generate_rand(uint8_t conidx, uint8_t state);
325 
326 /**
327  ****************************************************************************************
328  * @brief Generate the first value needed in the confirm value generation
329  *
330  * @param[in] conidx   Connection Index
331  * @param[in] role     Current role of the device
332  * @param[in] local    true if the confirm value to generate is the confirm value of the
333  *                     device, false if it is the remote device's one.
334  ****************************************************************************************
335  */
336 void smpc_generate_e1(uint8_t conidx, uint8_t role, bool local);
337 
338 /**
339  ****************************************************************************************
340  * @brief Generate the confirm value
341  *
342  * @param[in] conidx   Connection Index
343  * @param[in] role     Current role of the device
344  * @param[in] e1       e1 value
345  ****************************************************************************************
346  */
347 void smpc_generate_cfm(uint8_t conidx, uint8_t role, uint8_t *e1);
348 
349 /**
350  ****************************************************************************************
351  * @brief Generate the STK used to encrypt a link after the pairing procedure
352  *
353  * @param[in] conidx   Connection Index
354  * @param[in] role     Current role of the device
355  ****************************************************************************************
356  */
357 void smpc_generate_stk(uint8_t conidx, uint8_t role);
358 
359 /**
360  ****************************************************************************************
361  * @brief Calculate one of the subkey used during the signature generation/verification
362  *        procedure.
363  *
364  * @param[in] gen_k2        true if the returned subkeys is k2, false if k1
365  * @param[in] l_value       L value obtained from the CSRK.
366  * @param[in|out] subkey    Buffer which will contain the generated subkey.
367  ****************************************************************************************
368  */
369 void smpc_calc_subkeys(bool gen_k2, uint8_t *l_value, uint8_t *subkey);
370 
371 /**
372  ****************************************************************************************
373  * @brief Start to send the keys defined during the pairing features exchange procedure.
374  *
375  * @param[in] conidx        Connection Index
376  * @param[in] role          Current role of the device
377  ****************************************************************************************
378  */
379 void smpc_tkdp_send_start(uint8_t conidx, uint8_t role);
380 
381 /**
382  ****************************************************************************************
383  * @brief Define the next step of TKDP procedure (sending side).
384  *
385  * @param[in] conidx        Connection Index
386  * @param[in] role          Current role of the device
387  ****************************************************************************************
388  */
389 void smpc_tkdp_send_continue(uint8_t conidx, uint8_t role);
390 
391 /**
392  ****************************************************************************************
393  * @brief Put the task in a state allowing to receive the keys defined during the pairing
394  *        features exchange procedure.
395  *
396  * @param[in] conidx        Connection Index
397  * @param[in] role          Current role of the device
398  ****************************************************************************************
399  */
400 void smpc_tkdp_rcp_start(uint8_t conidx, uint8_t role);
401 
402 /**
403  ****************************************************************************************
404  * @brief Define the next step of TKDP procedure (reception side).
405  *
406  * @param[in] conidx        Connection Index
407  * @param[in] role          Current role of the device
408  ****************************************************************************************
409  */
410 void smpc_tkdp_rcp_continue(uint8_t conidx, uint8_t role);
411 
412 
413 /**
414  ****************************************************************************************
415  * @brief Start the timer used to detect a Repeated Attempts attack
416  *
417  * @param[in] conidx        Connection Index
418  ****************************************************************************************
419  */
420 void smpc_launch_rep_att_timer(uint8_t conidx);
421 
422 /**
423  ****************************************************************************************
424  * @brief Determine the method which will be used to generate the STK during a pairing
425  *        procedure
426  *
427  * @param[in] conidx        Connection Index
428  ****************************************************************************************
429  */
430 void smpc_get_key_sec_prop(uint8_t conidx);
431 
432 /**
433  ****************************************************************************************
434  * @brief Check if the security mode requested by the application or the peer device can
435  *        be reached with the exchanged pairing features.
436  *
437  * @param[in] conidx        Connection Index
438  * @param[in] role          Current role of the device
439  ****************************************************************************************
440  */
441 bool smpc_is_sec_mode_reached(uint8_t conidx, uint8_t role);
442 
443 /**
444  ****************************************************************************************
445  * @brief Define what to do once a start encryption procedure has been successfully finished.
446  *
447  * @param[in] conidx        Connection Index
448  * @param[in] role          Current role of the device
449  * @param[in] status        Status
450  ****************************************************************************************
451  */
452 void smpc_handle_enc_change_evt(uint8_t conidx, uint8_t role, uint8_t status);
453 
454 
455 #if (SECURE_CONNECTIONS)
456 /**
457  ****************************************************************************************
458  * @brief Initiate DHKey Check algorithm
459  *
460  * @param[in] conidx        Connection Index
461  ****************************************************************************************
462  */
463 void smpc_initiate_dhkey_check(uint8_t conidx);
464 
465 /**
466  ****************************************************************************************
467  * @brief Initiates the f5 algorithm to calculate the MacKey and LTK for a link
468  *
469  * @param[in] conidx        Connection Index
470  *
471  ****************************************************************************************
472  */
473 
474 void smpc_init_mac_key_calculation(uint8_t conidx);
475 
476 /**
477  ****************************************************************************************
478  * @brief Initiates the f6 algorithm to verify a DH Key Check.
479  *
480  * @param[in] conidx        Connection Index
481  *
482  ****************************************************************************************
483  */
484 
485 void smpc_initiate_dhkey_verification(uint8_t conidx);
486 
487 /**
488  ****************************************************************************************
489  * @brief Determines the next bit of the passkey to be used
490  *
491  * @param[in] conidx        Connection Index
492  *
493  ****************************************************************************************
494  */
495 uint8_t smpc_get_next_passkey_bit(uint8_t conidx);
496 
497 /**
498  ****************************************************************************************
499  * @brief Checks if secure connections are enabled on a link
500  *
501  * @param[in] conidx        Connection Index
502  *
503  ****************************************************************************************
504  */
505 bool smpc_secure_connections_enabled(uint8_t idx);
506 
507 #endif // (SECURE_CONNECTIONS)
508 #endif //(BLE_SMPC)
509 #endif //SMPC_INT_H_
510 
511 /// @} SMPC
512