2011-06-10 01:50:40 +04:00
/*
BlueZ - Bluetooth protocol stack for Linux
Copyright ( C ) 2011 Nokia Corporation and / or its subsidiary ( - ies ) .
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation ;
THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS
OR IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS .
IN NO EVENT SHALL THE COPYRIGHT HOLDER ( S ) AND AUTHOR ( S ) BE LIABLE FOR ANY
CLAIM , OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES , OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER IN AN
ACTION OF CONTRACT , NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
ALL LIABILITY , INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS ,
COPYRIGHTS , TRADEMARKS OR OTHER RIGHTS , RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED .
*/
2015-01-01 01:43:16 +03:00
# include <linux/debugfs.h>
2012-05-23 11:04:22 +04:00
# include <linux/scatterlist.h>
# include <crypto/b128ops.h>
2016-01-24 16:18:30 +03:00
# include <crypto/hash.h>
# include <crypto/skcipher.h>
2012-05-23 11:04:22 +04:00
2011-06-10 01:50:40 +04:00
# include <net/bluetooth/bluetooth.h>
# include <net/bluetooth/hci_core.h>
# include <net/bluetooth/l2cap.h>
2011-12-22 04:12:12 +04:00
# include <net/bluetooth/mgmt.h>
2013-10-11 01:54:16 +04:00
2014-06-06 11:50:15 +04:00
# include "ecc.h"
2013-10-11 01:54:16 +04:00
# include "smp.h"
2011-06-10 01:50:44 +04:00
2015-06-11 13:52:26 +03:00
# define SMP_DEV(hdev) \
( ( struct smp_dev * ) ( ( struct l2cap_chan * ) ( ( hdev ) - > smp_data ) ) - > data )
2014-12-01 23:03:16 +03:00
/* Low-level debug macros to be used for stuff that we don't want
* accidentially in dmesg , i . e . the values of the various crypto keys
* and the inputs & outputs of crypto functions .
*/
# ifdef DEBUG
# define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \
# #__VA_ARGS__)
# else
# define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \
# #__VA_ARGS__)
# endif
2014-09-05 23:19:55 +04:00
# define SMP_ALLOW_CMD(smp, code) set_bit(code, &smp->allow_cmd)
2014-06-06 11:50:15 +04:00
/* Keys which are not distributed with Secure Connections */
# define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY);
2012-03-02 02:32:37 +04:00
# define SMP_TIMEOUT msecs_to_jiffies(30000)
2011-06-14 20:37:41 +04:00
2015-03-13 12:11:00 +03:00
# define AUTH_REQ_MASK(dev) (hci_dev_test_flag(dev, HCI_SC_ENABLED) ? \
2014-05-26 14:29:28 +04:00
0x1f : 0x07 )
# define KEY_DIST_MASK 0x07
2012-10-11 18:26:06 +04:00
2014-06-06 12:30:08 +04:00
/* Maximum message length that can be passed to aes_cmac */
# define CMAC_MSG_MAX 80
2014-06-16 20:25:18 +04:00
enum {
SMP_FLAG_TK_VALID ,
SMP_FLAG_CFM_PENDING ,
SMP_FLAG_MITM_AUTH ,
SMP_FLAG_COMPLETE ,
SMP_FLAG_INITIATOR ,
2014-05-16 12:03:34 +04:00
SMP_FLAG_SC ,
2014-06-06 12:09:28 +04:00
SMP_FLAG_REMOTE_PK ,
2014-05-31 19:52:28 +04:00
SMP_FLAG_DEBUG_KEY ,
2014-06-25 12:10:28 +04:00
SMP_FLAG_WAIT_USER ,
2014-06-04 12:07:40 +04:00
SMP_FLAG_DHKEY_PENDING ,
2015-03-16 12:45:44 +03:00
SMP_FLAG_REMOTE_OOB ,
SMP_FLAG_LOCAL_OOB ,
2014-06-16 20:25:18 +04:00
} ;
2014-05-20 10:45:47 +04:00
2015-03-16 11:10:19 +03:00
struct smp_dev {
2015-03-16 11:10:22 +03:00
/* Secure Connections OOB data */
u8 local_pk [ 64 ] ;
u8 local_sk [ 32 ] ;
2015-03-16 22:34:57 +03:00
u8 local_rand [ 16 ] ;
2015-03-16 11:10:22 +03:00
bool debug_key ;
2015-06-11 13:52:27 +03:00
u8 min_key_size ;
2015-06-11 13:52:26 +03:00
u8 max_key_size ;
2016-01-24 16:18:30 +03:00
struct crypto_skcipher * tfm_aes ;
struct crypto_shash * tfm_cmac ;
2015-03-16 11:10:19 +03:00
} ;
2014-05-20 10:45:47 +04:00
struct smp_chan {
2014-08-11 23:06:40 +04:00
struct l2cap_conn * conn ;
struct delayed_work security_timer ;
2014-09-05 23:19:55 +04:00
unsigned long allow_cmd ; /* Bitmask of allowed commands */
2014-08-11 23:06:40 +04:00
2014-05-20 10:45:47 +04:00
u8 preq [ 7 ] ; /* SMP Pairing Request */
u8 prsp [ 7 ] ; /* SMP Pairing Response */
u8 prnd [ 16 ] ; /* SMP Pairing Random (local) */
u8 rrnd [ 16 ] ; /* SMP Pairing Random (remote) */
u8 pcnf [ 16 ] ; /* SMP Pairing Confirm */
u8 tk [ 16 ] ; /* SMP Temporary Key */
2015-03-16 12:45:43 +03:00
u8 rr [ 16 ] ; /* Remote OOB ra/rb value */
u8 lr [ 16 ] ; /* Local OOB ra/rb value */
2014-05-20 10:45:47 +04:00
u8 enc_key_size ;
u8 remote_key_dist ;
bdaddr_t id_addr ;
u8 id_addr_type ;
u8 irk [ 16 ] ;
struct smp_csrk * csrk ;
struct smp_csrk * slave_csrk ;
struct smp_ltk * ltk ;
struct smp_ltk * slave_ltk ;
struct smp_irk * remote_irk ;
2014-06-06 12:54:04 +04:00
u8 * link_key ;
2014-05-20 10:45:50 +04:00
unsigned long flags ;
2014-05-31 19:48:26 +04:00
u8 method ;
2014-06-25 12:10:28 +04:00
u8 passkey_round ;
2014-06-27 15:23:03 +04:00
2014-06-06 11:50:15 +04:00
/* Secure Connections variables */
u8 local_pk [ 64 ] ;
u8 local_sk [ 32 ] ;
2014-06-06 12:09:28 +04:00
u8 remote_pk [ 64 ] ;
u8 dhkey [ 32 ] ;
2014-06-06 12:44:05 +04:00
u8 mackey [ 16 ] ;
2014-06-06 11:50:15 +04:00
2016-01-24 16:18:30 +03:00
struct crypto_skcipher * tfm_aes ;
struct crypto_shash * tfm_cmac ;
2014-05-20 10:45:47 +04:00
} ;
2014-05-31 19:52:28 +04:00
/* These debug key values are defined in the SMP section of the core
* specification . debug_pk is the public debug key and debug_sk the
* private debug key .
*/
static const u8 debug_pk [ 64 ] = {
0xe6 , 0x9d , 0x35 , 0x0e , 0x48 , 0x01 , 0x03 , 0xcc ,
0xdb , 0xfd , 0xf4 , 0xac , 0x11 , 0x91 , 0xf4 , 0xef ,
0xb9 , 0xa5 , 0xf9 , 0xe9 , 0xa7 , 0x83 , 0x2c , 0x5e ,
0x2c , 0xbe , 0x97 , 0xf2 , 0xd2 , 0x03 , 0xb0 , 0x20 ,
0x8b , 0xd2 , 0x89 , 0x15 , 0xd0 , 0x8e , 0x1c , 0x74 ,
0x24 , 0x30 , 0xed , 0x8f , 0xc2 , 0x45 , 0x63 , 0x76 ,
0x5c , 0x15 , 0x52 , 0x5a , 0xbf , 0x9a , 0x32 , 0x63 ,
0x6d , 0xeb , 0x2a , 0x65 , 0x49 , 0x9c , 0x80 , 0xdc ,
} ;
static const u8 debug_sk [ 32 ] = {
0xbd , 0x1a , 0x3c , 0xcd , 0xa6 , 0xb8 , 0x99 , 0x58 ,
0x99 , 0xb7 , 0x40 , 0xeb , 0x7b , 0x60 , 0xff , 0x4a ,
0x50 , 0x3f , 0x10 , 0xd2 , 0xe3 , 0xb3 , 0xc9 , 0x74 ,
0x38 , 0x5f , 0xc5 , 0xa3 , 0xd4 , 0xf6 , 0x49 , 0x3f ,
} ;
2014-06-16 20:25:19 +04:00
static inline void swap_buf ( const u8 * src , u8 * dst , size_t len )
2011-06-10 01:50:44 +04:00
{
2014-06-16 20:25:19 +04:00
size_t i ;
2011-06-10 01:50:44 +04:00
2014-06-16 20:25:19 +04:00
for ( i = 0 ; i < len ; i + + )
dst [ len - 1 - i ] = src [ i ] ;
2011-06-10 01:50:44 +04:00
}
2014-12-02 14:39:23 +03:00
/* The following functions map to the LE SC SMP crypto functions
* AES - CMAC , f4 , f5 , f6 , g2 and h6 .
*/
2016-01-24 16:18:30 +03:00
static int aes_cmac ( struct crypto_shash * tfm , const u8 k [ 16 ] , const u8 * m ,
2014-06-06 12:30:08 +04:00
size_t len , u8 mac [ 16 ] )
{
uint8_t tmp [ 16 ] , mac_msb [ 16 ] , msg_msb [ CMAC_MSG_MAX ] ;
2016-01-24 16:18:30 +03:00
SHASH_DESC_ON_STACK ( desc , tfm ) ;
2014-06-06 12:30:08 +04:00
int err ;
if ( len > CMAC_MSG_MAX )
return - EFBIG ;
if ( ! tfm ) {
BT_ERR ( " tfm %p " , tfm ) ;
return - EINVAL ;
}
2016-01-24 16:18:30 +03:00
desc - > tfm = tfm ;
desc - > flags = 0 ;
2014-06-06 12:30:08 +04:00
/* Swap key and message from LSB to MSB */
swap_buf ( k , tmp , 16 ) ;
swap_buf ( m , msg_msb , len ) ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " msg (len %zu) %*phN " , len , ( int ) len , m ) ;
SMP_DBG ( " key %16phN " , k ) ;
2014-06-06 12:30:08 +04:00
2016-01-24 16:18:30 +03:00
err = crypto_shash_setkey ( tfm , tmp , 16 ) ;
2014-06-06 12:30:08 +04:00
if ( err ) {
BT_ERR ( " cipher setkey failed: %d " , err ) ;
return err ;
}
2016-01-24 16:18:30 +03:00
err = crypto_shash_digest ( desc , msg_msb , len , mac_msb ) ;
shash_desc_zero ( desc ) ;
2014-06-06 12:30:08 +04:00
if ( err ) {
2016-01-24 16:18:30 +03:00
BT_ERR ( " Hash computation error %d " , err ) ;
2014-06-06 12:30:08 +04:00
return err ;
}
swap_buf ( mac_msb , mac , 16 ) ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " mac %16phN " , mac ) ;
2014-06-06 12:30:08 +04:00
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int smp_f4 ( struct crypto_shash * tfm_cmac , const u8 u [ 32 ] ,
const u8 v [ 32 ] , const u8 x [ 16 ] , u8 z , u8 res [ 16 ] )
2014-06-06 12:30:08 +04:00
{
u8 m [ 65 ] ;
int err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " u %32phN " , u ) ;
SMP_DBG ( " v %32phN " , v ) ;
SMP_DBG ( " x %16phN z %02x " , x , z ) ;
2014-06-06 12:30:08 +04:00
m [ 0 ] = z ;
memcpy ( m + 1 , v , 32 ) ;
memcpy ( m + 33 , u , 32 ) ;
err = aes_cmac ( tfm_cmac , x , m , sizeof ( m ) , res ) ;
if ( err )
return err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " res %16phN " , res ) ;
2014-06-06 12:30:08 +04:00
return err ;
}
2016-01-24 16:18:30 +03:00
static int smp_f5 ( struct crypto_shash * tfm_cmac , const u8 w [ 32 ] ,
2014-12-29 13:04:10 +03:00
const u8 n1 [ 16 ] , const u8 n2 [ 16 ] , const u8 a1 [ 7 ] ,
const u8 a2 [ 7 ] , u8 mackey [ 16 ] , u8 ltk [ 16 ] )
2014-06-06 12:44:05 +04:00
{
/* The btle, salt and length "magic" values are as defined in
* the SMP section of the Bluetooth core specification . In ASCII
* the btle value ends up being ' btle ' . The salt is just a
* random number whereas length is the value 256 in little
* endian format .
*/
const u8 btle [ 4 ] = { 0x65 , 0x6c , 0x74 , 0x62 } ;
const u8 salt [ 16 ] = { 0xbe , 0x83 , 0x60 , 0x5a , 0xdb , 0x0b , 0x37 , 0x60 ,
0x38 , 0xa5 , 0xf5 , 0xaa , 0x91 , 0x83 , 0x88 , 0x6c } ;
const u8 length [ 2 ] = { 0x00 , 0x01 } ;
u8 m [ 53 ] , t [ 16 ] ;
int err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " w %32phN " , w ) ;
SMP_DBG ( " n1 %16phN n2 %16phN " , n1 , n2 ) ;
SMP_DBG ( " a1 %7phN a2 %7phN " , a1 , a2 ) ;
2014-06-06 12:44:05 +04:00
err = aes_cmac ( tfm_cmac , salt , w , 32 , t ) ;
if ( err )
return err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " t %16phN " , t ) ;
2014-06-06 12:44:05 +04:00
memcpy ( m , length , 2 ) ;
memcpy ( m + 2 , a2 , 7 ) ;
memcpy ( m + 9 , a1 , 7 ) ;
memcpy ( m + 16 , n2 , 16 ) ;
memcpy ( m + 32 , n1 , 16 ) ;
memcpy ( m + 48 , btle , 4 ) ;
m [ 52 ] = 0 ; /* Counter */
err = aes_cmac ( tfm_cmac , t , m , sizeof ( m ) , mackey ) ;
if ( err )
return err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " mackey %16phN " , mackey ) ;
2014-06-06 12:44:05 +04:00
m [ 52 ] = 1 ; /* Counter */
err = aes_cmac ( tfm_cmac , t , m , sizeof ( m ) , ltk ) ;
if ( err )
return err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " ltk %16phN " , ltk ) ;
2014-06-06 12:44:05 +04:00
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int smp_f6 ( struct crypto_shash * tfm_cmac , const u8 w [ 16 ] ,
2014-12-29 13:04:10 +03:00
const u8 n1 [ 16 ] , const u8 n2 [ 16 ] , const u8 r [ 16 ] ,
2014-06-06 12:44:05 +04:00
const u8 io_cap [ 3 ] , const u8 a1 [ 7 ] , const u8 a2 [ 7 ] ,
u8 res [ 16 ] )
{
u8 m [ 65 ] ;
int err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " w %16phN " , w ) ;
SMP_DBG ( " n1 %16phN n2 %16phN " , n1 , n2 ) ;
SMP_DBG ( " r %16phN io_cap %3phN a1 %7phN a2 %7phN " , r , io_cap , a1 , a2 ) ;
2014-06-06 12:44:05 +04:00
memcpy ( m , a2 , 7 ) ;
memcpy ( m + 7 , a1 , 7 ) ;
memcpy ( m + 14 , io_cap , 3 ) ;
memcpy ( m + 17 , r , 16 ) ;
memcpy ( m + 33 , n2 , 16 ) ;
memcpy ( m + 49 , n1 , 16 ) ;
err = aes_cmac ( tfm_cmac , w , m , sizeof ( m ) , res ) ;
if ( err )
return err ;
2015-01-01 07:01:22 +03:00
SMP_DBG ( " res %16phN " , res ) ;
2014-06-06 12:44:05 +04:00
return err ;
}
2016-01-24 16:18:30 +03:00
static int smp_g2 ( struct crypto_shash * tfm_cmac , const u8 u [ 32 ] , const u8 v [ 32 ] ,
2014-06-06 12:39:49 +04:00
const u8 x [ 16 ] , const u8 y [ 16 ] , u32 * val )
{
u8 m [ 80 ] , tmp [ 16 ] ;
int err ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " u %32phN " , u ) ;
SMP_DBG ( " v %32phN " , v ) ;
SMP_DBG ( " x %16phN y %16phN " , x , y ) ;
2014-06-06 12:39:49 +04:00
memcpy ( m , y , 16 ) ;
memcpy ( m + 16 , v , 32 ) ;
memcpy ( m + 48 , u , 32 ) ;
err = aes_cmac ( tfm_cmac , x , m , sizeof ( m ) , tmp ) ;
if ( err )
return err ;
* val = get_unaligned_le32 ( tmp ) ;
* val % = 1000000 ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " val %06u " , * val ) ;
2014-06-06 12:39:49 +04:00
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int smp_h6 ( struct crypto_shash * tfm_cmac , const u8 w [ 16 ] ,
2014-12-02 14:39:23 +03:00
const u8 key_id [ 4 ] , u8 res [ 16 ] )
{
int err ;
SMP_DBG ( " w %16phN key_id %4phN " , w , key_id ) ;
err = aes_cmac ( tfm_cmac , w , key_id , 4 , res ) ;
if ( err )
return err ;
SMP_DBG ( " res %16phN " , res ) ;
return err ;
}
/* The following functions map to the legacy SMP crypto functions e, c1,
* s1 and ah .
*/
2016-01-24 16:18:30 +03:00
static int smp_e ( struct crypto_skcipher * tfm , const u8 * k , u8 * r )
2011-06-10 01:50:44 +04:00
{
2016-01-24 16:18:30 +03:00
SKCIPHER_REQUEST_ON_STACK ( req , tfm ) ;
2011-06-10 01:50:44 +04:00
struct scatterlist sg ;
2014-03-18 14:58:24 +04:00
uint8_t tmp [ 16 ] , data [ 16 ] ;
2013-12-02 12:49:04 +04:00
int err ;
2011-06-10 01:50:44 +04:00
2015-05-19 21:06:04 +03:00
SMP_DBG ( " k %16phN r %16phN " , k , r ) ;
2014-12-03 17:07:13 +03:00
if ( ! tfm ) {
2011-06-10 01:50:44 +04:00
BT_ERR ( " tfm %p " , tfm ) ;
return - EINVAL ;
}
2014-03-18 14:58:24 +04:00
/* The most significant octet of key corresponds to k[0] */
2014-06-16 20:25:19 +04:00
swap_buf ( k , tmp , 16 ) ;
2014-03-18 14:58:24 +04:00
2016-01-24 16:18:30 +03:00
err = crypto_skcipher_setkey ( tfm , tmp , 16 ) ;
2011-06-10 01:50:44 +04:00
if ( err ) {
BT_ERR ( " cipher setkey failed: %d " , err ) ;
return err ;
}
2014-03-18 14:58:24 +04:00
/* Most significant octet of plaintextData corresponds to data[0] */
2014-06-16 20:25:19 +04:00
swap_buf ( r , data , 16 ) ;
2014-03-18 14:58:24 +04:00
sg_init_one ( & sg , data , 16 ) ;
2011-06-10 01:50:44 +04:00
2016-01-24 16:18:30 +03:00
skcipher_request_set_tfm ( req , tfm ) ;
skcipher_request_set_callback ( req , 0 , NULL , NULL ) ;
skcipher_request_set_crypt ( req , & sg , & sg , 16 , NULL ) ;
err = crypto_skcipher_encrypt ( req ) ;
skcipher_request_zero ( req ) ;
2011-06-10 01:50:44 +04:00
if ( err )
BT_ERR ( " Encrypt data error %d " , err ) ;
2014-03-18 14:58:24 +04:00
/* Most significant octet of encryptedData corresponds to data[0] */
2014-06-16 20:25:19 +04:00
swap_buf ( data , r , 16 ) ;
2014-03-18 14:58:24 +04:00
2015-05-19 21:06:04 +03:00
SMP_DBG ( " r %16phN " , r ) ;
2011-06-10 01:50:44 +04:00
return err ;
}
2016-01-24 16:18:30 +03:00
static int smp_c1 ( struct crypto_skcipher * tfm_aes , const u8 k [ 16 ] ,
2014-12-02 14:39:23 +03:00
const u8 r [ 16 ] , const u8 preq [ 7 ] , const u8 pres [ 7 ] , u8 _iat ,
const bdaddr_t * ia , u8 _rat , const bdaddr_t * ra , u8 res [ 16 ] )
2014-06-06 12:54:04 +04:00
{
2014-12-02 14:39:23 +03:00
u8 p1 [ 16 ] , p2 [ 16 ] ;
2014-06-06 12:54:04 +04:00
int err ;
2015-05-19 21:06:04 +03:00
SMP_DBG ( " k %16phN r %16phN " , k , r ) ;
SMP_DBG ( " iat %u ia %6phN rat %u ra %6phN " , _iat , ia , _rat , ra ) ;
SMP_DBG ( " preq %7phN pres %7phN " , preq , pres ) ;
2014-12-02 14:39:23 +03:00
memset ( p1 , 0 , 16 ) ;
2014-06-06 12:54:04 +04:00
2014-12-02 14:39:23 +03:00
/* p1 = pres || preq || _rat || _iat */
p1 [ 0 ] = _iat ;
p1 [ 1 ] = _rat ;
memcpy ( p1 + 2 , preq , 7 ) ;
memcpy ( p1 + 9 , pres , 7 ) ;
2015-05-19 21:06:04 +03:00
SMP_DBG ( " p1 %16phN " , p1 ) ;
2014-12-02 14:39:23 +03:00
/* res = r XOR p1 */
u128_xor ( ( u128 * ) res , ( u128 * ) r , ( u128 * ) p1 ) ;
/* res = e(k, res) */
err = smp_e ( tfm_aes , k , res ) ;
if ( err ) {
BT_ERR ( " Encrypt data error " ) ;
2014-06-06 12:54:04 +04:00
return err ;
2014-12-02 14:39:23 +03:00
}
2014-06-06 12:54:04 +04:00
2015-05-19 21:06:04 +03:00
/* p2 = padding || ia || ra */
memcpy ( p2 , ra , 6 ) ;
memcpy ( p2 + 6 , ia , 6 ) ;
memset ( p2 + 12 , 0 , 4 ) ;
SMP_DBG ( " p2 %16phN " , p2 ) ;
2014-12-02 14:39:23 +03:00
/* res = res XOR p2 */
u128_xor ( ( u128 * ) res , ( u128 * ) res , ( u128 * ) p2 ) ;
/* res = e(k, res) */
err = smp_e ( tfm_aes , k , res ) ;
if ( err )
BT_ERR ( " Encrypt data error " ) ;
return err ;
}
2016-01-24 16:18:30 +03:00
static int smp_s1 ( struct crypto_skcipher * tfm_aes , const u8 k [ 16 ] ,
2014-12-02 14:39:23 +03:00
const u8 r1 [ 16 ] , const u8 r2 [ 16 ] , u8 _r [ 16 ] )
{
int err ;
/* Just least significant octets from r1 and r2 are considered */
memcpy ( _r , r2 , 8 ) ;
memcpy ( _r + 8 , r1 , 8 ) ;
err = smp_e ( tfm_aes , k , _r ) ;
if ( err )
BT_ERR ( " Encrypt data error " ) ;
2014-06-06 12:54:04 +04:00
return err ;
}
2016-01-24 16:18:30 +03:00
static int smp_ah ( struct crypto_skcipher * tfm , const u8 irk [ 16 ] ,
2014-12-02 14:37:41 +03:00
const u8 r [ 3 ] , u8 res [ 3 ] )
2014-02-18 12:19:31 +04:00
{
2014-03-18 14:58:24 +04:00
u8 _res [ 16 ] ;
2014-02-18 12:19:31 +04:00
int err ;
/* r' = padding || r */
2014-03-18 14:58:24 +04:00
memcpy ( _res , r , 3 ) ;
memset ( _res + 3 , 0 , 13 ) ;
2014-02-18 12:19:31 +04:00
2014-03-18 14:58:24 +04:00
err = smp_e ( tfm , irk , _res ) ;
2014-02-18 12:19:31 +04:00
if ( err ) {
BT_ERR ( " Encrypt error " ) ;
return err ;
}
/* The output of the random address function ah is:
2015-09-04 18:08:18 +03:00
* ah ( k , r ) = e ( k , r ' ) mod 2 ^ 24
2014-02-18 12:19:31 +04:00
* The output of the security function e is then truncated to 24 bits
* by taking the least significant 24 bits of the output of e as the
* result of ah .
*/
2014-03-18 14:58:24 +04:00
memcpy ( res , _res , 3 ) ;
2014-02-18 12:19:31 +04:00
return 0 ;
}
2014-12-02 14:37:41 +03:00
bool smp_irk_matches ( struct hci_dev * hdev , const u8 irk [ 16 ] ,
const bdaddr_t * bdaddr )
2014-02-18 12:19:31 +04:00
{
2014-08-08 10:37:17 +04:00
struct l2cap_chan * chan = hdev - > smp_data ;
2015-03-16 11:10:19 +03:00
struct smp_dev * smp ;
2014-02-18 12:19:31 +04:00
u8 hash [ 3 ] ;
int err ;
2014-08-08 10:37:17 +04:00
if ( ! chan | | ! chan - > data )
return false ;
2015-03-16 11:10:19 +03:00
smp = chan - > data ;
2014-08-08 10:37:17 +04:00
2014-02-18 12:19:31 +04:00
BT_DBG ( " RPA %pMR IRK %*phN " , bdaddr , 16 , irk ) ;
2015-03-16 11:10:19 +03:00
err = smp_ah ( smp - > tfm_aes , irk , & bdaddr - > b [ 3 ] , hash ) ;
2014-02-18 12:19:31 +04:00
if ( err )
return false ;
return ! memcmp ( bdaddr - > b , hash , 3 ) ;
}
2014-12-02 14:37:41 +03:00
int smp_generate_rpa ( struct hci_dev * hdev , const u8 irk [ 16 ] , bdaddr_t * rpa )
2014-02-23 21:42:19 +04:00
{
2014-08-08 10:37:17 +04:00
struct l2cap_chan * chan = hdev - > smp_data ;
2015-03-16 11:10:19 +03:00
struct smp_dev * smp ;
2014-02-23 21:42:19 +04:00
int err ;
2014-08-08 10:37:17 +04:00
if ( ! chan | | ! chan - > data )
return - EOPNOTSUPP ;
2015-03-16 11:10:19 +03:00
smp = chan - > data ;
2014-08-08 10:37:17 +04:00
2014-02-23 21:42:19 +04:00
get_random_bytes ( & rpa - > b [ 3 ] , 3 ) ;
rpa - > b [ 5 ] & = 0x3f ; /* Clear two most significant bits */
rpa - > b [ 5 ] | = 0x40 ; /* Set second most significant bit */
2015-03-16 11:10:19 +03:00
err = smp_ah ( smp - > tfm_aes , irk , & rpa - > b [ 3 ] , rpa - > b ) ;
2014-02-23 21:42:19 +04:00
if ( err < 0 )
return err ;
BT_DBG ( " RPA %pMR " , rpa ) ;
return 0 ;
}
2015-03-16 11:10:22 +03:00
int smp_generate_oob ( struct hci_dev * hdev , u8 hash [ 16 ] , u8 rand [ 16 ] )
{
struct l2cap_chan * chan = hdev - > smp_data ;
struct smp_dev * smp ;
int err ;
if ( ! chan | | ! chan - > data )
return - EOPNOTSUPP ;
smp = chan - > data ;
if ( hci_dev_test_flag ( hdev , HCI_USE_DEBUG_KEYS ) ) {
BT_DBG ( " Using debug keys " ) ;
memcpy ( smp - > local_pk , debug_pk , 64 ) ;
memcpy ( smp - > local_sk , debug_sk , 32 ) ;
smp - > debug_key = true ;
} else {
while ( true ) {
/* Generate local key pair for Secure Connections */
if ( ! ecc_make_key ( smp - > local_pk , smp - > local_sk ) )
return - EIO ;
/* This is unlikely, but we need to check that
* we didn ' t accidentially generate a debug key .
*/
if ( memcmp ( smp - > local_sk , debug_sk , 32 ) )
break ;
}
smp - > debug_key = false ;
}
SMP_DBG ( " OOB Public Key X: %32phN " , smp - > local_pk ) ;
SMP_DBG ( " OOB Public Key Y: %32phN " , smp - > local_pk + 32 ) ;
SMP_DBG ( " OOB Private Key: %32phN " , smp - > local_sk ) ;
2015-03-16 22:34:57 +03:00
get_random_bytes ( smp - > local_rand , 16 ) ;
2015-03-16 11:10:22 +03:00
err = smp_f4 ( smp - > tfm_cmac , smp - > local_pk , smp - > local_pk ,
2015-03-16 22:34:57 +03:00
smp - > local_rand , 0 , hash ) ;
2015-03-16 11:10:22 +03:00
if ( err < 0 )
return err ;
2015-03-16 22:34:57 +03:00
memcpy ( rand , smp - > local_rand , 16 ) ;
2015-03-16 11:10:22 +03:00
return 0 ;
}
2014-08-08 10:37:18 +04:00
static void smp_send_cmd ( struct l2cap_conn * conn , u8 code , u16 len , void * data )
2011-06-10 01:50:40 +04:00
{
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
2014-08-11 23:06:40 +04:00
struct smp_chan * smp ;
2014-08-08 10:37:18 +04:00
struct kvec iv [ 2 ] ;
struct msghdr msg ;
2011-06-10 01:50:40 +04:00
2014-08-08 10:37:18 +04:00
if ( ! chan )
return ;
2011-06-10 01:50:40 +04:00
2014-08-08 10:37:18 +04:00
BT_DBG ( " code 0x%2.2x " , code ) ;
2011-06-10 01:50:40 +04:00
2014-08-08 10:37:18 +04:00
iv [ 0 ] . iov_base = & code ;
iv [ 0 ] . iov_len = 1 ;
2011-06-10 01:50:40 +04:00
2014-08-08 10:37:18 +04:00
iv [ 1 ] . iov_base = data ;
iv [ 1 ] . iov_len = len ;
2011-06-10 01:50:40 +04:00
2014-08-08 10:37:18 +04:00
memset ( & msg , 0 , sizeof ( msg ) ) ;
2011-06-10 01:50:40 +04:00
2014-11-25 01:07:38 +03:00
iov_iter_kvec ( & msg . msg_iter , WRITE | ITER_KVEC , iv , 2 , 1 + len ) ;
2011-06-10 01:50:40 +04:00
2014-08-08 10:37:18 +04:00
l2cap_chan_send ( chan , & msg , 1 + len ) ;
2011-08-20 04:06:50 +04:00
2014-08-11 23:06:40 +04:00
if ( ! chan - > data )
return ;
smp = chan - > data ;
cancel_delayed_work_sync ( & smp - > security_timer ) ;
2014-09-05 23:19:48 +04:00
schedule_delayed_work ( & smp - > security_timer , SMP_TIMEOUT ) ;
2011-06-10 01:50:40 +04:00
}
2014-05-16 11:59:06 +04:00
static u8 authreq_to_seclevel ( u8 authreq )
2011-12-22 04:12:12 +04:00
{
2014-05-16 11:59:06 +04:00
if ( authreq & SMP_AUTH_MITM ) {
if ( authreq & SMP_AUTH_SC )
return BT_SECURITY_FIPS ;
else
return BT_SECURITY_HIGH ;
} else {
2011-12-22 04:12:12 +04:00
return BT_SECURITY_MEDIUM ;
2014-05-16 11:59:06 +04:00
}
2011-12-22 04:12:12 +04:00
}
static __u8 seclevel_to_authreq ( __u8 sec_level )
{
switch ( sec_level ) {
2014-05-16 11:59:06 +04:00
case BT_SECURITY_FIPS :
2011-12-22 04:12:12 +04:00
case BT_SECURITY_HIGH :
return SMP_AUTH_MITM | SMP_AUTH_BONDING ;
case BT_SECURITY_MEDIUM :
return SMP_AUTH_BONDING ;
default :
return SMP_AUTH_NONE ;
}
}
2011-06-10 01:50:52 +04:00
static void build_pairing_cmd ( struct l2cap_conn * conn ,
2013-10-13 16:43:25 +04:00
struct smp_cmd_pairing * req ,
struct smp_cmd_pairing * rsp , __u8 authreq )
2011-06-10 01:50:52 +04:00
{
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-02-18 12:19:36 +04:00
struct hci_conn * hcon = conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
2014-10-26 23:19:10 +03:00
u8 local_dist = 0 , remote_dist = 0 , oob_flag = SMP_OOB_NOT_PRESENT ;
2011-07-08 01:59:38 +04:00
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_BONDABLE ) ) {
2014-03-09 23:19:17 +04:00
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN ;
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN ;
2011-07-08 01:59:38 +04:00
authreq | = SMP_AUTH_BONDING ;
2011-12-22 04:12:12 +04:00
} else {
authreq & = ~ SMP_AUTH_BONDING ;
2011-07-08 01:59:38 +04:00
}
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_RPA_RESOLVING ) )
2014-02-18 12:19:36 +04:00
remote_dist | = SMP_DIST_ID_KEY ;
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_PRIVACY ) )
2014-02-22 21:06:32 +04:00
local_dist | = SMP_DIST_ID_KEY ;
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_SC_ENABLED ) & &
2014-10-26 23:19:10 +03:00
( authreq & SMP_AUTH_SC ) ) {
struct oob_data * oob_data ;
u8 bdaddr_type ;
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_SSP_ENABLED ) ) {
2014-06-06 11:39:56 +04:00
local_dist | = SMP_DIST_LINK_KEY ;
remote_dist | = SMP_DIST_LINK_KEY ;
}
2014-10-26 23:19:10 +03:00
if ( hcon - > dst_type = = ADDR_LE_DEV_PUBLIC )
bdaddr_type = BDADDR_LE_PUBLIC ;
else
bdaddr_type = BDADDR_LE_RANDOM ;
oob_data = hci_find_remote_oob_data ( hdev , & hcon - > dst ,
bdaddr_type ) ;
2015-01-31 11:15:52 +03:00
if ( oob_data & & oob_data - > present ) {
2015-03-16 12:45:44 +03:00
set_bit ( SMP_FLAG_REMOTE_OOB , & smp - > flags ) ;
2014-10-26 23:19:10 +03:00
oob_flag = SMP_OOB_PRESENT ;
2014-10-28 17:17:05 +03:00
memcpy ( smp - > rr , oob_data - > rand256 , 16 ) ;
2014-10-26 23:19:10 +03:00
memcpy ( smp - > pcnf , oob_data - > hash256 , 16 ) ;
2015-03-16 22:34:56 +03:00
SMP_DBG ( " OOB Remote Confirmation: %16phN " , smp - > pcnf ) ;
SMP_DBG ( " OOB Remote Random: %16phN " , smp - > rr ) ;
2014-10-26 23:19:10 +03:00
}
2014-06-06 11:39:56 +04:00
} else {
authreq & = ~ SMP_AUTH_SC ;
}
2011-07-08 01:59:38 +04:00
if ( rsp = = NULL ) {
req - > io_capability = conn - > hcon - > io_capability ;
2014-10-26 23:19:10 +03:00
req - > oob_flag = oob_flag ;
2015-06-11 13:52:26 +03:00
req - > max_key_size = SMP_DEV ( hdev ) - > max_key_size ;
2014-02-18 12:19:36 +04:00
req - > init_key_dist = local_dist ;
req - > resp_key_dist = remote_dist ;
2014-05-26 14:29:28 +04:00
req - > auth_req = ( authreq & AUTH_REQ_MASK ( hdev ) ) ;
2014-02-18 12:19:36 +04:00
smp - > remote_key_dist = remote_dist ;
2011-07-08 01:59:38 +04:00
return ;
}
rsp - > io_capability = conn - > hcon - > io_capability ;
2014-10-26 23:19:10 +03:00
rsp - > oob_flag = oob_flag ;
2015-06-11 13:52:26 +03:00
rsp - > max_key_size = SMP_DEV ( hdev ) - > max_key_size ;
2014-02-18 12:19:36 +04:00
rsp - > init_key_dist = req - > init_key_dist & remote_dist ;
rsp - > resp_key_dist = req - > resp_key_dist & local_dist ;
2014-05-26 14:29:28 +04:00
rsp - > auth_req = ( authreq & AUTH_REQ_MASK ( hdev ) ) ;
2014-02-18 12:19:36 +04:00
smp - > remote_key_dist = rsp - > init_key_dist ;
2011-06-10 01:50:52 +04:00
}
2011-06-14 20:37:42 +04:00
static u8 check_enc_key_size ( struct l2cap_conn * conn , __u8 max_key_size )
{
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
2015-06-11 13:52:26 +03:00
struct hci_dev * hdev = conn - > hcon - > hdev ;
2014-08-08 10:37:18 +04:00
struct smp_chan * smp = chan - > data ;
2011-09-05 21:31:30 +04:00
2015-06-11 13:52:26 +03:00
if ( max_key_size > SMP_DEV ( hdev ) - > max_key_size | |
max_key_size < SMP_MIN_ENC_KEY_SIZE )
2011-06-14 20:37:42 +04:00
return SMP_ENC_KEY_SIZE ;
2012-01-31 02:29:12 +04:00
smp - > enc_key_size = max_key_size ;
2011-06-14 20:37:42 +04:00
return 0 ;
}
2014-08-11 23:06:44 +04:00
static void smp_chan_destroy ( struct l2cap_conn * conn )
{
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-12-03 13:43:39 +03:00
struct hci_conn * hcon = conn - > hcon ;
2014-08-11 23:06:44 +04:00
bool complete ;
BUG_ON ( ! smp ) ;
cancel_delayed_work_sync ( & smp - > security_timer ) ;
complete = test_bit ( SMP_FLAG_COMPLETE , & smp - > flags ) ;
2014-12-03 13:43:39 +03:00
mgmt_smp_complete ( hcon , complete ) ;
2014-08-11 23:06:44 +04:00
2015-03-16 11:10:18 +03:00
kzfree ( smp - > csrk ) ;
kzfree ( smp - > slave_csrk ) ;
kzfree ( smp - > link_key ) ;
2014-08-11 23:06:44 +04:00
2016-01-24 16:18:30 +03:00
crypto_free_skcipher ( smp - > tfm_aes ) ;
crypto_free_shash ( smp - > tfm_cmac ) ;
2014-08-11 23:06:44 +04:00
2014-12-03 13:43:39 +03:00
/* Ensure that we don't leave any debug key around if debug key
* support hasn ' t been explicitly enabled .
*/
if ( smp - > ltk & & smp - > ltk - > type = = SMP_LTK_P256_DEBUG & &
2015-03-13 12:11:00 +03:00
! hci_dev_test_flag ( hcon - > hdev , HCI_KEEP_DEBUG_KEYS ) ) {
2014-12-03 13:43:39 +03:00
list_del_rcu ( & smp - > ltk - > list ) ;
kfree_rcu ( smp - > ltk , rcu ) ;
smp - > ltk = NULL ;
}
2014-08-11 23:06:44 +04:00
/* If pairing failed clean up any keys we might have */
if ( ! complete ) {
if ( smp - > ltk ) {
2014-11-13 15:37:47 +03:00
list_del_rcu ( & smp - > ltk - > list ) ;
kfree_rcu ( smp - > ltk , rcu ) ;
2014-08-11 23:06:44 +04:00
}
if ( smp - > slave_ltk ) {
2014-11-13 15:37:47 +03:00
list_del_rcu ( & smp - > slave_ltk - > list ) ;
kfree_rcu ( smp - > slave_ltk , rcu ) ;
2014-08-11 23:06:44 +04:00
}
if ( smp - > remote_irk ) {
2014-11-13 15:37:48 +03:00
list_del_rcu ( & smp - > remote_irk - > list ) ;
kfree_rcu ( smp - > remote_irk , rcu ) ;
2014-08-11 23:06:44 +04:00
}
}
chan - > data = NULL ;
2015-03-16 11:10:18 +03:00
kzfree ( smp ) ;
2014-12-03 13:43:39 +03:00
hci_conn_drop ( hcon ) ;
2014-08-11 23:06:44 +04:00
}
2013-11-06 13:24:57 +04:00
static void smp_failure ( struct l2cap_conn * conn , u8 reason )
2011-11-23 20:28:36 +04:00
{
2012-02-09 18:07:29 +04:00
struct hci_conn * hcon = conn - > hcon ;
2014-08-11 23:06:40 +04:00
struct l2cap_chan * chan = conn - > smp ;
2012-02-09 18:07:29 +04:00
2013-11-06 13:24:57 +04:00
if ( reason )
2011-11-23 20:28:36 +04:00
smp_send_cmd ( conn , SMP_CMD_PAIRING_FAIL , sizeof ( reason ) ,
2013-10-13 16:43:25 +04:00
& reason ) ;
2011-11-23 20:28:36 +04:00
2014-09-09 04:09:49 +04:00
mgmt_auth_failed ( hcon , HCI_ERROR_AUTH_FAILURE ) ;
2012-02-02 01:27:56 +04:00
2014-09-05 23:19:52 +04:00
if ( chan - > data )
2012-02-02 01:27:56 +04:00
smp_chan_destroy ( conn ) ;
2011-11-23 20:28:36 +04:00
}
2011-12-22 04:12:12 +04:00
# define JUST_WORKS 0x00
# define JUST_CFM 0x01
# define REQ_PASSKEY 0x02
# define CFM_PASSKEY 0x03
# define REQ_OOB 0x04
2014-05-31 19:51:02 +04:00
# define DSP_PASSKEY 0x05
2011-12-22 04:12:12 +04:00
# define OVERLAP 0xFF
static const u8 gen_method [ 5 ] [ 5 ] = {
{ JUST_WORKS , JUST_CFM , REQ_PASSKEY , JUST_WORKS , REQ_PASSKEY } ,
{ JUST_WORKS , JUST_CFM , REQ_PASSKEY , JUST_WORKS , REQ_PASSKEY } ,
{ CFM_PASSKEY , CFM_PASSKEY , REQ_PASSKEY , JUST_WORKS , CFM_PASSKEY } ,
{ JUST_WORKS , JUST_CFM , JUST_WORKS , JUST_WORKS , JUST_CFM } ,
{ CFM_PASSKEY , CFM_PASSKEY , REQ_PASSKEY , JUST_WORKS , OVERLAP } ,
} ;
2014-05-31 19:51:02 +04:00
static const u8 sc_method [ 5 ] [ 5 ] = {
{ JUST_WORKS , JUST_CFM , REQ_PASSKEY , JUST_WORKS , REQ_PASSKEY } ,
{ JUST_WORKS , CFM_PASSKEY , REQ_PASSKEY , JUST_WORKS , CFM_PASSKEY } ,
{ DSP_PASSKEY , DSP_PASSKEY , REQ_PASSKEY , JUST_WORKS , DSP_PASSKEY } ,
{ JUST_WORKS , JUST_CFM , JUST_WORKS , JUST_WORKS , JUST_CFM } ,
{ DSP_PASSKEY , CFM_PASSKEY , REQ_PASSKEY , JUST_WORKS , CFM_PASSKEY } ,
} ;
2014-06-17 14:07:38 +04:00
static u8 get_auth_method ( struct smp_chan * smp , u8 local_io , u8 remote_io )
{
2014-07-09 20:18:09 +04:00
/* If either side has unknown io_caps, use JUST_CFM (which gets
* converted later to JUST_WORKS if we ' re initiators .
*/
2014-06-17 14:07:38 +04:00
if ( local_io > SMP_IO_KEYBOARD_DISPLAY | |
remote_io > SMP_IO_KEYBOARD_DISPLAY )
2014-07-09 20:18:09 +04:00
return JUST_CFM ;
2014-06-17 14:07:38 +04:00
2014-05-31 19:51:02 +04:00
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) )
return sc_method [ remote_io ] [ local_io ] ;
2014-06-17 14:07:38 +04:00
return gen_method [ remote_io ] [ local_io ] ;
}
2011-12-22 04:12:12 +04:00
static int tk_request ( struct l2cap_conn * conn , u8 remote_oob , u8 auth ,
u8 local_io , u8 remote_io )
{
struct hci_conn * hcon = conn - > hcon ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2011-12-22 04:12:12 +04:00
u32 passkey = 0 ;
int ret = 0 ;
/* Initialize key for JUST WORKS */
memset ( smp - > tk , 0 , sizeof ( smp - > tk ) ) ;
2014-05-20 10:45:50 +04:00
clear_bit ( SMP_FLAG_TK_VALID , & smp - > flags ) ;
2011-12-22 04:12:12 +04:00
BT_DBG ( " tk_request: auth:%d lcl:%d rem:%d " , auth , local_io , remote_io ) ;
2014-07-09 20:18:09 +04:00
/* If neither side wants MITM, either "just" confirm an incoming
* request or use just - works for outgoing ones . The JUST_CFM
* will be converted to JUST_WORKS if necessary later in this
* function . If either side has MITM look up the method from the
* table .
*/
2014-06-17 14:07:38 +04:00
if ( ! ( auth & SMP_AUTH_MITM ) )
2014-05-31 19:48:26 +04:00
smp - > method = JUST_CFM ;
2011-12-22 04:12:12 +04:00
else
2014-05-31 19:48:26 +04:00
smp - > method = get_auth_method ( smp , local_io , remote_io ) ;
2011-12-22 04:12:12 +04:00
2014-03-24 16:39:07 +04:00
/* Don't confirm locally initiated pairing attempts */
2014-05-31 19:48:26 +04:00
if ( smp - > method = = JUST_CFM & & test_bit ( SMP_FLAG_INITIATOR ,
& smp - > flags ) )
smp - > method = JUST_WORKS ;
2014-03-24 16:39:07 +04:00
2014-07-16 16:09:13 +04:00
/* Don't bother user space with no IO capabilities */
2014-05-31 19:48:26 +04:00
if ( smp - > method = = JUST_CFM & &
hcon - > io_capability = = HCI_IO_NO_INPUT_OUTPUT )
smp - > method = JUST_WORKS ;
2014-07-16 16:09:13 +04:00
2011-12-22 04:12:12 +04:00
/* If Just Works, Continue with Zero TK */
2014-05-31 19:48:26 +04:00
if ( smp - > method = = JUST_WORKS ) {
2014-05-20 10:45:50 +04:00
set_bit ( SMP_FLAG_TK_VALID , & smp - > flags ) ;
2011-12-22 04:12:12 +04:00
return 0 ;
}
Bluetooth: Add workaround for broken OS X legacy SMP pairing
OS X version 10.10.2 (and possibly older versions) doesn't support LE
Secure Connections but incorrectly copies all authentication request
bits from a Security Request to its Pairing Request. The result is that
an SC capable initiator (such as BlueZ) will think OS X intends to do SC
when in fact it's incapable of it:
< ACL Data TX: Handle 3585 flags 0x00 dlen 6
SMP: Security Request (0x0b) len 1
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
> ACL Data RX: Handle 3585 flags 0x02 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey IdKey Sign (0x07)
< ACL Data TX: Handle 3585 flags 0x00 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey Sign (0x05)
The pairing eventually fails when we get an unexpected Pairing Confirm
PDU instead of a Public Key PDU:
> ACL Data RX: Handle 3585 flags 0x02 dlen 21
SMP: Pairing Confirm (0x03) len 16
Confim value: bcc3bed31b8f313a78ec3cce32685faf
It is only at this point that we can speculate that the remote doesn't
really support SC. This patch creates a workaround for the just-works
model, however the MITM case is unsolvable because the OS X user has
already been requested to enter a PIN which we're now expected to
randomly generate and show the user (i.e. a chicken-and-egg problem).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-03-15 20:34:04 +03:00
/* If this function is used for SC -> legacy fallback we
* can only recover the just - works case .
*/
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) )
return - EINVAL ;
2011-12-22 04:12:12 +04:00
/* Not Just Works/Confirm results in MITM Authentication */
2014-05-31 19:48:26 +04:00
if ( smp - > method ! = JUST_CFM ) {
2014-05-20 10:45:50 +04:00
set_bit ( SMP_FLAG_MITM_AUTH , & smp - > flags ) ;
2014-09-18 12:26:32 +04:00
if ( hcon - > pending_sec_level < BT_SECURITY_HIGH )
hcon - > pending_sec_level = BT_SECURITY_HIGH ;
}
2011-12-22 04:12:12 +04:00
/* If both devices have Keyoard-Display I/O, the master
* Confirms and the slave Enters the passkey .
*/
2014-05-31 19:48:26 +04:00
if ( smp - > method = = OVERLAP ) {
2014-07-16 12:42:27 +04:00
if ( hcon - > role = = HCI_ROLE_MASTER )
2014-05-31 19:48:26 +04:00
smp - > method = CFM_PASSKEY ;
2011-12-22 04:12:12 +04:00
else
2014-05-31 19:48:26 +04:00
smp - > method = REQ_PASSKEY ;
2011-12-22 04:12:12 +04:00
}
2014-03-19 16:14:53 +04:00
/* Generate random passkey. */
2014-05-31 19:48:26 +04:00
if ( smp - > method = = CFM_PASSKEY ) {
2014-03-18 14:58:24 +04:00
memset ( smp - > tk , 0 , sizeof ( smp - > tk ) ) ;
2011-12-22 04:12:12 +04:00
get_random_bytes ( & passkey , sizeof ( passkey ) ) ;
passkey % = 1000000 ;
2014-03-18 14:58:24 +04:00
put_unaligned_le32 ( passkey , smp - > tk ) ;
2011-12-22 04:12:12 +04:00
BT_DBG ( " PassKey: %d " , passkey ) ;
2014-05-20 10:45:50 +04:00
set_bit ( SMP_FLAG_TK_VALID , & smp - > flags ) ;
2011-12-22 04:12:12 +04:00
}
2014-05-31 19:48:26 +04:00
if ( smp - > method = = REQ_PASSKEY )
2013-10-13 13:23:39 +04:00
ret = mgmt_user_passkey_request ( hcon - > hdev , & hcon - > dst ,
2012-02-09 17:26:12 +04:00
hcon - > type , hcon - > dst_type ) ;
2014-05-31 19:48:26 +04:00
else if ( smp - > method = = JUST_CFM )
2014-03-24 16:39:05 +04:00
ret = mgmt_user_confirm_request ( hcon - > hdev , & hcon - > dst ,
hcon - > type , hcon - > dst_type ,
passkey , 1 ) ;
2011-12-22 04:12:12 +04:00
else
2014-03-19 16:14:53 +04:00
ret = mgmt_user_passkey_notify ( hcon - > hdev , & hcon - > dst ,
2012-02-09 17:26:12 +04:00
hcon - > type , hcon - > dst_type ,
2014-03-20 10:18:14 +04:00
passkey , 0 ) ;
2011-12-22 04:12:12 +04:00
return ret ;
}
2014-05-20 10:45:52 +04:00
static u8 smp_confirm ( struct smp_chan * smp )
2011-09-05 21:31:31 +04:00
{
struct l2cap_conn * conn = smp - > conn ;
struct smp_cmd_pairing_confirm cp ;
int ret ;
BT_DBG ( " conn %p " , conn ) ;
2014-10-25 23:15:37 +04:00
ret = smp_c1 ( smp - > tfm_aes , smp - > tk , smp - > prnd , smp - > preq , smp - > prsp ,
2014-02-28 14:54:17 +04:00
conn - > hcon - > init_addr_type , & conn - > hcon - > init_addr ,
2014-03-18 14:58:24 +04:00
conn - > hcon - > resp_addr_type , & conn - > hcon - > resp_addr ,
cp . confirm_val ) ;
2014-05-20 10:45:52 +04:00
if ( ret )
return SMP_UNSPECIFIED ;
2011-09-05 21:31:31 +04:00
2014-05-20 10:45:50 +04:00
clear_bit ( SMP_FLAG_CFM_PENDING , & smp - > flags ) ;
2011-12-22 04:12:12 +04:00
2011-09-05 21:31:31 +04:00
smp_send_cmd ( smp - > conn , SMP_CMD_PAIRING_CONFIRM , sizeof ( cp ) , & cp ) ;
2014-09-05 23:19:55 +04:00
if ( conn - > hcon - > out )
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
else
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RANDOM ) ;
2014-05-20 10:45:52 +04:00
return 0 ;
2011-09-05 21:31:31 +04:00
}
2014-05-20 10:45:51 +04:00
static u8 smp_random ( struct smp_chan * smp )
2011-09-05 21:31:31 +04:00
{
struct l2cap_conn * conn = smp - > conn ;
struct hci_conn * hcon = conn - > hcon ;
2014-05-20 10:45:51 +04:00
u8 confirm [ 16 ] ;
2011-09-05 21:31:31 +04:00
int ret ;
2014-06-27 15:23:04 +04:00
if ( IS_ERR_OR_NULL ( smp - > tfm_aes ) )
2014-05-20 10:45:51 +04:00
return SMP_UNSPECIFIED ;
2011-09-05 21:31:31 +04:00
BT_DBG ( " conn %p %s " , conn , conn - > hcon - > out ? " master " : " slave " ) ;
2014-10-25 23:15:37 +04:00
ret = smp_c1 ( smp - > tfm_aes , smp - > tk , smp - > rrnd , smp - > preq , smp - > prsp ,
2014-02-28 14:54:17 +04:00
hcon - > init_addr_type , & hcon - > init_addr ,
2014-03-18 14:58:24 +04:00
hcon - > resp_addr_type , & hcon - > resp_addr , confirm ) ;
2014-05-20 10:45:51 +04:00
if ( ret )
return SMP_UNSPECIFIED ;
2011-09-05 21:31:31 +04:00
if ( memcmp ( smp - > pcnf , confirm , sizeof ( smp - > pcnf ) ) ! = 0 ) {
BT_ERR ( " Pairing failed (confirmation values mismatch) " ) ;
2014-05-20 10:45:51 +04:00
return SMP_CONFIRM_FAILED ;
2011-09-05 21:31:31 +04:00
}
if ( hcon - > out ) {
2014-02-28 04:00:28 +04:00
u8 stk [ 16 ] ;
__le64 rand = 0 ;
__le16 ediv = 0 ;
2011-09-05 21:31:31 +04:00
2014-10-25 23:15:37 +04:00
smp_s1 ( smp - > tfm_aes , smp - > tk , smp - > rrnd , smp - > prnd , stk ) ;
2011-09-05 21:31:31 +04:00
2014-05-20 10:45:51 +04:00
if ( test_and_set_bit ( HCI_CONN_ENCRYPT_PEND , & hcon - > flags ) )
return SMP_UNSPECIFIED ;
2011-09-05 21:31:31 +04:00
2015-06-08 18:14:39 +03:00
hci_le_start_enc ( hcon , ediv , rand , stk , smp - > enc_key_size ) ;
2012-01-31 02:29:12 +04:00
hcon - > enc_key_size = smp - > enc_key_size ;
2014-07-01 20:14:12 +04:00
set_bit ( HCI_CONN_STK_ENCRYPT , & hcon - > flags ) ;
2011-09-05 21:31:31 +04:00
} else {
2014-06-10 16:19:50 +04:00
u8 stk [ 16 ] , auth ;
2014-02-28 04:00:28 +04:00
__le64 rand = 0 ;
__le16 ediv = 0 ;
2011-09-05 21:31:31 +04:00
2014-03-18 14:58:24 +04:00
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM , sizeof ( smp - > prnd ) ,
smp - > prnd ) ;
2011-09-05 21:31:31 +04:00
2014-10-25 23:15:37 +04:00
smp_s1 ( smp - > tfm_aes , smp - > tk , smp - > prnd , smp - > rrnd , stk ) ;
2011-09-05 21:31:31 +04:00
2014-06-10 16:19:50 +04:00
if ( hcon - > pending_sec_level = = BT_SECURITY_HIGH )
auth = 1 ;
else
auth = 0 ;
2014-06-16 20:25:15 +04:00
/* Even though there's no _SLAVE suffix this is the
* slave STK we ' re adding for later lookup ( the master
* STK never needs to be stored ) .
*/
2013-10-13 13:23:39 +04:00
hci_add_ltk ( hcon - > hdev , & hcon - > dst , hcon - > dst_type ,
2014-06-16 20:25:16 +04:00
SMP_STK , auth , stk , smp - > enc_key_size , ediv , rand ) ;
2011-09-05 21:31:31 +04:00
}
2014-05-20 10:45:51 +04:00
return 0 ;
2011-09-05 21:31:31 +04:00
}
2014-08-11 23:06:36 +04:00
static void smp_notify_keys ( struct l2cap_conn * conn )
{
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
struct hci_conn * hcon = conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
struct smp_cmd_pairing * req = ( void * ) & smp - > preq [ 1 ] ;
struct smp_cmd_pairing * rsp = ( void * ) & smp - > prsp [ 1 ] ;
bool persistent ;
2015-10-12 14:36:19 +03:00
if ( hcon - > type = = ACL_LINK ) {
if ( hcon - > key_type = = HCI_LK_DEBUG_COMBINATION )
persistent = false ;
else
persistent = ! test_bit ( HCI_CONN_FLUSH_KEY ,
& hcon - > flags ) ;
} else {
/* The LTKs, IRKs and CSRKs should be persistent only if
* both sides had the bonding bit set in their
* authentication requests .
*/
persistent = ! ! ( ( req - > auth_req & rsp - > auth_req ) &
SMP_AUTH_BONDING ) ;
}
2014-08-11 23:06:36 +04:00
if ( smp - > remote_irk ) {
2015-10-12 14:36:19 +03:00
mgmt_new_irk ( hdev , smp - > remote_irk , persistent ) ;
2014-08-11 23:06:36 +04:00
/* Now that user space can be considered to know the
* identity address track the connection based on it
2014-08-14 13:34:26 +04:00
* from now on ( assuming this is an LE link ) .
2014-08-11 23:06:36 +04:00
*/
2014-08-14 13:34:26 +04:00
if ( hcon - > type = = LE_LINK ) {
bacpy ( & hcon - > dst , & smp - > remote_irk - > bdaddr ) ;
hcon - > dst_type = smp - > remote_irk - > addr_type ;
queue_work ( hdev - > workqueue , & conn - > id_addr_update_work ) ;
}
2014-08-11 23:06:36 +04:00
}
if ( smp - > csrk ) {
smp - > csrk - > bdaddr_type = hcon - > dst_type ;
bacpy ( & smp - > csrk - > bdaddr , & hcon - > dst ) ;
mgmt_new_csrk ( hdev , smp - > csrk , persistent ) ;
}
if ( smp - > slave_csrk ) {
smp - > slave_csrk - > bdaddr_type = hcon - > dst_type ;
bacpy ( & smp - > slave_csrk - > bdaddr , & hcon - > dst ) ;
mgmt_new_csrk ( hdev , smp - > slave_csrk , persistent ) ;
}
if ( smp - > ltk ) {
smp - > ltk - > bdaddr_type = hcon - > dst_type ;
bacpy ( & smp - > ltk - > bdaddr , & hcon - > dst ) ;
mgmt_new_ltk ( hdev , smp - > ltk , persistent ) ;
}
if ( smp - > slave_ltk ) {
smp - > slave_ltk - > bdaddr_type = hcon - > dst_type ;
bacpy ( & smp - > slave_ltk - > bdaddr , & hcon - > dst ) ;
mgmt_new_ltk ( hdev , smp - > slave_ltk , persistent ) ;
}
2014-06-06 12:54:04 +04:00
if ( smp - > link_key ) {
2014-06-01 17:33:39 +04:00
struct link_key * key ;
u8 type ;
if ( test_bit ( SMP_FLAG_DEBUG_KEY , & smp - > flags ) )
type = HCI_LK_DEBUG_COMBINATION ;
else if ( hcon - > sec_level = = BT_SECURITY_FIPS )
type = HCI_LK_AUTH_COMBINATION_P256 ;
else
type = HCI_LK_UNAUTH_COMBINATION_P256 ;
key = hci_add_link_key ( hdev , smp - > conn - > hcon , & hcon - > dst ,
smp - > link_key , type , 0 , & persistent ) ;
if ( key ) {
mgmt_new_link_key ( hdev , key , persistent ) ;
/* Don't keep debug keys around if the relevant
* flag is not set .
*/
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hdev , HCI_KEEP_DEBUG_KEYS ) & &
2014-06-01 17:33:39 +04:00
key - > type = = HCI_LK_DEBUG_COMBINATION ) {
list_del_rcu ( & key - > list ) ;
kfree_rcu ( key , rcu ) ;
}
}
2014-06-06 12:54:04 +04:00
}
}
2014-06-04 12:07:40 +04:00
static void sc_add_ltk ( struct smp_chan * smp )
{
struct hci_conn * hcon = smp - > conn - > hcon ;
u8 key_type , auth ;
if ( test_bit ( SMP_FLAG_DEBUG_KEY , & smp - > flags ) )
key_type = SMP_LTK_P256_DEBUG ;
else
key_type = SMP_LTK_P256 ;
if ( hcon - > pending_sec_level = = BT_SECURITY_FIPS )
auth = 1 ;
else
auth = 0 ;
smp - > ltk = hci_add_ltk ( hcon - > hdev , & hcon - > dst , hcon - > dst_type ,
key_type , auth , smp - > tk , smp - > enc_key_size ,
0 , 0 ) ;
}
2014-06-06 12:54:04 +04:00
static void sc_generate_link_key ( struct smp_chan * smp )
{
/* These constants are as specified in the core specification.
* In ASCII they spell out to ' tmp1 ' and ' lebr ' .
*/
const u8 tmp1 [ 4 ] = { 0x31 , 0x70 , 0x6d , 0x74 } ;
const u8 lebr [ 4 ] = { 0x72 , 0x62 , 0x65 , 0x6c } ;
smp - > link_key = kzalloc ( 16 , GFP_KERNEL ) ;
if ( ! smp - > link_key )
return ;
if ( smp_h6 ( smp - > tfm_cmac , smp - > tk , tmp1 , smp - > link_key ) ) {
2015-03-16 11:10:18 +03:00
kzfree ( smp - > link_key ) ;
2014-06-06 12:54:04 +04:00
smp - > link_key = NULL ;
return ;
}
if ( smp_h6 ( smp - > tfm_cmac , smp - > link_key , lebr , smp - > link_key ) ) {
2015-03-16 11:10:18 +03:00
kzfree ( smp - > link_key ) ;
2014-06-06 12:54:04 +04:00
smp - > link_key = NULL ;
return ;
}
2014-08-11 23:06:36 +04:00
}
2014-09-05 23:19:55 +04:00
static void smp_allow_key_dist ( struct smp_chan * smp )
{
/* Allow the first expected phase 3 PDU. The rest of the PDUs
* will be allowed in each PDU handler to ensure we receive
* them in the correct order .
*/
if ( smp - > remote_key_dist & SMP_DIST_ENC_KEY )
SMP_ALLOW_CMD ( smp , SMP_CMD_ENCRYPT_INFO ) ;
else if ( smp - > remote_key_dist & SMP_DIST_ID_KEY )
SMP_ALLOW_CMD ( smp , SMP_CMD_IDENT_INFO ) ;
else if ( smp - > remote_key_dist & SMP_DIST_SIGN )
SMP_ALLOW_CMD ( smp , SMP_CMD_SIGN_INFO ) ;
}
2014-08-14 13:34:26 +04:00
static void sc_generate_ltk ( struct smp_chan * smp )
{
/* These constants are as specified in the core specification.
* In ASCII they spell out to ' tmp2 ' and ' brle ' .
*/
const u8 tmp2 [ 4 ] = { 0x32 , 0x70 , 0x6d , 0x74 } ;
const u8 brle [ 4 ] = { 0x65 , 0x6c , 0x72 , 0x62 } ;
struct hci_conn * hcon = smp - > conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
struct link_key * key ;
key = hci_find_link_key ( hdev , & hcon - > dst ) ;
if ( ! key ) {
BT_ERR ( " %s No Link Key found to generate LTK " , hdev - > name ) ;
return ;
}
if ( key - > type = = HCI_LK_DEBUG_COMBINATION )
set_bit ( SMP_FLAG_DEBUG_KEY , & smp - > flags ) ;
if ( smp_h6 ( smp - > tfm_cmac , key - > val , tmp2 , smp - > tk ) )
return ;
if ( smp_h6 ( smp - > tfm_cmac , smp - > tk , brle , smp - > tk ) )
return ;
sc_add_ltk ( smp ) ;
}
2014-09-05 23:19:51 +04:00
static void smp_distribute_keys ( struct smp_chan * smp )
2014-08-11 23:06:36 +04:00
{
struct smp_cmd_pairing * req , * rsp ;
2014-08-11 23:06:43 +04:00
struct l2cap_conn * conn = smp - > conn ;
2014-08-11 23:06:36 +04:00
struct hci_conn * hcon = conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
__u8 * keydist ;
BT_DBG ( " conn %p " , conn ) ;
rsp = ( void * ) & smp - > prsp [ 1 ] ;
/* The responder sends its keys first */
2014-09-05 23:19:55 +04:00
if ( hcon - > out & & ( smp - > remote_key_dist & KEY_DIST_MASK ) ) {
smp_allow_key_dist ( smp ) ;
2014-08-11 23:06:43 +04:00
return ;
2014-09-05 23:19:55 +04:00
}
2014-08-11 23:06:36 +04:00
req = ( void * ) & smp - > preq [ 1 ] ;
if ( hcon - > out ) {
keydist = & rsp - > init_key_dist ;
* keydist & = req - > init_key_dist ;
} else {
keydist = & rsp - > resp_key_dist ;
* keydist & = req - > resp_key_dist ;
}
2014-06-06 12:54:04 +04:00
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) ) {
2014-08-14 13:34:26 +04:00
if ( hcon - > type = = LE_LINK & & ( * keydist & SMP_DIST_LINK_KEY ) )
2014-06-06 12:54:04 +04:00
sc_generate_link_key ( smp ) ;
2014-08-14 13:34:26 +04:00
if ( hcon - > type = = ACL_LINK & & ( * keydist & SMP_DIST_ENC_KEY ) )
sc_generate_ltk ( smp ) ;
2014-06-06 12:54:04 +04:00
/* Clear the keys which are generated but not distributed */
* keydist & = ~ SMP_SC_NO_DIST ;
}
2014-08-11 23:06:36 +04:00
BT_DBG ( " keydist 0x%x " , * keydist ) ;
if ( * keydist & SMP_DIST_ENC_KEY ) {
struct smp_cmd_encrypt_info enc ;
struct smp_cmd_master_ident ident ;
struct smp_ltk * ltk ;
u8 authenticated ;
__le16 ediv ;
__le64 rand ;
2015-06-10 11:11:20 +03:00
/* Make sure we generate only the significant amount of
* bytes based on the encryption key size , and set the rest
* of the value to zeroes .
*/
get_random_bytes ( enc . ltk , smp - > enc_key_size ) ;
memset ( enc . ltk + smp - > enc_key_size , 0 ,
sizeof ( enc . ltk ) - smp - > enc_key_size ) ;
2014-08-11 23:06:36 +04:00
get_random_bytes ( & ediv , sizeof ( ediv ) ) ;
get_random_bytes ( & rand , sizeof ( rand ) ) ;
smp_send_cmd ( conn , SMP_CMD_ENCRYPT_INFO , sizeof ( enc ) , & enc ) ;
authenticated = hcon - > sec_level = = BT_SECURITY_HIGH ;
ltk = hci_add_ltk ( hdev , & hcon - > dst , hcon - > dst_type ,
SMP_LTK_SLAVE , authenticated , enc . ltk ,
smp - > enc_key_size , ediv , rand ) ;
smp - > slave_ltk = ltk ;
ident . ediv = ediv ;
ident . rand = rand ;
smp_send_cmd ( conn , SMP_CMD_MASTER_IDENT , sizeof ( ident ) , & ident ) ;
* keydist & = ~ SMP_DIST_ENC_KEY ;
}
if ( * keydist & SMP_DIST_ID_KEY ) {
struct smp_cmd_ident_addr_info addrinfo ;
struct smp_cmd_ident_info idinfo ;
memcpy ( idinfo . irk , hdev - > irk , sizeof ( idinfo . irk ) ) ;
smp_send_cmd ( conn , SMP_CMD_IDENT_INFO , sizeof ( idinfo ) , & idinfo ) ;
/* The hci_conn contains the local identity address
* after the connection has been established .
*
* This is true even when the connection has been
* established using a resolvable random address .
*/
bacpy ( & addrinfo . bdaddr , & hcon - > src ) ;
addrinfo . addr_type = hcon - > src_type ;
smp_send_cmd ( conn , SMP_CMD_IDENT_ADDR_INFO , sizeof ( addrinfo ) ,
& addrinfo ) ;
* keydist & = ~ SMP_DIST_ID_KEY ;
}
if ( * keydist & SMP_DIST_SIGN ) {
struct smp_cmd_sign_info sign ;
struct smp_csrk * csrk ;
/* Generate a new random key */
get_random_bytes ( sign . csrk , sizeof ( sign . csrk ) ) ;
csrk = kzalloc ( sizeof ( * csrk ) , GFP_KERNEL ) ;
if ( csrk ) {
2015-02-27 11:11:13 +03:00
if ( hcon - > sec_level > BT_SECURITY_MEDIUM )
csrk - > type = MGMT_CSRK_LOCAL_AUTHENTICATED ;
else
csrk - > type = MGMT_CSRK_LOCAL_UNAUTHENTICATED ;
2014-08-11 23:06:36 +04:00
memcpy ( csrk - > val , sign . csrk , sizeof ( csrk - > val ) ) ;
}
smp - > slave_csrk = csrk ;
smp_send_cmd ( conn , SMP_CMD_SIGN_INFO , sizeof ( sign ) , & sign ) ;
* keydist & = ~ SMP_DIST_SIGN ;
}
/* If there are still keys to be received wait for them */
2014-09-05 23:19:55 +04:00
if ( smp - > remote_key_dist & KEY_DIST_MASK ) {
smp_allow_key_dist ( smp ) ;
2014-08-11 23:06:43 +04:00
return ;
2014-09-05 23:19:55 +04:00
}
2014-08-11 23:06:36 +04:00
set_bit ( SMP_FLAG_COMPLETE , & smp - > flags ) ;
smp_notify_keys ( conn ) ;
smp_chan_destroy ( conn ) ;
}
2014-08-11 23:06:40 +04:00
static void smp_timeout ( struct work_struct * work )
{
struct smp_chan * smp = container_of ( work , struct smp_chan ,
security_timer . work ) ;
struct l2cap_conn * conn = smp - > conn ;
BT_DBG ( " conn %p " , conn ) ;
2014-08-18 21:33:29 +04:00
hci_disconnect ( conn - > hcon , HCI_ERROR_REMOTE_USER_TERM ) ;
2014-08-11 23:06:40 +04:00
}
2011-09-05 21:31:31 +04:00
static struct smp_chan * smp_chan_create ( struct l2cap_conn * conn )
{
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
2011-09-05 21:31:31 +04:00
struct smp_chan * smp ;
2013-10-13 16:43:25 +04:00
smp = kzalloc ( sizeof ( * smp ) , GFP_ATOMIC ) ;
2014-09-05 23:19:52 +04:00
if ( ! smp )
2011-09-05 21:31:31 +04:00
return NULL ;
2016-01-24 16:18:30 +03:00
smp - > tfm_aes = crypto_alloc_skcipher ( " ecb(aes) " , 0 , CRYPTO_ALG_ASYNC ) ;
2014-06-27 15:23:03 +04:00
if ( IS_ERR ( smp - > tfm_aes ) ) {
BT_ERR ( " Unable to create ECB crypto context " ) ;
2015-03-16 11:10:18 +03:00
kzfree ( smp ) ;
2014-06-27 15:23:03 +04:00
return NULL ;
}
2016-01-24 16:18:30 +03:00
smp - > tfm_cmac = crypto_alloc_shash ( " cmac(aes) " , 0 , 0 ) ;
2014-05-02 15:19:47 +04:00
if ( IS_ERR ( smp - > tfm_cmac ) ) {
BT_ERR ( " Unable to create CMAC crypto context " ) ;
2016-01-24 16:18:30 +03:00
crypto_free_skcipher ( smp - > tfm_aes ) ;
2015-03-16 11:10:18 +03:00
kzfree ( smp ) ;
2014-05-02 15:19:47 +04:00
return NULL ;
}
2011-09-05 21:31:31 +04:00
smp - > conn = conn ;
2014-08-08 10:37:18 +04:00
chan - > data = smp ;
2011-09-05 21:31:31 +04:00
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_FAIL ) ;
2014-08-11 23:06:40 +04:00
INIT_DELAYED_WORK ( & smp - > security_timer , smp_timeout ) ;
2011-09-05 21:31:31 +04:00
hci_conn_hold ( conn - > hcon ) ;
return smp ;
}
2014-06-06 12:44:05 +04:00
static int sc_mackey_and_ltk ( struct smp_chan * smp , u8 mackey [ 16 ] , u8 ltk [ 16 ] )
{
struct hci_conn * hcon = smp - > conn - > hcon ;
u8 * na , * nb , a [ 7 ] , b [ 7 ] ;
if ( hcon - > out ) {
na = smp - > prnd ;
nb = smp - > rrnd ;
} else {
na = smp - > rrnd ;
nb = smp - > prnd ;
}
memcpy ( a , & hcon - > init_addr , 6 ) ;
memcpy ( b , & hcon - > resp_addr , 6 ) ;
a [ 6 ] = hcon - > init_addr_type ;
b [ 6 ] = hcon - > resp_addr_type ;
return smp_f5 ( smp - > tfm_cmac , smp - > dhkey , na , nb , a , b , mackey , ltk ) ;
}
2014-06-25 12:10:28 +04:00
static void sc_dhkey_check ( struct smp_chan * smp )
2014-06-06 12:44:05 +04:00
{
struct hci_conn * hcon = smp - > conn - > hcon ;
struct smp_cmd_dhkey_check check ;
u8 a [ 7 ] , b [ 7 ] , * local_addr , * remote_addr ;
u8 io_cap [ 3 ] , r [ 16 ] ;
memcpy ( a , & hcon - > init_addr , 6 ) ;
memcpy ( b , & hcon - > resp_addr , 6 ) ;
a [ 6 ] = hcon - > init_addr_type ;
b [ 6 ] = hcon - > resp_addr_type ;
if ( hcon - > out ) {
local_addr = a ;
remote_addr = b ;
memcpy ( io_cap , & smp - > preq [ 1 ] , 3 ) ;
} else {
local_addr = b ;
remote_addr = a ;
memcpy ( io_cap , & smp - > prsp [ 1 ] , 3 ) ;
}
2014-06-01 16:38:09 +04:00
memset ( r , 0 , sizeof ( r ) ) ;
if ( smp - > method = = REQ_PASSKEY | | smp - > method = = DSP_PASSKEY )
2014-06-25 12:10:28 +04:00
put_unaligned_le32 ( hcon - > passkey_notify , r ) ;
2014-06-06 12:44:05 +04:00
2014-10-28 17:17:05 +03:00
if ( smp - > method = = REQ_OOB )
memcpy ( r , smp - > rr , 16 ) ;
2014-06-06 12:44:05 +04:00
smp_f6 ( smp - > tfm_cmac , smp - > mackey , smp - > prnd , smp - > rrnd , r , io_cap ,
local_addr , remote_addr , check . e ) ;
smp_send_cmd ( smp - > conn , SMP_CMD_DHKEY_CHECK , sizeof ( check ) , & check ) ;
2014-06-01 16:38:09 +04:00
}
2014-06-25 12:10:28 +04:00
static u8 sc_passkey_send_confirm ( struct smp_chan * smp )
{
struct l2cap_conn * conn = smp - > conn ;
struct hci_conn * hcon = conn - > hcon ;
struct smp_cmd_pairing_confirm cfm ;
u8 r ;
r = ( ( hcon - > passkey_notify > > smp - > passkey_round ) & 0x01 ) ;
r | = 0x80 ;
get_random_bytes ( smp - > prnd , sizeof ( smp - > prnd ) ) ;
if ( smp_f4 ( smp - > tfm_cmac , smp - > local_pk , smp - > remote_pk , smp - > prnd , r ,
cfm . confirm_val ) )
return SMP_UNSPECIFIED ;
smp_send_cmd ( conn , SMP_CMD_PAIRING_CONFIRM , sizeof ( cfm ) , & cfm ) ;
return 0 ;
}
static u8 sc_passkey_round ( struct smp_chan * smp , u8 smp_op )
{
struct l2cap_conn * conn = smp - > conn ;
struct hci_conn * hcon = conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
u8 cfm [ 16 ] , r ;
/* Ignore the PDU if we've already done 20 rounds (0 - 19) */
if ( smp - > passkey_round > = 20 )
return 0 ;
switch ( smp_op ) {
case SMP_CMD_PAIRING_RANDOM :
r = ( ( hcon - > passkey_notify > > smp - > passkey_round ) & 0x01 ) ;
r | = 0x80 ;
if ( smp_f4 ( smp - > tfm_cmac , smp - > remote_pk , smp - > local_pk ,
smp - > rrnd , r , cfm ) )
return SMP_UNSPECIFIED ;
if ( memcmp ( smp - > pcnf , cfm , 16 ) )
return SMP_CONFIRM_FAILED ;
smp - > passkey_round + + ;
if ( smp - > passkey_round = = 20 ) {
/* Generate MacKey and LTK */
if ( sc_mackey_and_ltk ( smp , smp - > mackey , smp - > tk ) )
return SMP_UNSPECIFIED ;
}
/* The round is only complete when the initiator
* receives pairing random .
*/
if ( ! hcon - > out ) {
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM ,
sizeof ( smp - > prnd ) , smp - > prnd ) ;
2014-06-04 12:07:40 +04:00
if ( smp - > passkey_round = = 20 )
2014-06-25 12:10:28 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_DHKEY_CHECK ) ;
2014-06-04 12:07:40 +04:00
else
2014-06-25 12:10:28 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
return 0 ;
}
/* Start the next round */
if ( smp - > passkey_round ! = 20 )
return sc_passkey_round ( smp , 0 ) ;
/* Passkey rounds are complete - start DHKey Check */
sc_dhkey_check ( smp ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_DHKEY_CHECK ) ;
break ;
case SMP_CMD_PAIRING_CONFIRM :
if ( test_bit ( SMP_FLAG_WAIT_USER , & smp - > flags ) ) {
set_bit ( SMP_FLAG_CFM_PENDING , & smp - > flags ) ;
return 0 ;
}
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RANDOM ) ;
if ( hcon - > out ) {
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM ,
sizeof ( smp - > prnd ) , smp - > prnd ) ;
return 0 ;
}
return sc_passkey_send_confirm ( smp ) ;
case SMP_CMD_PUBLIC_KEY :
default :
/* Initiating device starts the round */
if ( ! hcon - > out )
return 0 ;
BT_DBG ( " %s Starting passkey round %u " , hdev - > name ,
smp - > passkey_round + 1 ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
return sc_passkey_send_confirm ( smp ) ;
}
return 0 ;
}
2014-06-01 16:38:09 +04:00
static int sc_user_reply ( struct smp_chan * smp , u16 mgmt_op , __le32 passkey )
{
2014-06-25 12:10:28 +04:00
struct l2cap_conn * conn = smp - > conn ;
struct hci_conn * hcon = conn - > hcon ;
u8 smp_op ;
clear_bit ( SMP_FLAG_WAIT_USER , & smp - > flags ) ;
2014-06-01 16:38:09 +04:00
switch ( mgmt_op ) {
case MGMT_OP_USER_PASSKEY_NEG_REPLY :
smp_failure ( smp - > conn , SMP_PASSKEY_ENTRY_FAILED ) ;
return 0 ;
case MGMT_OP_USER_CONFIRM_NEG_REPLY :
smp_failure ( smp - > conn , SMP_NUMERIC_COMP_FAILED ) ;
return 0 ;
2014-06-25 12:10:28 +04:00
case MGMT_OP_USER_PASSKEY_REPLY :
hcon - > passkey_notify = le32_to_cpu ( passkey ) ;
smp - > passkey_round = 0 ;
if ( test_and_clear_bit ( SMP_FLAG_CFM_PENDING , & smp - > flags ) )
smp_op = SMP_CMD_PAIRING_CONFIRM ;
else
smp_op = 0 ;
if ( sc_passkey_round ( smp , smp_op ) )
return - EIO ;
return 0 ;
2014-06-01 16:38:09 +04:00
}
2014-06-04 12:07:40 +04:00
/* Initiator sends DHKey check first */
if ( hcon - > out ) {
sc_dhkey_check ( smp ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_DHKEY_CHECK ) ;
} else if ( test_and_clear_bit ( SMP_FLAG_DHKEY_PENDING , & smp - > flags ) ) {
sc_dhkey_check ( smp ) ;
sc_add_ltk ( smp ) ;
}
2014-06-06 12:44:05 +04:00
return 0 ;
}
2011-12-22 04:12:12 +04:00
int smp_user_confirm_reply ( struct hci_conn * hcon , u16 mgmt_op , __le32 passkey )
{
2014-06-27 15:23:07 +04:00
struct l2cap_conn * conn = hcon - > l2cap_data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan ;
2011-12-22 04:12:12 +04:00
struct smp_chan * smp ;
u32 value ;
2014-09-05 23:19:52 +04:00
int err ;
2011-12-22 04:12:12 +04:00
BT_DBG ( " " ) ;
2014-09-05 23:19:52 +04:00
if ( ! conn )
2011-12-22 04:12:12 +04:00
return - ENOTCONN ;
2014-08-08 10:37:18 +04:00
chan = conn - > smp ;
if ( ! chan )
return - ENOTCONN ;
2014-09-05 23:19:52 +04:00
l2cap_chan_lock ( chan ) ;
if ( ! chan - > data ) {
err = - ENOTCONN ;
goto unlock ;
}
2014-08-08 10:37:18 +04:00
smp = chan - > data ;
2011-12-22 04:12:12 +04:00
2014-06-06 12:44:05 +04:00
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) ) {
err = sc_user_reply ( smp , mgmt_op , passkey ) ;
goto unlock ;
}
2011-12-22 04:12:12 +04:00
switch ( mgmt_op ) {
case MGMT_OP_USER_PASSKEY_REPLY :
value = le32_to_cpu ( passkey ) ;
2014-03-18 14:58:24 +04:00
memset ( smp - > tk , 0 , sizeof ( smp - > tk ) ) ;
2011-12-22 04:12:12 +04:00
BT_DBG ( " PassKey: %d " , value ) ;
2014-03-18 14:58:24 +04:00
put_unaligned_le32 ( value , smp - > tk ) ;
2011-12-22 04:12:12 +04:00
/* Fall Through */
case MGMT_OP_USER_CONFIRM_REPLY :
2014-05-20 10:45:50 +04:00
set_bit ( SMP_FLAG_TK_VALID , & smp - > flags ) ;
2011-12-22 04:12:12 +04:00
break ;
case MGMT_OP_USER_PASSKEY_NEG_REPLY :
case MGMT_OP_USER_CONFIRM_NEG_REPLY :
2013-11-06 13:24:57 +04:00
smp_failure ( conn , SMP_PASSKEY_ENTRY_FAILED ) ;
2014-09-05 23:19:52 +04:00
err = 0 ;
goto unlock ;
2011-12-22 04:12:12 +04:00
default :
2013-11-06 13:24:57 +04:00
smp_failure ( conn , SMP_PASSKEY_ENTRY_FAILED ) ;
2014-09-05 23:19:52 +04:00
err = - EOPNOTSUPP ;
goto unlock ;
2011-12-22 04:12:12 +04:00
}
2014-09-05 23:19:52 +04:00
err = 0 ;
2011-12-22 04:12:12 +04:00
/* If it is our turn to send Pairing Confirm, do so now */
2014-05-20 10:45:52 +04:00
if ( test_bit ( SMP_FLAG_CFM_PENDING , & smp - > flags ) ) {
u8 rsp = smp_confirm ( smp ) ;
if ( rsp )
smp_failure ( conn , rsp ) ;
}
2011-12-22 04:12:12 +04:00
2014-09-05 23:19:52 +04:00
unlock :
l2cap_chan_unlock ( chan ) ;
return err ;
2011-12-22 04:12:12 +04:00
}
2014-08-14 13:34:26 +04:00
static void build_bredr_pairing_cmd ( struct smp_chan * smp ,
struct smp_cmd_pairing * req ,
struct smp_cmd_pairing * rsp )
{
struct l2cap_conn * conn = smp - > conn ;
struct hci_dev * hdev = conn - > hcon - > hdev ;
u8 local_dist = 0 , remote_dist = 0 ;
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_BONDABLE ) ) {
2014-08-14 13:34:26 +04:00
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN ;
remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN ;
}
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_RPA_RESOLVING ) )
2014-08-14 13:34:26 +04:00
remote_dist | = SMP_DIST_ID_KEY ;
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_PRIVACY ) )
2014-08-14 13:34:26 +04:00
local_dist | = SMP_DIST_ID_KEY ;
if ( ! rsp ) {
memset ( req , 0 , sizeof ( * req ) ) ;
req - > init_key_dist = local_dist ;
req - > resp_key_dist = remote_dist ;
2015-06-11 13:52:30 +03:00
req - > max_key_size = conn - > hcon - > enc_key_size ;
2014-08-14 13:34:26 +04:00
smp - > remote_key_dist = remote_dist ;
return ;
}
memset ( rsp , 0 , sizeof ( * rsp ) ) ;
2015-06-11 13:52:30 +03:00
rsp - > max_key_size = conn - > hcon - > enc_key_size ;
2014-08-14 13:34:26 +04:00
rsp - > init_key_dist = req - > init_key_dist & remote_dist ;
rsp - > resp_key_dist = req - > resp_key_dist & local_dist ;
smp - > remote_key_dist = rsp - > init_key_dist ;
}
2011-06-10 01:50:53 +04:00
static u8 smp_cmd_pairing_req ( struct l2cap_conn * conn , struct sk_buff * skb )
2011-06-10 01:50:42 +04:00
{
2011-06-14 20:37:42 +04:00
struct smp_cmd_pairing rsp , * req = ( void * ) skb - > data ;
2014-09-05 23:19:52 +04:00
struct l2cap_chan * chan = conn - > smp ;
2014-07-10 12:02:07 +04:00
struct hci_dev * hdev = conn - > hcon - > hdev ;
2011-09-05 21:31:31 +04:00
struct smp_chan * smp ;
2014-06-17 14:07:37 +04:00
u8 key_size , auth , sec_level ;
2011-09-05 21:31:31 +04:00
int ret ;
2011-06-10 01:50:42 +04:00
BT_DBG ( " conn %p " , conn ) ;
2014-02-18 12:19:29 +04:00
if ( skb - > len < sizeof ( * req ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2014-07-16 12:42:27 +04:00
if ( conn - > hcon - > role ! = HCI_ROLE_SLAVE )
2011-12-22 04:12:12 +04:00
return SMP_CMD_NOTSUPP ;
2014-09-05 23:19:52 +04:00
if ( ! chan - > data )
2011-09-05 21:31:31 +04:00
smp = smp_chan_create ( conn ) ;
2014-09-05 23:19:52 +04:00
else
2014-08-08 10:37:18 +04:00
smp = chan - > data ;
2011-09-05 21:31:31 +04:00
2012-07-19 18:03:43 +04:00
if ( ! smp )
return SMP_UNSPECIFIED ;
2011-08-20 04:06:51 +04:00
2014-09-11 04:37:42 +04:00
/* We didn't start the pairing, so match remote */
2014-05-26 14:29:28 +04:00
auth = req - > auth_req & AUTH_REQ_MASK ( hdev ) ;
2014-09-11 04:37:42 +04:00
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hdev , HCI_BONDABLE ) & &
2014-09-11 04:37:42 +04:00
( auth & SMP_AUTH_BONDING ) )
2014-07-10 12:02:07 +04:00
return SMP_PAIRING_NOTSUPP ;
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_SC_ONLY ) & & ! ( auth & SMP_AUTH_SC ) )
2014-09-09 03:59:18 +04:00
return SMP_AUTH_REQUIREMENTS ;
2011-09-05 21:31:30 +04:00
smp - > preq [ 0 ] = SMP_CMD_PAIRING_REQ ;
memcpy ( & smp - > preq [ 1 ] , req , sizeof ( * req ) ) ;
2011-06-14 20:37:42 +04:00
skb_pull ( skb , sizeof ( * req ) ) ;
2011-06-10 01:50:42 +04:00
2015-03-16 22:12:34 +03:00
/* If the remote side's OOB flag is set it means it has
* successfully received our local OOB data - therefore set the
* flag to indicate that local OOB is in use .
*/
2015-03-16 12:45:45 +03:00
if ( req - > oob_flag = = SMP_OOB_PRESENT )
set_bit ( SMP_FLAG_LOCAL_OOB , & smp - > flags ) ;
2014-08-14 13:34:26 +04:00
/* SMP over BR/EDR requires special treatment */
if ( conn - > hcon - > type = = ACL_LINK ) {
/* We must have a BR/EDR SC link */
2014-12-07 18:19:12 +03:00
if ( ! test_bit ( HCI_CONN_AES_CCM , & conn - > hcon - > flags ) & &
2015-03-13 20:20:35 +03:00
! hci_dev_test_flag ( hdev , HCI_FORCE_BREDR_SMP ) )
2014-08-14 13:34:26 +04:00
return SMP_CROSS_TRANSP_NOT_ALLOWED ;
set_bit ( SMP_FLAG_SC , & smp - > flags ) ;
build_bredr_pairing_cmd ( smp , req , & rsp ) ;
key_size = min ( req - > max_key_size , rsp . max_key_size ) ;
if ( check_enc_key_size ( conn , key_size ) )
return SMP_ENC_KEY_SIZE ;
/* Clear bits which are generated but not distributed */
smp - > remote_key_dist & = ~ SMP_SC_NO_DIST ;
smp - > prsp [ 0 ] = SMP_CMD_PAIRING_RSP ;
memcpy ( & smp - > prsp [ 1 ] , & rsp , sizeof ( rsp ) ) ;
smp_send_cmd ( conn , SMP_CMD_PAIRING_RSP , sizeof ( rsp ) , & rsp ) ;
smp_distribute_keys ( smp ) ;
return 0 ;
}
2014-05-31 19:51:02 +04:00
build_pairing_cmd ( conn , req , & rsp , auth ) ;
if ( rsp . auth_req & SMP_AUTH_SC )
set_bit ( SMP_FLAG_SC , & smp - > flags ) ;
2014-09-11 04:58:54 +04:00
if ( conn - > hcon - > io_capability = = HCI_IO_NO_INPUT_OUTPUT )
2014-09-11 04:37:44 +04:00
sec_level = BT_SECURITY_MEDIUM ;
else
sec_level = authreq_to_seclevel ( auth ) ;
2014-06-17 14:07:37 +04:00
if ( sec_level > conn - > hcon - > pending_sec_level )
conn - > hcon - > pending_sec_level = sec_level ;
2012-03-05 22:09:38 +04:00
2014-10-28 07:12:20 +03:00
/* If we need MITM check that it can be achieved */
2014-06-17 14:07:39 +04:00
if ( conn - > hcon - > pending_sec_level > = BT_SECURITY_HIGH ) {
u8 method ;
method = get_auth_method ( smp , conn - > hcon - > io_capability ,
req - > io_capability ) ;
if ( method = = JUST_WORKS | | method = = JUST_CFM )
return SMP_AUTH_REQUIREMENTS ;
}
2011-06-14 20:37:42 +04:00
key_size = min ( req - > max_key_size , rsp . max_key_size ) ;
if ( check_enc_key_size ( conn , key_size ) )
return SMP_ENC_KEY_SIZE ;
2011-06-10 01:50:42 +04:00
2013-12-02 12:49:03 +04:00
get_random_bytes ( smp - > prnd , sizeof ( smp - > prnd ) ) ;
2011-09-05 21:31:31 +04:00
2011-09-05 21:31:30 +04:00
smp - > prsp [ 0 ] = SMP_CMD_PAIRING_RSP ;
memcpy ( & smp - > prsp [ 1 ] , & rsp , sizeof ( rsp ) ) ;
2011-06-10 01:50:45 +04:00
2011-06-14 20:37:42 +04:00
smp_send_cmd ( conn , SMP_CMD_PAIRING_RSP , sizeof ( rsp ) , & rsp ) ;
2014-06-06 11:50:15 +04:00
clear_bit ( SMP_FLAG_INITIATOR , & smp - > flags ) ;
Bluetooth: Add workaround for broken OS X legacy SMP pairing
OS X version 10.10.2 (and possibly older versions) doesn't support LE
Secure Connections but incorrectly copies all authentication request
bits from a Security Request to its Pairing Request. The result is that
an SC capable initiator (such as BlueZ) will think OS X intends to do SC
when in fact it's incapable of it:
< ACL Data TX: Handle 3585 flags 0x00 dlen 6
SMP: Security Request (0x0b) len 1
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
> ACL Data RX: Handle 3585 flags 0x02 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey IdKey Sign (0x07)
< ACL Data TX: Handle 3585 flags 0x00 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey Sign (0x05)
The pairing eventually fails when we get an unexpected Pairing Confirm
PDU instead of a Public Key PDU:
> ACL Data RX: Handle 3585 flags 0x02 dlen 21
SMP: Pairing Confirm (0x03) len 16
Confim value: bcc3bed31b8f313a78ec3cce32685faf
It is only at this point that we can speculate that the remote doesn't
really support SC. This patch creates a workaround for the just-works
model, however the MITM case is unsolvable because the OS X user has
already been requested to enter a PIN which we're now expected to
randomly generate and show the user (i.e. a chicken-and-egg problem).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-03-15 20:34:04 +03:00
/* Strictly speaking we shouldn't allow Pairing Confirm for the
* SC case , however some implementations incorrectly copy RFU auth
* req bits from our security request , which may create a false
* positive SC enablement .
*/
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
2014-06-06 11:50:15 +04:00
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) ) {
SMP_ALLOW_CMD ( smp , SMP_CMD_PUBLIC_KEY ) ;
/* Clear bits which are generated but not distributed */
smp - > remote_key_dist & = ~ SMP_SC_NO_DIST ;
/* Wait for Public Key from Initiating Device */
return 0 ;
}
2011-06-10 01:50:53 +04:00
2011-12-22 04:12:12 +04:00
/* Request setup of TK */
ret = tk_request ( conn , 0 , auth , rsp . io_capability , req - > io_capability ) ;
if ( ret )
return SMP_UNSPECIFIED ;
2011-06-10 01:50:53 +04:00
return 0 ;
2011-06-10 01:50:42 +04:00
}
2014-06-06 11:50:15 +04:00
static u8 sc_send_public_key ( struct smp_chan * smp )
{
2014-06-24 16:22:59 +04:00
struct hci_dev * hdev = smp - > conn - > hcon - > hdev ;
2014-06-06 11:50:15 +04:00
BT_DBG ( " " ) ;
2015-03-16 12:45:44 +03:00
if ( test_bit ( SMP_FLAG_LOCAL_OOB , & smp - > flags ) ) {
2015-03-16 11:10:24 +03:00
struct l2cap_chan * chan = hdev - > smp_data ;
struct smp_dev * smp_dev ;
if ( ! chan | | ! chan - > data )
return SMP_UNSPECIFIED ;
smp_dev = chan - > data ;
memcpy ( smp - > local_pk , smp_dev - > local_pk , 64 ) ;
memcpy ( smp - > local_sk , smp_dev - > local_sk , 32 ) ;
2015-03-16 22:34:57 +03:00
memcpy ( smp - > lr , smp_dev - > local_rand , 16 ) ;
2015-03-16 11:10:24 +03:00
if ( smp_dev - > debug_key )
set_bit ( SMP_FLAG_DEBUG_KEY , & smp - > flags ) ;
goto done ;
}
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_USE_DEBUG_KEYS ) ) {
2014-06-24 16:22:59 +04:00
BT_DBG ( " Using debug keys " ) ;
memcpy ( smp - > local_pk , debug_pk , 64 ) ;
memcpy ( smp - > local_sk , debug_sk , 32 ) ;
set_bit ( SMP_FLAG_DEBUG_KEY , & smp - > flags ) ;
} else {
while ( true ) {
/* Generate local key pair for Secure Connections */
if ( ! ecc_make_key ( smp - > local_pk , smp - > local_sk ) )
return SMP_UNSPECIFIED ;
2014-06-06 16:33:30 +04:00
2014-06-24 16:22:59 +04:00
/* This is unlikely, but we need to check that
* we didn ' t accidentially generate a debug key .
*/
if ( memcmp ( smp - > local_sk , debug_sk , 32 ) )
break ;
}
2014-06-06 16:33:30 +04:00
}
2014-06-06 11:50:15 +04:00
2015-03-16 11:10:24 +03:00
done :
2014-12-01 23:03:16 +03:00
SMP_DBG ( " Local Public Key X: %32phN " , smp - > local_pk ) ;
2015-03-16 11:10:25 +03:00
SMP_DBG ( " Local Public Key Y: %32phN " , smp - > local_pk + 32 ) ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " Local Private Key: %32phN " , smp - > local_sk ) ;
2014-06-06 11:50:15 +04:00
smp_send_cmd ( smp - > conn , SMP_CMD_PUBLIC_KEY , 64 , smp - > local_pk ) ;
return 0 ;
}
2011-06-10 01:50:53 +04:00
static u8 smp_cmd_pairing_rsp ( struct l2cap_conn * conn , struct sk_buff * skb )
2011-06-10 01:50:42 +04:00
{
2011-06-14 20:37:42 +04:00
struct smp_cmd_pairing * req , * rsp = ( void * ) skb - > data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-05-26 14:29:28 +04:00
struct hci_dev * hdev = conn - > hcon - > hdev ;
2014-09-11 04:37:41 +04:00
u8 key_size , auth ;
2011-06-10 01:50:46 +04:00
int ret ;
2011-06-10 01:50:42 +04:00
BT_DBG ( " conn %p " , conn ) ;
2014-02-18 12:19:29 +04:00
if ( skb - > len < sizeof ( * rsp ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2014-07-16 12:42:27 +04:00
if ( conn - > hcon - > role ! = HCI_ROLE_MASTER )
2011-12-22 04:12:12 +04:00
return SMP_CMD_NOTSUPP ;
2011-06-14 20:37:42 +04:00
skb_pull ( skb , sizeof ( * rsp ) ) ;
2011-09-05 21:31:30 +04:00
req = ( void * ) & smp - > preq [ 1 ] ;
2011-06-10 01:50:53 +04:00
2011-06-14 20:37:42 +04:00
key_size = min ( req - > max_key_size , rsp - > max_key_size ) ;
if ( check_enc_key_size ( conn , key_size ) )
return SMP_ENC_KEY_SIZE ;
2014-05-26 14:29:28 +04:00
auth = rsp - > auth_req & AUTH_REQ_MASK ( hdev ) ;
2014-09-11 04:37:42 +04:00
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_SC_ONLY ) & & ! ( auth & SMP_AUTH_SC ) )
2014-09-09 03:59:18 +04:00
return SMP_AUTH_REQUIREMENTS ;
2015-03-16 22:12:34 +03:00
/* If the remote side's OOB flag is set it means it has
* successfully received our local OOB data - therefore set the
* flag to indicate that local OOB is in use .
*/
2015-03-16 12:45:45 +03:00
if ( rsp - > oob_flag = = SMP_OOB_PRESENT )
set_bit ( SMP_FLAG_LOCAL_OOB , & smp - > flags ) ;
2014-08-14 13:34:26 +04:00
smp - > prsp [ 0 ] = SMP_CMD_PAIRING_RSP ;
memcpy ( & smp - > prsp [ 1 ] , rsp , sizeof ( * rsp ) ) ;
/* Update remote key distribution in case the remote cleared
* some bits that we had enabled in our request .
*/
smp - > remote_key_dist & = rsp - > resp_key_dist ;
/* For BR/EDR this means we're done and can start phase 3 */
if ( conn - > hcon - > type = = ACL_LINK ) {
/* Clear bits which are generated but not distributed */
smp - > remote_key_dist & = ~ SMP_SC_NO_DIST ;
smp_distribute_keys ( smp ) ;
return 0 ;
}
2014-05-16 12:03:34 +04:00
if ( ( req - > auth_req & SMP_AUTH_SC ) & & ( auth & SMP_AUTH_SC ) )
set_bit ( SMP_FLAG_SC , & smp - > flags ) ;
2014-05-16 11:59:06 +04:00
else if ( conn - > hcon - > pending_sec_level > BT_SECURITY_HIGH )
conn - > hcon - > pending_sec_level = BT_SECURITY_HIGH ;
2014-05-16 12:03:34 +04:00
2014-10-28 07:12:20 +03:00
/* If we need MITM check that it can be achieved */
2014-06-17 14:07:39 +04:00
if ( conn - > hcon - > pending_sec_level > = BT_SECURITY_HIGH ) {
u8 method ;
method = get_auth_method ( smp , req - > io_capability ,
rsp - > io_capability ) ;
if ( method = = JUST_WORKS | | method = = JUST_CFM )
return SMP_AUTH_REQUIREMENTS ;
}
2013-12-02 12:49:03 +04:00
get_random_bytes ( smp - > prnd , sizeof ( smp - > prnd ) ) ;
2011-06-10 01:50:46 +04:00
2014-03-14 12:53:50 +04:00
/* Update remote key distribution in case the remote cleared
* some bits that we had enabled in our request .
*/
smp - > remote_key_dist & = rsp - > resp_key_dist ;
2014-06-06 11:50:15 +04:00
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) ) {
/* Clear bits which are generated but not distributed */
smp - > remote_key_dist & = ~ SMP_SC_NO_DIST ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PUBLIC_KEY ) ;
return sc_send_public_key ( smp ) ;
}
2014-09-11 04:37:42 +04:00
auth | = req - > auth_req ;
2011-12-22 04:12:12 +04:00
2012-06-06 14:54:15 +04:00
ret = tk_request ( conn , 0 , auth , req - > io_capability , rsp - > io_capability ) ;
2011-12-22 04:12:12 +04:00
if ( ret )
return SMP_UNSPECIFIED ;
2014-05-20 10:45:50 +04:00
set_bit ( SMP_FLAG_CFM_PENDING , & smp - > flags ) ;
2011-12-22 04:12:12 +04:00
/* Can't compose response until we have been confirmed */
2014-05-20 10:45:50 +04:00
if ( test_bit ( SMP_FLAG_TK_VALID , & smp - > flags ) )
2014-05-20 10:45:52 +04:00
return smp_confirm ( smp ) ;
2011-06-10 01:50:53 +04:00
return 0 ;
2011-06-10 01:50:42 +04:00
}
2014-06-06 12:36:38 +04:00
static u8 sc_check_confirm ( struct smp_chan * smp )
{
struct l2cap_conn * conn = smp - > conn ;
BT_DBG ( " " ) ;
2014-06-25 12:10:28 +04:00
if ( smp - > method = = REQ_PASSKEY | | smp - > method = = DSP_PASSKEY )
return sc_passkey_round ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
2014-06-06 12:36:38 +04:00
if ( conn - > hcon - > out ) {
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM , sizeof ( smp - > prnd ) ,
smp - > prnd ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RANDOM ) ;
}
return 0 ;
}
Bluetooth: Add workaround for broken OS X legacy SMP pairing
OS X version 10.10.2 (and possibly older versions) doesn't support LE
Secure Connections but incorrectly copies all authentication request
bits from a Security Request to its Pairing Request. The result is that
an SC capable initiator (such as BlueZ) will think OS X intends to do SC
when in fact it's incapable of it:
< ACL Data TX: Handle 3585 flags 0x00 dlen 6
SMP: Security Request (0x0b) len 1
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
> ACL Data RX: Handle 3585 flags 0x02 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey IdKey Sign (0x07)
< ACL Data TX: Handle 3585 flags 0x00 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey Sign (0x05)
The pairing eventually fails when we get an unexpected Pairing Confirm
PDU instead of a Public Key PDU:
> ACL Data RX: Handle 3585 flags 0x02 dlen 21
SMP: Pairing Confirm (0x03) len 16
Confim value: bcc3bed31b8f313a78ec3cce32685faf
It is only at this point that we can speculate that the remote doesn't
really support SC. This patch creates a workaround for the just-works
model, however the MITM case is unsolvable because the OS X user has
already been requested to enter a PIN which we're now expected to
randomly generate and show the user (i.e. a chicken-and-egg problem).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-03-15 20:34:04 +03:00
/* Work-around for some implementations that incorrectly copy RFU bits
* from our security request and thereby create the impression that
* we ' re doing SC when in fact the remote doesn ' t support it .
*/
static int fixup_sc_false_positive ( struct smp_chan * smp )
{
struct l2cap_conn * conn = smp - > conn ;
struct hci_conn * hcon = conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
struct smp_cmd_pairing * req , * rsp ;
u8 auth ;
/* The issue is only observed when we're in slave role */
if ( hcon - > out )
return SMP_UNSPECIFIED ;
if ( hci_dev_test_flag ( hdev , HCI_SC_ONLY ) ) {
BT_ERR ( " Refusing SMP SC -> legacy fallback in SC-only mode " ) ;
return SMP_UNSPECIFIED ;
}
BT_ERR ( " Trying to fall back to legacy SMP " ) ;
req = ( void * ) & smp - > preq [ 1 ] ;
rsp = ( void * ) & smp - > prsp [ 1 ] ;
/* Rebuild key dist flags which may have been cleared for SC */
smp - > remote_key_dist = ( req - > init_key_dist & rsp - > resp_key_dist ) ;
auth = req - > auth_req & AUTH_REQ_MASK ( hdev ) ;
if ( tk_request ( conn , 0 , auth , rsp - > io_capability , req - > io_capability ) ) {
BT_ERR ( " Failed to fall back to legacy SMP " ) ;
return SMP_UNSPECIFIED ;
}
clear_bit ( SMP_FLAG_SC , & smp - > flags ) ;
return 0 ;
}
2011-06-10 01:50:53 +04:00
static u8 smp_cmd_pairing_confirm ( struct l2cap_conn * conn , struct sk_buff * skb )
2011-06-10 01:50:42 +04:00
{
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2011-06-10 01:50:46 +04:00
2011-06-10 01:50:42 +04:00
BT_DBG ( " conn %p %s " , conn , conn - > hcon - > out ? " master " : " slave " ) ;
2014-02-18 12:19:29 +04:00
if ( skb - > len < sizeof ( smp - > pcnf ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2011-09-05 21:31:30 +04:00
memcpy ( smp - > pcnf , skb - > data , sizeof ( smp - > pcnf ) ) ;
skb_pull ( skb , sizeof ( smp - > pcnf ) ) ;
2011-06-10 01:50:42 +04:00
Bluetooth: Add workaround for broken OS X legacy SMP pairing
OS X version 10.10.2 (and possibly older versions) doesn't support LE
Secure Connections but incorrectly copies all authentication request
bits from a Security Request to its Pairing Request. The result is that
an SC capable initiator (such as BlueZ) will think OS X intends to do SC
when in fact it's incapable of it:
< ACL Data TX: Handle 3585 flags 0x00 dlen 6
SMP: Security Request (0x0b) len 1
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
> ACL Data RX: Handle 3585 flags 0x02 dlen 11
SMP: Pairing Request (0x01) len 6
IO capability: KeyboardDisplay (0x04)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey IdKey Sign (0x07)
< ACL Data TX: Handle 3585 flags 0x00 dlen 11
SMP: Pairing Response (0x02) len 6
IO capability: NoInputNoOutput (0x03)
OOB data: Authentication data not present (0x00)
Authentication requirement: Bonding, No MITM, SC, No Keypresses (0x09)
Max encryption key size: 16
Initiator key distribution: EncKey (0x01)
Responder key distribution: EncKey Sign (0x05)
The pairing eventually fails when we get an unexpected Pairing Confirm
PDU instead of a Public Key PDU:
> ACL Data RX: Handle 3585 flags 0x02 dlen 21
SMP: Pairing Confirm (0x03) len 16
Confim value: bcc3bed31b8f313a78ec3cce32685faf
It is only at this point that we can speculate that the remote doesn't
really support SC. This patch creates a workaround for the just-works
model, however the MITM case is unsolvable because the OS X user has
already been requested to enter a PIN which we're now expected to
randomly generate and show the user (i.e. a chicken-and-egg problem).
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-03-15 20:34:04 +03:00
if ( test_bit ( SMP_FLAG_SC , & smp - > flags ) ) {
int ret ;
/* Public Key exchange must happen before any other steps */
if ( test_bit ( SMP_FLAG_REMOTE_PK , & smp - > flags ) )
return sc_check_confirm ( smp ) ;
BT_ERR ( " Unexpected SMP Pairing Confirm " ) ;
ret = fixup_sc_false_positive ( smp ) ;
if ( ret )
return ret ;
}
2014-06-06 12:36:38 +04:00
2014-09-05 23:19:55 +04:00
if ( conn - > hcon - > out ) {
2014-03-18 14:58:24 +04:00
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM , sizeof ( smp - > prnd ) ,
smp - > prnd ) ;
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RANDOM ) ;
return 0 ;
}
if ( test_bit ( SMP_FLAG_TK_VALID , & smp - > flags ) )
2014-05-20 10:45:52 +04:00
return smp_confirm ( smp ) ;
2015-03-12 03:47:40 +03:00
set_bit ( SMP_FLAG_CFM_PENDING , & smp - > flags ) ;
2011-06-10 01:50:53 +04:00
return 0 ;
2011-06-10 01:50:42 +04:00
}
2011-06-10 01:50:53 +04:00
static u8 smp_cmd_pairing_random ( struct l2cap_conn * conn , struct sk_buff * skb )
2011-06-10 01:50:42 +04:00
{
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-06-06 12:39:49 +04:00
struct hci_conn * hcon = conn - > hcon ;
u8 * pkax , * pkbx , * na , * nb ;
u32 passkey ;
int err ;
2011-06-10 01:50:46 +04:00
2011-09-05 21:31:31 +04:00
BT_DBG ( " conn %p " , conn ) ;
2011-06-14 20:37:42 +04:00
2014-02-18 12:19:29 +04:00
if ( skb - > len < sizeof ( smp - > rrnd ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2014-03-18 14:58:24 +04:00
memcpy ( smp - > rrnd , skb - > data , sizeof ( smp - > rrnd ) ) ;
2011-09-05 21:31:31 +04:00
skb_pull ( skb , sizeof ( smp - > rrnd ) ) ;
2011-07-08 01:59:40 +04:00
2014-06-06 12:39:49 +04:00
if ( ! test_bit ( SMP_FLAG_SC , & smp - > flags ) )
return smp_random ( smp ) ;
Bluetooth: Fix false-positive "uninitialized" compiler warning
Some gcc versions don't seem to be able to properly track the flow of
the smp_cmd_pairing_random() function and end up causing the following
types of (false-positive) warnings:
smp.c:1995:6: warning: ‘nb’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
smp.c:1995:6: warning: ‘na’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
^
smp.c:1995:6: warning: ‘pkbx’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
^
smp.c:1995:6: warning: ‘pkax’ may be used uninitialized in this function [-Wmaybe-uninitialized]
err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
This patch fixes the issue by moving the pkax/pkbx and na/nb
initialization earlier in the function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-12-03 17:26:37 +03:00
if ( hcon - > out ) {
pkax = smp - > local_pk ;
pkbx = smp - > remote_pk ;
na = smp - > prnd ;
nb = smp - > rrnd ;
} else {
pkax = smp - > remote_pk ;
pkbx = smp - > local_pk ;
na = smp - > rrnd ;
nb = smp - > prnd ;
}
2014-10-28 17:17:05 +03:00
if ( smp - > method = = REQ_OOB ) {
if ( ! hcon - > out )
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM ,
sizeof ( smp - > prnd ) , smp - > prnd ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_DHKEY_CHECK ) ;
goto mackey_and_ltk ;
}
2014-06-25 12:10:28 +04:00
/* Passkey entry has special treatment */
if ( smp - > method = = REQ_PASSKEY | | smp - > method = = DSP_PASSKEY )
return sc_passkey_round ( smp , SMP_CMD_PAIRING_RANDOM ) ;
2014-06-06 12:39:49 +04:00
if ( hcon - > out ) {
u8 cfm [ 16 ] ;
err = smp_f4 ( smp - > tfm_cmac , smp - > remote_pk , smp - > local_pk ,
smp - > rrnd , 0 , cfm ) ;
if ( err )
return SMP_UNSPECIFIED ;
if ( memcmp ( smp - > pcnf , cfm , 16 ) )
return SMP_CONFIRM_FAILED ;
} else {
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM , sizeof ( smp - > prnd ) ,
smp - > prnd ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_DHKEY_CHECK ) ;
}
2014-10-28 17:17:05 +03:00
mackey_and_ltk :
2014-06-06 12:44:05 +04:00
/* Generate MacKey and LTK */
err = sc_mackey_and_ltk ( smp , smp - > mackey , smp - > tk ) ;
if ( err )
return SMP_UNSPECIFIED ;
2014-10-28 17:17:05 +03:00
if ( smp - > method = = JUST_WORKS | | smp - > method = = REQ_OOB ) {
2014-06-01 16:38:09 +04:00
if ( hcon - > out ) {
2014-06-25 12:10:28 +04:00
sc_dhkey_check ( smp ) ;
2014-06-01 16:38:09 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_DHKEY_CHECK ) ;
}
return 0 ;
}
2014-06-25 12:10:28 +04:00
err = smp_g2 ( smp - > tfm_cmac , pkax , pkbx , na , nb , & passkey ) ;
if ( err )
return SMP_UNSPECIFIED ;
err = mgmt_user_confirm_request ( hcon - > hdev , & hcon - > dst , hcon - > type ,
hcon - > dst_type , passkey , 0 ) ;
2014-06-06 12:39:49 +04:00
if ( err )
return SMP_UNSPECIFIED ;
2014-06-25 12:10:28 +04:00
set_bit ( SMP_FLAG_WAIT_USER , & smp - > flags ) ;
2014-06-06 12:39:49 +04:00
return 0 ;
2011-06-10 01:50:42 +04:00
}
2014-07-01 12:59:24 +04:00
static bool smp_ltk_encrypt ( struct l2cap_conn * conn , u8 sec_level )
2011-08-26 03:02:28 +04:00
{
2012-02-03 04:08:01 +04:00
struct smp_ltk * key ;
2011-08-26 03:02:28 +04:00
struct hci_conn * hcon = conn - > hcon ;
2014-05-29 16:02:59 +04:00
key = hci_find_ltk ( hcon - > hdev , & hcon - > dst , hcon - > dst_type , hcon - > role ) ;
2011-08-26 03:02:28 +04:00
if ( ! key )
2014-07-01 12:59:24 +04:00
return false ;
2011-08-26 03:02:28 +04:00
2014-09-11 04:37:45 +04:00
if ( smp_ltk_sec_level ( key ) < sec_level )
2014-07-01 12:59:24 +04:00
return false ;
2012-06-07 10:58:37 +04:00
2012-01-16 08:10:31 +04:00
if ( test_and_set_bit ( HCI_CONN_ENCRYPT_PEND , & hcon - > flags ) )
2014-07-01 12:59:24 +04:00
return true ;
2011-08-26 03:02:28 +04:00
2015-06-08 18:14:39 +03:00
hci_le_start_enc ( hcon , key - > ediv , key - > rand , key - > val , key - > enc_size ) ;
2012-02-03 04:08:01 +04:00
hcon - > enc_key_size = key - > enc_size ;
2011-08-26 03:02:28 +04:00
2014-07-01 20:14:12 +04:00
/* We never store STKs for master role, so clear this flag */
clear_bit ( HCI_CONN_STK_ENCRYPT , & hcon - > flags ) ;
2014-07-01 12:59:24 +04:00
return true ;
2011-08-26 03:02:28 +04:00
}
2013-10-13 16:43:25 +04:00
2014-11-13 11:55:18 +03:00
bool smp_sufficient_security ( struct hci_conn * hcon , u8 sec_level ,
enum smp_key_pref key_pref )
2014-07-01 19:40:20 +04:00
{
if ( sec_level = = BT_SECURITY_LOW )
return true ;
2014-11-13 11:55:18 +03:00
/* If we're encrypted with an STK but the caller prefers using
* LTK claim insufficient security . This way we allow the
* connection to be re - encrypted with an LTK , even if the LTK
* provides the same level of security . Only exception is if we
* don ' t have an LTK ( e . g . because of key distribution bits ) .
2014-07-01 20:14:13 +04:00
*/
2014-11-13 11:55:18 +03:00
if ( key_pref = = SMP_USE_LTK & &
test_bit ( HCI_CONN_STK_ENCRYPT , & hcon - > flags ) & &
2014-05-29 16:02:59 +04:00
hci_find_ltk ( hcon - > hdev , & hcon - > dst , hcon - > dst_type , hcon - > role ) )
2014-07-01 20:14:13 +04:00
return false ;
2014-07-01 19:40:20 +04:00
if ( hcon - > sec_level > = sec_level )
return true ;
return false ;
}
2011-06-10 01:50:53 +04:00
static u8 smp_cmd_security_req ( struct l2cap_conn * conn , struct sk_buff * skb )
2011-06-10 01:50:42 +04:00
{
struct smp_cmd_security_req * rp = ( void * ) skb - > data ;
struct smp_cmd_pairing cp ;
2011-01-27 03:42:57 +03:00
struct hci_conn * hcon = conn - > hcon ;
2014-05-26 14:29:28 +04:00
struct hci_dev * hdev = hcon - > hdev ;
2011-09-05 21:31:31 +04:00
struct smp_chan * smp ;
2014-09-11 04:37:42 +04:00
u8 sec_level , auth ;
2011-06-10 01:50:42 +04:00
BT_DBG ( " conn %p " , conn ) ;
2014-02-18 12:19:29 +04:00
if ( skb - > len < sizeof ( * rp ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2014-07-16 12:42:27 +04:00
if ( hcon - > role ! = HCI_ROLE_MASTER )
2013-11-05 13:30:39 +04:00
return SMP_CMD_NOTSUPP ;
2014-05-26 14:29:28 +04:00
auth = rp - > auth_req & AUTH_REQ_MASK ( hdev ) ;
2014-09-11 04:37:42 +04:00
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hdev , HCI_SC_ONLY ) & & ! ( auth & SMP_AUTH_SC ) )
2014-09-09 03:59:18 +04:00
return SMP_AUTH_REQUIREMENTS ;
2014-09-11 04:58:54 +04:00
if ( hcon - > io_capability = = HCI_IO_NO_INPUT_OUTPUT )
2014-09-11 04:37:44 +04:00
sec_level = BT_SECURITY_MEDIUM ;
else
sec_level = authreq_to_seclevel ( auth ) ;
2014-11-13 11:55:18 +03:00
if ( smp_sufficient_security ( hcon , sec_level , SMP_USE_LTK ) )
2014-07-01 19:40:20 +04:00
return 0 ;
2014-06-17 14:07:37 +04:00
if ( sec_level > hcon - > pending_sec_level )
hcon - > pending_sec_level = sec_level ;
2011-08-26 03:02:35 +04:00
2012-06-07 10:58:37 +04:00
if ( smp_ltk_encrypt ( conn , hcon - > pending_sec_level ) )
2011-08-26 03:02:28 +04:00
return 0 ;
2011-09-05 21:31:31 +04:00
smp = smp_chan_create ( conn ) ;
2014-06-16 20:25:14 +04:00
if ( ! smp )
return SMP_UNSPECIFIED ;
2011-08-20 04:06:51 +04:00
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hdev , HCI_BONDABLE ) & &
2014-09-11 04:37:42 +04:00
( auth & SMP_AUTH_BONDING ) )
2014-07-29 15:18:48 +04:00
return SMP_PAIRING_NOTSUPP ;
2011-06-10 01:50:42 +04:00
skb_pull ( skb , sizeof ( * rp ) ) ;
2011-06-10 01:50:53 +04:00
memset ( & cp , 0 , sizeof ( cp ) ) ;
2014-09-11 04:37:42 +04:00
build_pairing_cmd ( conn , & cp , NULL , auth ) ;
2011-06-10 01:50:42 +04:00
2011-09-05 21:31:30 +04:00
smp - > preq [ 0 ] = SMP_CMD_PAIRING_REQ ;
memcpy ( & smp - > preq [ 1 ] , & cp , sizeof ( cp ) ) ;
2011-06-10 01:50:45 +04:00
2011-06-10 01:50:42 +04:00
smp_send_cmd ( conn , SMP_CMD_PAIRING_REQ , sizeof ( cp ) , & cp ) ;
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RSP ) ;
2011-01-27 03:42:57 +03:00
2011-06-10 01:50:53 +04:00
return 0 ;
2011-06-10 01:50:42 +04:00
}
2012-08-24 04:32:43 +04:00
int smp_conn_security ( struct hci_conn * hcon , __u8 sec_level )
2011-06-10 01:50:40 +04:00
{
2012-08-24 04:32:43 +04:00
struct l2cap_conn * conn = hcon - > l2cap_data ;
2014-09-06 07:59:10 +04:00
struct l2cap_chan * chan ;
2014-03-24 16:39:03 +04:00
struct smp_chan * smp ;
2011-12-22 04:12:12 +04:00
__u8 authreq ;
2014-09-05 23:19:52 +04:00
int ret ;
2011-06-10 01:50:40 +04:00
2011-06-10 01:50:43 +04:00
BT_DBG ( " conn %p hcon %p level 0x%2.2x " , conn , hcon , sec_level ) ;
2014-03-24 16:39:03 +04:00
/* This may be NULL if there's an unexpected disconnection */
if ( ! conn )
return 1 ;
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hcon - > hdev , HCI_LE_ENABLED ) )
2011-07-01 02:20:56 +04:00
return 1 ;
2014-11-13 11:55:18 +03:00
if ( smp_sufficient_security ( hcon , sec_level , SMP_USE_LTK ) )
2011-06-10 01:50:40 +04:00
return 1 ;
2011-01-27 03:42:57 +03:00
2014-06-17 14:07:37 +04:00
if ( sec_level > hcon - > pending_sec_level )
hcon - > pending_sec_level = sec_level ;
2014-07-16 12:42:27 +04:00
if ( hcon - > role = = HCI_ROLE_MASTER )
2014-06-17 14:07:37 +04:00
if ( smp_ltk_encrypt ( conn , hcon - > pending_sec_level ) )
return 0 ;
2011-08-20 04:06:51 +04:00
2015-09-04 12:22:46 +03:00
chan = conn - > smp ;
if ( ! chan ) {
BT_ERR ( " SMP security requested but not available " ) ;
return 1 ;
}
2014-09-05 23:19:52 +04:00
l2cap_chan_lock ( chan ) ;
/* If SMP is already in progress ignore this request */
if ( chan - > data ) {
ret = 0 ;
goto unlock ;
}
2011-08-20 04:06:51 +04:00
2011-09-05 21:31:31 +04:00
smp = smp_chan_create ( conn ) ;
2014-09-05 23:19:52 +04:00
if ( ! smp ) {
ret = 1 ;
goto unlock ;
}
2011-12-22 04:12:12 +04:00
authreq = seclevel_to_authreq ( sec_level ) ;
2011-08-20 04:06:51 +04:00
2015-03-13 12:11:00 +03:00
if ( hci_dev_test_flag ( hcon - > hdev , HCI_SC_ENABLED ) )
2014-05-16 11:59:06 +04:00
authreq | = SMP_AUTH_SC ;
2014-06-01 10:45:24 +04:00
/* Require MITM if IO Capability allows or the security level
* requires it .
2014-03-18 17:42:30 +04:00
*/
2014-06-01 10:45:24 +04:00
if ( hcon - > io_capability ! = HCI_IO_NO_INPUT_OUTPUT | |
2014-06-17 14:07:37 +04:00
hcon - > pending_sec_level > BT_SECURITY_MEDIUM )
2014-03-18 17:42:30 +04:00
authreq | = SMP_AUTH_MITM ;
2014-07-16 12:42:27 +04:00
if ( hcon - > role = = HCI_ROLE_MASTER ) {
2011-08-20 04:06:51 +04:00
struct smp_cmd_pairing cp ;
2011-06-10 01:50:45 +04:00
2011-12-22 04:12:12 +04:00
build_pairing_cmd ( conn , & cp , NULL , authreq ) ;
2011-09-05 21:31:30 +04:00
smp - > preq [ 0 ] = SMP_CMD_PAIRING_REQ ;
memcpy ( & smp - > preq [ 1 ] , & cp , sizeof ( cp ) ) ;
2011-06-10 01:50:45 +04:00
2011-06-10 01:50:40 +04:00
smp_send_cmd ( conn , SMP_CMD_PAIRING_REQ , sizeof ( cp ) , & cp ) ;
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RSP ) ;
2011-06-10 01:50:40 +04:00
} else {
struct smp_cmd_security_req cp ;
2011-12-22 04:12:12 +04:00
cp . auth_req = authreq ;
2011-06-10 01:50:40 +04:00
smp_send_cmd ( conn , SMP_CMD_SECURITY_REQ , sizeof ( cp ) , & cp ) ;
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_REQ ) ;
2011-06-10 01:50:40 +04:00
}
2014-05-20 10:45:50 +04:00
set_bit ( SMP_FLAG_INITIATOR , & smp - > flags ) ;
2014-09-05 23:19:52 +04:00
ret = 0 ;
2014-03-24 17:54:11 +04:00
2014-09-05 23:19:52 +04:00
unlock :
l2cap_chan_unlock ( chan ) ;
return ret ;
2011-06-10 01:50:40 +04:00
}
2015-10-22 09:38:35 +03:00
void smp_cancel_pairing ( struct hci_conn * hcon )
{
struct l2cap_conn * conn = hcon - > l2cap_data ;
struct l2cap_chan * chan ;
struct smp_chan * smp ;
if ( ! conn )
return ;
chan = conn - > smp ;
if ( ! chan )
return ;
l2cap_chan_lock ( chan ) ;
smp = chan - > data ;
if ( smp ) {
if ( test_bit ( SMP_FLAG_COMPLETE , & smp - > flags ) )
smp_failure ( conn , 0 ) ;
else
smp_failure ( conn , SMP_UNSPECIFIED ) ;
}
l2cap_chan_unlock ( chan ) ;
}
2011-07-08 01:59:34 +04:00
static int smp_cmd_encrypt_info ( struct l2cap_conn * conn , struct sk_buff * skb )
{
2011-07-08 01:59:39 +04:00
struct smp_cmd_encrypt_info * rp = ( void * ) skb - > data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2011-07-08 01:59:39 +04:00
2014-02-18 12:19:29 +04:00
BT_DBG ( " conn %p " , conn ) ;
if ( skb - > len < sizeof ( * rp ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_MASTER_IDENT ) ;
2014-02-18 12:19:37 +04:00
2011-07-08 01:59:39 +04:00
skb_pull ( skb , sizeof ( * rp ) ) ;
2011-09-05 21:31:30 +04:00
memcpy ( smp - > tk , rp - > ltk , sizeof ( smp - > tk ) ) ;
2011-07-08 01:59:39 +04:00
2011-07-08 01:59:34 +04:00
return 0 ;
}
static int smp_cmd_master_ident ( struct l2cap_conn * conn , struct sk_buff * skb )
{
2011-07-08 01:59:39 +04:00
struct smp_cmd_master_ident * rp = ( void * ) skb - > data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2012-02-03 04:08:01 +04:00
struct hci_dev * hdev = conn - > hcon - > hdev ;
struct hci_conn * hcon = conn - > hcon ;
2014-02-19 16:57:46 +04:00
struct smp_ltk * ltk ;
2012-02-03 04:08:01 +04:00
u8 authenticated ;
2011-07-08 01:59:39 +04:00
2014-02-18 12:19:29 +04:00
BT_DBG ( " conn %p " , conn ) ;
if ( skb - > len < sizeof ( * rp ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:29 +04:00
2014-02-27 01:33:43 +04:00
/* Mark the information as received */
smp - > remote_key_dist & = ~ SMP_DIST_ENC_KEY ;
2014-09-05 23:19:55 +04:00
if ( smp - > remote_key_dist & SMP_DIST_ID_KEY )
SMP_ALLOW_CMD ( smp , SMP_CMD_IDENT_INFO ) ;
2014-09-10 03:21:46 +04:00
else if ( smp - > remote_key_dist & SMP_DIST_SIGN )
SMP_ALLOW_CMD ( smp , SMP_CMD_SIGN_INFO ) ;
2014-09-05 23:19:55 +04:00
2011-07-08 01:59:39 +04:00
skb_pull ( skb , sizeof ( * rp ) ) ;
2011-07-08 01:59:34 +04:00
2013-10-13 13:23:39 +04:00
authenticated = ( hcon - > sec_level = = BT_SECURITY_HIGH ) ;
2014-06-16 20:25:16 +04:00
ltk = hci_add_ltk ( hdev , & hcon - > dst , hcon - > dst_type , SMP_LTK ,
2014-02-19 16:57:46 +04:00
authenticated , smp - > tk , smp - > enc_key_size ,
rp - > ediv , rp - > rand ) ;
smp - > ltk = ltk ;
2014-09-05 23:19:54 +04:00
if ( ! ( smp - > remote_key_dist & KEY_DIST_MASK ) )
2014-09-05 23:19:51 +04:00
smp_distribute_keys ( smp ) ;
2011-07-08 01:59:34 +04:00
return 0 ;
}
2014-02-18 12:19:36 +04:00
static int smp_cmd_ident_info ( struct l2cap_conn * conn , struct sk_buff * skb )
{
struct smp_cmd_ident_info * info = ( void * ) skb - > data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-02-18 12:19:36 +04:00
BT_DBG ( " " ) ;
if ( skb - > len < sizeof ( * info ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:36 +04:00
2014-09-05 23:19:55 +04:00
SMP_ALLOW_CMD ( smp , SMP_CMD_IDENT_ADDR_INFO ) ;
2014-02-18 12:19:37 +04:00
2014-02-18 12:19:36 +04:00
skb_pull ( skb , sizeof ( * info ) ) ;
memcpy ( smp - > irk , info - > irk , 16 ) ;
return 0 ;
}
static int smp_cmd_ident_addr_info ( struct l2cap_conn * conn ,
struct sk_buff * skb )
{
struct smp_cmd_ident_addr_info * info = ( void * ) skb - > data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-02-18 12:19:36 +04:00
struct hci_conn * hcon = conn - > hcon ;
bdaddr_t rpa ;
BT_DBG ( " " ) ;
if ( skb - > len < sizeof ( * info ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-02-18 12:19:36 +04:00
2014-02-27 01:33:43 +04:00
/* Mark the information as received */
smp - > remote_key_dist & = ~ SMP_DIST_ID_KEY ;
2014-09-05 23:19:55 +04:00
if ( smp - > remote_key_dist & SMP_DIST_SIGN )
SMP_ALLOW_CMD ( smp , SMP_CMD_SIGN_INFO ) ;
2014-02-18 12:19:36 +04:00
skb_pull ( skb , sizeof ( * info ) ) ;
2014-02-26 00:24:37 +04:00
/* Strictly speaking the Core Specification (4.1) allows sending
* an empty address which would force us to rely on just the IRK
* as " identity information " . However , since such
* implementations are not known of and in order to not over
* complicate our implementation , simply pretend that we never
* received an IRK for such a device .
2015-01-14 21:51:37 +03:00
*
* The Identity Address must also be a Static Random or Public
* Address , which hci_is_identity_address ( ) checks for .
2014-02-26 00:24:37 +04:00
*/
2015-01-14 21:51:37 +03:00
if ( ! bacmp ( & info - > bdaddr , BDADDR_ANY ) | |
! hci_is_identity_address ( & info - > bdaddr , info - > addr_type ) ) {
2014-02-26 00:24:37 +04:00
BT_ERR ( " Ignoring IRK with no identity address " ) ;
2014-06-27 15:23:02 +04:00
goto distribute ;
2014-02-26 00:24:37 +04:00
}
2014-02-18 12:19:36 +04:00
bacpy ( & smp - > id_addr , & info - > bdaddr ) ;
smp - > id_addr_type = info - > addr_type ;
if ( hci_bdaddr_is_rpa ( & hcon - > dst , hcon - > dst_type ) )
bacpy ( & rpa , & hcon - > dst ) ;
else
bacpy ( & rpa , BDADDR_ANY ) ;
2014-02-19 16:57:46 +04:00
smp - > remote_irk = hci_add_irk ( conn - > hcon - > hdev , & smp - > id_addr ,
smp - > id_addr_type , smp - > irk , & rpa ) ;
2014-02-18 12:19:36 +04:00
2014-06-27 15:23:02 +04:00
distribute :
2014-09-05 23:19:54 +04:00
if ( ! ( smp - > remote_key_dist & KEY_DIST_MASK ) )
smp_distribute_keys ( smp ) ;
2014-02-18 12:19:36 +04:00
return 0 ;
}
2014-03-09 23:19:17 +04:00
static int smp_cmd_sign_info ( struct l2cap_conn * conn , struct sk_buff * skb )
{
struct smp_cmd_sign_info * rp = ( void * ) skb - > data ;
2014-08-08 10:37:18 +04:00
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-03-09 23:19:17 +04:00
struct smp_csrk * csrk ;
BT_DBG ( " conn %p " , conn ) ;
if ( skb - > len < sizeof ( * rp ) )
2014-05-08 15:19:11 +04:00
return SMP_INVALID_PARAMS ;
2014-03-09 23:19:17 +04:00
/* Mark the information as received */
smp - > remote_key_dist & = ~ SMP_DIST_SIGN ;
skb_pull ( skb , sizeof ( * rp ) ) ;
csrk = kzalloc ( sizeof ( * csrk ) , GFP_KERNEL ) ;
if ( csrk ) {
2015-02-27 11:11:13 +03:00
if ( conn - > hcon - > sec_level > BT_SECURITY_MEDIUM )
csrk - > type = MGMT_CSRK_REMOTE_AUTHENTICATED ;
else
csrk - > type = MGMT_CSRK_REMOTE_UNAUTHENTICATED ;
2014-03-09 23:19:17 +04:00
memcpy ( csrk - > val , rp - > csrk , sizeof ( csrk - > val ) ) ;
}
smp - > csrk = csrk ;
2014-09-05 23:19:51 +04:00
smp_distribute_keys ( smp ) ;
2014-03-09 23:19:17 +04:00
return 0 ;
}
2014-05-31 19:51:02 +04:00
static u8 sc_select_method ( struct smp_chan * smp )
{
struct l2cap_conn * conn = smp - > conn ;
struct hci_conn * hcon = conn - > hcon ;
struct smp_cmd_pairing * local , * remote ;
u8 local_mitm , remote_mitm , local_io , remote_io , method ;
2015-03-16 12:45:44 +03:00
if ( test_bit ( SMP_FLAG_REMOTE_OOB , & smp - > flags ) | |
test_bit ( SMP_FLAG_LOCAL_OOB , & smp - > flags ) )
2014-10-28 17:17:05 +03:00
return REQ_OOB ;
2014-05-31 19:51:02 +04:00
/* The preq/prsp contain the raw Pairing Request/Response PDUs
* which are needed as inputs to some crypto functions . To get
* the " struct smp_cmd_pairing " from them we need to skip the
* first byte which contains the opcode .
*/
if ( hcon - > out ) {
local = ( void * ) & smp - > preq [ 1 ] ;
remote = ( void * ) & smp - > prsp [ 1 ] ;
} else {
local = ( void * ) & smp - > prsp [ 1 ] ;
remote = ( void * ) & smp - > preq [ 1 ] ;
}
local_io = local - > io_capability ;
remote_io = remote - > io_capability ;
local_mitm = ( local - > auth_req & SMP_AUTH_MITM ) ;
remote_mitm = ( remote - > auth_req & SMP_AUTH_MITM ) ;
/* If either side wants MITM, look up the method from the table,
* otherwise use JUST WORKS .
*/
if ( local_mitm | | remote_mitm )
method = get_auth_method ( smp , local_io , remote_io ) ;
else
method = JUST_WORKS ;
/* Don't confirm locally initiated pairing attempts */
if ( method = = JUST_CFM & & test_bit ( SMP_FLAG_INITIATOR , & smp - > flags ) )
method = JUST_WORKS ;
return method ;
}
2014-06-06 12:09:28 +04:00
static int smp_cmd_public_key ( struct l2cap_conn * conn , struct sk_buff * skb )
{
struct smp_cmd_public_key * key = ( void * ) skb - > data ;
struct hci_conn * hcon = conn - > hcon ;
struct l2cap_chan * chan = conn - > smp ;
struct smp_chan * smp = chan - > data ;
2014-05-31 19:51:02 +04:00
struct hci_dev * hdev = hcon - > hdev ;
2014-06-06 12:30:08 +04:00
struct smp_cmd_pairing_confirm cfm ;
2014-06-06 12:09:28 +04:00
int err ;
BT_DBG ( " conn %p " , conn ) ;
if ( skb - > len < sizeof ( * key ) )
return SMP_INVALID_PARAMS ;
memcpy ( smp - > remote_pk , key , 64 ) ;
2015-03-16 19:12:57 +03:00
if ( test_bit ( SMP_FLAG_REMOTE_OOB , & smp - > flags ) ) {
err = smp_f4 ( smp - > tfm_cmac , smp - > remote_pk , smp - > remote_pk ,
smp - > rr , 0 , cfm . confirm_val ) ;
if ( err )
return SMP_UNSPECIFIED ;
if ( memcmp ( cfm . confirm_val , smp - > pcnf , 16 ) )
return SMP_CONFIRM_FAILED ;
}
2014-06-06 12:09:28 +04:00
/* Non-initiating device sends its public key after receiving
* the key from the initiating device .
*/
if ( ! hcon - > out ) {
err = sc_send_public_key ( smp ) ;
if ( err )
return err ;
}
2014-12-01 23:03:16 +03:00
SMP_DBG ( " Remote Public Key X: %32phN " , smp - > remote_pk ) ;
2015-03-16 22:34:55 +03:00
SMP_DBG ( " Remote Public Key Y: %32phN " , smp - > remote_pk + 32 ) ;
2014-06-06 12:09:28 +04:00
if ( ! ecdh_shared_secret ( smp - > remote_pk , smp - > local_sk , smp - > dhkey ) )
return SMP_UNSPECIFIED ;
2014-12-01 23:03:16 +03:00
SMP_DBG ( " DHKey %32phN " , smp - > dhkey ) ;
2014-06-06 12:09:28 +04:00
set_bit ( SMP_FLAG_REMOTE_PK , & smp - > flags ) ;
2014-05-31 19:51:02 +04:00
smp - > method = sc_select_method ( smp ) ;
BT_DBG ( " %s selected method 0x%02x " , hdev - > name , smp - > method ) ;
/* JUST_WORKS and JUST_CFM result in an unauthenticated key */
if ( smp - > method = = JUST_WORKS | | smp - > method = = JUST_CFM )
hcon - > pending_sec_level = BT_SECURITY_MEDIUM ;
else
hcon - > pending_sec_level = BT_SECURITY_FIPS ;
2014-05-31 19:52:28 +04:00
if ( ! memcmp ( debug_pk , smp - > remote_pk , 64 ) )
set_bit ( SMP_FLAG_DEBUG_KEY , & smp - > flags ) ;
2014-06-25 12:10:28 +04:00
if ( smp - > method = = DSP_PASSKEY ) {
get_random_bytes ( & hcon - > passkey_notify ,
sizeof ( hcon - > passkey_notify ) ) ;
hcon - > passkey_notify % = 1000000 ;
hcon - > passkey_entered = 0 ;
smp - > passkey_round = 0 ;
if ( mgmt_user_passkey_notify ( hdev , & hcon - > dst , hcon - > type ,
hcon - > dst_type ,
hcon - > passkey_notify ,
hcon - > passkey_entered ) )
return SMP_UNSPECIFIED ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
return sc_passkey_round ( smp , SMP_CMD_PUBLIC_KEY ) ;
}
2015-03-16 12:45:46 +03:00
if ( smp - > method = = REQ_OOB ) {
2014-10-28 17:17:05 +03:00
if ( hcon - > out )
smp_send_cmd ( conn , SMP_CMD_PAIRING_RANDOM ,
sizeof ( smp - > prnd ) , smp - > prnd ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RANDOM ) ;
return 0 ;
}
2014-06-25 12:10:28 +04:00
if ( hcon - > out )
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
if ( smp - > method = = REQ_PASSKEY ) {
if ( mgmt_user_passkey_request ( hdev , & hcon - > dst , hcon - > type ,
hcon - > dst_type ) )
return SMP_UNSPECIFIED ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_CONFIRM ) ;
set_bit ( SMP_FLAG_WAIT_USER , & smp - > flags ) ;
return 0 ;
}
2014-06-06 12:30:08 +04:00
/* The Initiating device waits for the non-initiating device to
* send the confirm value .
*/
if ( conn - > hcon - > out )
return 0 ;
err = smp_f4 ( smp - > tfm_cmac , smp - > local_pk , smp - > remote_pk , smp - > prnd ,
0 , cfm . confirm_val ) ;
if ( err )
return SMP_UNSPECIFIED ;
smp_send_cmd ( conn , SMP_CMD_PAIRING_CONFIRM , sizeof ( cfm ) , & cfm ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RANDOM ) ;
2014-06-06 12:09:28 +04:00
return 0 ;
}
2014-06-06 12:47:30 +04:00
static int smp_cmd_dhkey_check ( struct l2cap_conn * conn , struct sk_buff * skb )
{
struct smp_cmd_dhkey_check * check = ( void * ) skb - > data ;
struct l2cap_chan * chan = conn - > smp ;
struct hci_conn * hcon = conn - > hcon ;
struct smp_chan * smp = chan - > data ;
u8 a [ 7 ] , b [ 7 ] , * local_addr , * remote_addr ;
u8 io_cap [ 3 ] , r [ 16 ] , e [ 16 ] ;
int err ;
BT_DBG ( " conn %p " , conn ) ;
if ( skb - > len < sizeof ( * check ) )
return SMP_INVALID_PARAMS ;
memcpy ( a , & hcon - > init_addr , 6 ) ;
memcpy ( b , & hcon - > resp_addr , 6 ) ;
a [ 6 ] = hcon - > init_addr_type ;
b [ 6 ] = hcon - > resp_addr_type ;
if ( hcon - > out ) {
local_addr = a ;
remote_addr = b ;
memcpy ( io_cap , & smp - > prsp [ 1 ] , 3 ) ;
} else {
local_addr = b ;
remote_addr = a ;
memcpy ( io_cap , & smp - > preq [ 1 ] , 3 ) ;
}
memset ( r , 0 , sizeof ( r ) ) ;
2014-06-25 12:10:28 +04:00
if ( smp - > method = = REQ_PASSKEY | | smp - > method = = DSP_PASSKEY )
put_unaligned_le32 ( hcon - > passkey_notify , r ) ;
2015-03-16 12:45:43 +03:00
else if ( smp - > method = = REQ_OOB )
memcpy ( r , smp - > lr , 16 ) ;
2014-06-25 12:10:28 +04:00
2014-06-06 12:47:30 +04:00
err = smp_f6 ( smp - > tfm_cmac , smp - > mackey , smp - > rrnd , smp - > prnd , r ,
io_cap , remote_addr , local_addr , e ) ;
if ( err )
return SMP_UNSPECIFIED ;
if ( memcmp ( check - > e , e , 16 ) )
return SMP_DHKEY_CHECK_FAILED ;
2014-06-04 12:07:40 +04:00
if ( ! hcon - > out ) {
if ( test_bit ( SMP_FLAG_WAIT_USER , & smp - > flags ) ) {
set_bit ( SMP_FLAG_DHKEY_PENDING , & smp - > flags ) ;
return 0 ;
}
2014-05-31 19:53:36 +04:00
2014-06-04 12:07:40 +04:00
/* Slave sends DHKey check as response to master */
sc_dhkey_check ( smp ) ;
}
2014-05-31 19:53:36 +04:00
2014-06-04 12:07:40 +04:00
sc_add_ltk ( smp ) ;
2014-06-06 12:47:30 +04:00
if ( hcon - > out ) {
2015-06-08 18:14:39 +03:00
hci_le_start_enc ( hcon , 0 , 0 , smp - > tk , smp - > enc_key_size ) ;
2014-06-06 12:47:30 +04:00
hcon - > enc_key_size = smp - > enc_key_size ;
}
return 0 ;
}
2014-06-04 23:45:57 +04:00
static int smp_cmd_keypress_notify ( struct l2cap_conn * conn ,
struct sk_buff * skb )
{
struct smp_cmd_keypress_notify * kp = ( void * ) skb - > data ;
BT_DBG ( " value 0x%02x " , kp - > value ) ;
return 0 ;
}
2014-08-11 23:06:38 +04:00
static int smp_sig_channel ( struct l2cap_chan * chan , struct sk_buff * skb )
2011-06-10 01:50:40 +04:00
{
2014-08-08 10:37:18 +04:00
struct l2cap_conn * conn = chan - > conn ;
2013-10-03 11:00:57 +04:00
struct hci_conn * hcon = conn - > hcon ;
2014-09-05 23:19:55 +04:00
struct smp_chan * smp ;
2013-10-03 12:23:08 +04:00
__u8 code , reason ;
2011-06-10 01:50:40 +04:00
int err = 0 ;
2014-08-11 23:06:39 +04:00
if ( skb - > len < 1 )
2013-10-03 12:23:08 +04:00
return - EILSEQ ;
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hcon - > hdev , HCI_LE_ENABLED ) ) {
2011-07-01 02:20:56 +04:00
reason = SMP_PAIRING_NOTSUPP ;
goto done ;
}
2013-10-03 12:23:08 +04:00
code = skb - > data [ 0 ] ;
2011-06-10 01:50:40 +04:00
skb_pull ( skb , sizeof ( code ) ) ;
2014-09-05 23:19:55 +04:00
smp = chan - > data ;
if ( code > SMP_CMD_MAX )
goto drop ;
2014-09-11 04:37:43 +04:00
if ( smp & & ! test_and_clear_bit ( code , & smp - > allow_cmd ) )
2014-09-05 23:19:55 +04:00
goto drop ;
/* If we don't have a context the only allowed commands are
* pairing request and security request .
2013-01-29 20:44:23 +04:00
*/
2014-09-05 23:19:55 +04:00
if ( ! smp & & code ! = SMP_CMD_PAIRING_REQ & & code ! = SMP_CMD_SECURITY_REQ )
goto drop ;
2013-01-29 20:44:23 +04:00
2011-06-10 01:50:40 +04:00
switch ( code ) {
case SMP_CMD_PAIRING_REQ :
2011-06-10 01:50:53 +04:00
reason = smp_cmd_pairing_req ( conn , skb ) ;
2011-06-10 01:50:40 +04:00
break ;
case SMP_CMD_PAIRING_FAIL :
2013-11-06 13:24:57 +04:00
smp_failure ( conn , 0 ) ;
2011-06-10 01:50:53 +04:00
err = - EPERM ;
2011-06-10 01:50:40 +04:00
break ;
case SMP_CMD_PAIRING_RSP :
2011-06-10 01:50:53 +04:00
reason = smp_cmd_pairing_rsp ( conn , skb ) ;
2011-06-10 01:50:42 +04:00
break ;
case SMP_CMD_SECURITY_REQ :
2011-06-10 01:50:53 +04:00
reason = smp_cmd_security_req ( conn , skb ) ;
2011-06-10 01:50:42 +04:00
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_PAIRING_CONFIRM :
2011-06-10 01:50:53 +04:00
reason = smp_cmd_pairing_confirm ( conn , skb ) ;
2011-06-10 01:50:42 +04:00
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_PAIRING_RANDOM :
2011-06-10 01:50:53 +04:00
reason = smp_cmd_pairing_random ( conn , skb ) ;
2011-06-10 01:50:42 +04:00
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_ENCRYPT_INFO :
2011-07-08 01:59:34 +04:00
reason = smp_cmd_encrypt_info ( conn , skb ) ;
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_MASTER_IDENT :
2011-07-08 01:59:34 +04:00
reason = smp_cmd_master_ident ( conn , skb ) ;
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_IDENT_INFO :
2014-02-18 12:19:36 +04:00
reason = smp_cmd_ident_info ( conn , skb ) ;
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_IDENT_ADDR_INFO :
2014-02-18 12:19:36 +04:00
reason = smp_cmd_ident_addr_info ( conn , skb ) ;
break ;
2011-06-10 01:50:40 +04:00
case SMP_CMD_SIGN_INFO :
2014-03-09 23:19:17 +04:00
reason = smp_cmd_sign_info ( conn , skb ) ;
2011-07-08 01:59:34 +04:00
break ;
2014-06-06 12:09:28 +04:00
case SMP_CMD_PUBLIC_KEY :
reason = smp_cmd_public_key ( conn , skb ) ;
break ;
2014-06-06 12:47:30 +04:00
case SMP_CMD_DHKEY_CHECK :
reason = smp_cmd_dhkey_check ( conn , skb ) ;
break ;
2014-06-04 23:45:57 +04:00
case SMP_CMD_KEYPRESS_NOTIFY :
reason = smp_cmd_keypress_notify ( conn , skb ) ;
break ;
2011-06-10 01:50:40 +04:00
default :
BT_DBG ( " Unknown command code 0x%2.2x " , code ) ;
reason = SMP_CMD_NOTSUPP ;
2011-06-10 01:50:43 +04:00
goto done ;
2011-06-10 01:50:40 +04:00
}
2011-06-10 01:50:43 +04:00
done :
2014-08-18 21:33:31 +04:00
if ( ! err ) {
if ( reason )
smp_failure ( conn , reason ) ;
2014-08-11 23:06:39 +04:00
kfree_skb ( skb ) ;
2014-08-18 21:33:31 +04:00
}
2011-06-10 01:50:40 +04:00
return err ;
2014-09-05 23:19:55 +04:00
drop :
BT_ERR ( " %s unexpected SMP command 0x%02x from %pMR " , hcon - > hdev - > name ,
code , & hcon - > dst ) ;
kfree_skb ( skb ) ;
return 0 ;
2011-06-10 01:50:40 +04:00
}
2011-07-08 01:59:34 +04:00
2014-08-08 10:37:16 +04:00
static void smp_teardown_cb ( struct l2cap_chan * chan , int err )
{
struct l2cap_conn * conn = chan - > conn ;
BT_DBG ( " chan %p " , chan ) ;
2014-09-05 23:19:52 +04:00
if ( chan - > data )
2014-08-08 10:37:18 +04:00
smp_chan_destroy ( conn ) ;
2014-08-08 10:37:16 +04:00
conn - > smp = NULL ;
l2cap_chan_put ( chan ) ;
}
2014-08-14 13:34:26 +04:00
static void bredr_pairing ( struct l2cap_chan * chan )
{
struct l2cap_conn * conn = chan - > conn ;
struct hci_conn * hcon = conn - > hcon ;
struct hci_dev * hdev = hcon - > hdev ;
struct smp_cmd_pairing req ;
struct smp_chan * smp ;
BT_DBG ( " chan %p " , chan ) ;
/* Only new pairings are interesting */
if ( ! test_bit ( HCI_CONN_NEW_LINK_KEY , & hcon - > flags ) )
return ;
/* Don't bother if we're not encrypted */
if ( ! test_bit ( HCI_CONN_ENCRYPT , & hcon - > flags ) )
return ;
/* Only master may initiate SMP over BR/EDR */
if ( hcon - > role ! = HCI_ROLE_MASTER )
return ;
/* Secure Connections support must be enabled */
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hdev , HCI_SC_ENABLED ) )
2014-08-14 13:34:26 +04:00
return ;
/* BR/EDR must use Secure Connections for SMP */
if ( ! test_bit ( HCI_CONN_AES_CCM , & hcon - > flags ) & &
2015-03-13 20:20:35 +03:00
! hci_dev_test_flag ( hdev , HCI_FORCE_BREDR_SMP ) )
2014-08-14 13:34:26 +04:00
return ;
/* If our LE support is not enabled don't do anything */
2015-03-13 12:11:00 +03:00
if ( ! hci_dev_test_flag ( hdev , HCI_LE_ENABLED ) )
2014-08-14 13:34:26 +04:00
return ;
/* Don't bother if remote LE support is not enabled */
if ( ! lmp_host_le_capable ( hcon ) )
return ;
/* Remote must support SMP fixed chan for BR/EDR */
if ( ! ( conn - > remote_fixed_chan & L2CAP_FC_SMP_BREDR ) )
return ;
/* Don't bother if SMP is already ongoing */
if ( chan - > data )
return ;
smp = smp_chan_create ( conn ) ;
if ( ! smp ) {
BT_ERR ( " %s unable to create SMP context for BR/EDR " ,
hdev - > name ) ;
return ;
}
set_bit ( SMP_FLAG_SC , & smp - > flags ) ;
BT_DBG ( " %s starting SMP over BR/EDR " , hdev - > name ) ;
/* Prepare and send the BR/EDR SMP Pairing Request */
build_bredr_pairing_cmd ( smp , & req , NULL ) ;
smp - > preq [ 0 ] = SMP_CMD_PAIRING_REQ ;
memcpy ( & smp - > preq [ 1 ] , & req , sizeof ( req ) ) ;
smp_send_cmd ( conn , SMP_CMD_PAIRING_REQ , sizeof ( req ) , & req ) ;
SMP_ALLOW_CMD ( smp , SMP_CMD_PAIRING_RSP ) ;
}
2014-08-11 23:06:36 +04:00
static void smp_resume_cb ( struct l2cap_chan * chan )
{
2014-08-11 23:06:40 +04:00
struct smp_chan * smp = chan - > data ;
2014-08-11 23:06:36 +04:00
struct l2cap_conn * conn = chan - > conn ;
struct hci_conn * hcon = conn - > hcon ;
BT_DBG ( " chan %p " , chan ) ;
2014-08-14 13:34:26 +04:00
if ( hcon - > type = = ACL_LINK ) {
bredr_pairing ( chan ) ;
2014-08-13 16:12:32 +04:00
return ;
2014-08-14 13:34:26 +04:00
}
2014-08-13 16:12:32 +04:00
2014-08-11 23:06:43 +04:00
if ( ! smp )
return ;
2014-08-11 23:06:40 +04:00
2014-09-05 23:19:49 +04:00
if ( ! test_bit ( HCI_CONN_ENCRYPT , & hcon - > flags ) )
return ;
2014-08-11 23:06:43 +04:00
cancel_delayed_work ( & smp - > security_timer ) ;
2014-09-05 23:19:51 +04:00
smp_distribute_keys ( smp ) ;
2014-08-11 23:06:36 +04:00
}
2014-08-08 10:37:16 +04:00
static void smp_ready_cb ( struct l2cap_chan * chan )
{
struct l2cap_conn * conn = chan - > conn ;
2014-08-14 13:34:26 +04:00
struct hci_conn * hcon = conn - > hcon ;
2014-08-08 10:37:16 +04:00
BT_DBG ( " chan %p " , chan ) ;
2015-11-11 22:47:12 +03:00
/* No need to call l2cap_chan_hold() here since we already own
* the reference taken in smp_new_conn_cb ( ) . This is just the
* first time that we tie it to a specific pointer . The code in
* l2cap_core . c ensures that there ' s no risk this function wont
* get called if smp_new_conn_cb was previously called .
*/
2014-08-08 10:37:16 +04:00
conn - > smp = chan ;
2014-08-14 13:34:26 +04:00
if ( hcon - > type = = ACL_LINK & & test_bit ( HCI_CONN_ENCRYPT , & hcon - > flags ) )
bredr_pairing ( chan ) ;
2014-08-08 10:37:16 +04:00
}
2014-08-11 23:06:38 +04:00
static int smp_recv_cb ( struct l2cap_chan * chan , struct sk_buff * skb )
{
int err ;
BT_DBG ( " chan %p " , chan ) ;
err = smp_sig_channel ( chan , skb ) ;
if ( err ) {
2014-08-11 23:06:40 +04:00
struct smp_chan * smp = chan - > data ;
2014-08-11 23:06:38 +04:00
2014-08-11 23:06:40 +04:00
if ( smp )
cancel_delayed_work_sync ( & smp - > security_timer ) ;
2014-08-11 23:06:38 +04:00
2014-08-18 21:33:29 +04:00
hci_disconnect ( chan - > conn - > hcon , HCI_ERROR_AUTH_FAILURE ) ;
2014-08-11 23:06:38 +04:00
}
return err ;
}
2014-08-08 10:37:16 +04:00
static struct sk_buff * smp_alloc_skb_cb ( struct l2cap_chan * chan ,
unsigned long hdr_len ,
unsigned long len , int nb )
{
struct sk_buff * skb ;
skb = bt_skb_alloc ( hdr_len + len , GFP_KERNEL ) ;
if ( ! skb )
return ERR_PTR ( - ENOMEM ) ;
skb - > priority = HCI_PRIO_MAX ;
2015-03-30 23:21:01 +03:00
bt_cb ( skb ) - > l2cap . chan = chan ;
2014-08-08 10:37:16 +04:00
return skb ;
}
static const struct l2cap_ops smp_chan_ops = {
. name = " Security Manager " ,
. ready = smp_ready_cb ,
2014-08-08 10:37:18 +04:00
. recv = smp_recv_cb ,
2014-08-08 10:37:16 +04:00
. alloc_skb = smp_alloc_skb_cb ,
. teardown = smp_teardown_cb ,
2014-08-11 23:06:36 +04:00
. resume = smp_resume_cb ,
2014-08-08 10:37:16 +04:00
. new_connection = l2cap_chan_no_new_connection ,
. state_change = l2cap_chan_no_state_change ,
. close = l2cap_chan_no_close ,
. defer = l2cap_chan_no_defer ,
. suspend = l2cap_chan_no_suspend ,
. set_shutdown = l2cap_chan_no_set_shutdown ,
. get_sndtimeo = l2cap_chan_no_get_sndtimeo ,
} ;
static inline struct l2cap_chan * smp_new_conn_cb ( struct l2cap_chan * pchan )
{
struct l2cap_chan * chan ;
BT_DBG ( " pchan %p " , pchan ) ;
chan = l2cap_chan_create ( ) ;
if ( ! chan )
return NULL ;
chan - > chan_type = pchan - > chan_type ;
chan - > ops = & smp_chan_ops ;
chan - > scid = pchan - > scid ;
chan - > dcid = chan - > scid ;
chan - > imtu = pchan - > imtu ;
chan - > omtu = pchan - > omtu ;
chan - > mode = pchan - > mode ;
2014-11-12 23:22:21 +03:00
/* Other L2CAP channels may request SMP routines in order to
* change the security level . This means that the SMP channel
* lock must be considered in its own category to avoid lockdep
* warnings .
*/
atomic_set ( & chan - > nesting , L2CAP_NESTING_SMP ) ;
2014-08-08 10:37:16 +04:00
BT_DBG ( " created chan %p " , chan ) ;
return chan ;
}
static const struct l2cap_ops smp_root_chan_ops = {
. name = " Security Manager Root " ,
. new_connection = smp_new_conn_cb ,
/* None of these are implemented for the root channel */
. close = l2cap_chan_no_close ,
. alloc_skb = l2cap_chan_no_alloc_skb ,
. recv = l2cap_chan_no_recv ,
. state_change = l2cap_chan_no_state_change ,
. teardown = l2cap_chan_no_teardown ,
. ready = l2cap_chan_no_ready ,
. defer = l2cap_chan_no_defer ,
. suspend = l2cap_chan_no_suspend ,
. resume = l2cap_chan_no_resume ,
. set_shutdown = l2cap_chan_no_set_shutdown ,
. get_sndtimeo = l2cap_chan_no_get_sndtimeo ,
} ;
2014-08-13 16:12:32 +04:00
static struct l2cap_chan * smp_add_cid ( struct hci_dev * hdev , u16 cid )
2014-08-08 10:32:52 +04:00
{
2014-08-08 10:37:16 +04:00
struct l2cap_chan * chan ;
2015-03-16 11:10:19 +03:00
struct smp_dev * smp ;
2016-01-24 16:18:30 +03:00
struct crypto_skcipher * tfm_aes ;
struct crypto_shash * tfm_cmac ;
2014-08-08 10:37:16 +04:00
2014-08-13 16:12:32 +04:00
if ( cid = = L2CAP_CID_SMP_BREDR ) {
2015-03-16 11:10:19 +03:00
smp = NULL ;
2014-08-13 16:12:32 +04:00
goto create_chan ;
}
2014-08-08 10:32:52 +04:00
2015-03-16 11:10:19 +03:00
smp = kzalloc ( sizeof ( * smp ) , GFP_KERNEL ) ;
if ( ! smp )
return ERR_PTR ( - ENOMEM ) ;
2016-01-24 16:18:30 +03:00
tfm_aes = crypto_alloc_skcipher ( " ecb(aes) " , 0 , CRYPTO_ALG_ASYNC ) ;
2014-08-08 10:37:17 +04:00
if ( IS_ERR ( tfm_aes ) ) {
2015-03-16 11:10:19 +03:00
BT_ERR ( " Unable to create ECB crypto context " ) ;
kzfree ( smp ) ;
2014-12-07 22:04:38 +03:00
return ERR_CAST ( tfm_aes ) ;
2014-08-08 10:32:52 +04:00
}
2016-01-24 16:18:30 +03:00
tfm_cmac = crypto_alloc_shash ( " cmac(aes) " , 0 , 0 ) ;
2015-03-16 11:10:21 +03:00
if ( IS_ERR ( tfm_cmac ) ) {
BT_ERR ( " Unable to create CMAC crypto context " ) ;
2016-01-24 16:18:30 +03:00
crypto_free_skcipher ( tfm_aes ) ;
2015-03-16 11:10:21 +03:00
kzfree ( smp ) ;
return ERR_CAST ( tfm_cmac ) ;
}
2015-03-16 11:10:19 +03:00
smp - > tfm_aes = tfm_aes ;
2015-03-16 11:10:21 +03:00
smp - > tfm_cmac = tfm_cmac ;
2015-06-11 13:52:27 +03:00
smp - > min_key_size = SMP_MIN_ENC_KEY_SIZE ;
2015-06-11 13:52:26 +03:00
smp - > max_key_size = SMP_MAX_ENC_KEY_SIZE ;
2015-03-16 11:10:19 +03:00
2014-08-13 16:12:32 +04:00
create_chan :
2014-08-08 10:37:16 +04:00
chan = l2cap_chan_create ( ) ;
if ( ! chan ) {
2015-03-17 21:38:24 +03:00
if ( smp ) {
2016-01-24 16:18:30 +03:00
crypto_free_skcipher ( smp - > tfm_aes ) ;
crypto_free_shash ( smp - > tfm_cmac ) ;
2015-03-17 21:38:24 +03:00
kzfree ( smp ) ;
}
2014-08-13 16:12:32 +04:00
return ERR_PTR ( - ENOMEM ) ;
2014-08-08 10:37:16 +04:00
}
2015-03-16 11:10:19 +03:00
chan - > data = smp ;
2014-08-08 10:37:17 +04:00
2014-08-13 16:12:32 +04:00
l2cap_add_scid ( chan , cid ) ;
2014-08-08 10:37:16 +04:00
l2cap_chan_set_defaults ( chan ) ;
2015-01-15 02:43:09 +03:00
if ( cid = = L2CAP_CID_SMP ) {
2015-02-20 14:48:24 +03:00
u8 bdaddr_type ;
hci_copy_identity_address ( hdev , & chan - > src , & bdaddr_type ) ;
if ( bdaddr_type = = ADDR_LE_DEV_PUBLIC )
2015-01-15 02:43:09 +03:00
chan - > src_type = BDADDR_LE_PUBLIC ;
2015-02-20 14:48:24 +03:00
else
chan - > src_type = BDADDR_LE_RANDOM ;
2015-01-15 02:43:09 +03:00
} else {
bacpy ( & chan - > src , & hdev - > bdaddr ) ;
2014-08-13 16:12:32 +04:00
chan - > src_type = BDADDR_BREDR ;
2015-01-15 02:43:09 +03:00
}
2014-08-08 10:37:16 +04:00
chan - > state = BT_LISTEN ;
chan - > mode = L2CAP_MODE_BASIC ;
chan - > imtu = L2CAP_DEFAULT_MTU ;
chan - > ops = & smp_root_chan_ops ;
2014-11-12 23:22:21 +03:00
/* Set correct nesting level for a parent/listening channel */
atomic_set ( & chan - > nesting , L2CAP_NESTING_PARENT ) ;
2014-08-13 16:12:32 +04:00
return chan ;
2014-08-08 10:32:52 +04:00
}
2014-08-13 16:12:32 +04:00
static void smp_del_chan ( struct l2cap_chan * chan )
2014-08-08 10:32:52 +04:00
{
2015-03-16 11:10:19 +03:00
struct smp_dev * smp ;
2014-08-08 10:37:16 +04:00
2014-08-13 16:12:32 +04:00
BT_DBG ( " chan %p " , chan ) ;
2014-08-08 10:32:52 +04:00
2015-03-16 11:10:19 +03:00
smp = chan - > data ;
if ( smp ) {
2014-08-08 10:37:17 +04:00
chan - > data = NULL ;
2016-01-24 16:18:30 +03:00
crypto_free_skcipher ( smp - > tfm_aes ) ;
crypto_free_shash ( smp - > tfm_cmac ) ;
2015-03-16 11:10:19 +03:00
kzfree ( smp ) ;
2014-08-08 10:32:52 +04:00
}
2014-08-08 10:37:16 +04:00
l2cap_chan_put ( chan ) ;
2014-08-08 10:32:52 +04:00
}
2014-08-13 16:12:32 +04:00
2015-01-01 01:43:16 +03:00
static ssize_t force_bredr_smp_read ( struct file * file ,
char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct hci_dev * hdev = file - > private_data ;
char buf [ 3 ] ;
2015-03-13 20:20:35 +03:00
buf [ 0 ] = hci_dev_test_flag ( hdev , HCI_FORCE_BREDR_SMP ) ? ' Y ' : ' N ' ;
2015-01-01 01:43:16 +03:00
buf [ 1 ] = ' \n ' ;
buf [ 2 ] = ' \0 ' ;
return simple_read_from_buffer ( user_buf , count , ppos , buf , 2 ) ;
}
static ssize_t force_bredr_smp_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct hci_dev * hdev = file - > private_data ;
char buf [ 32 ] ;
size_t buf_size = min ( count , ( sizeof ( buf ) - 1 ) ) ;
bool enable ;
if ( copy_from_user ( buf , user_buf , buf_size ) )
return - EFAULT ;
buf [ buf_size ] = ' \0 ' ;
if ( strtobool ( buf , & enable ) )
return - EINVAL ;
2015-03-13 20:20:35 +03:00
if ( enable = = hci_dev_test_flag ( hdev , HCI_FORCE_BREDR_SMP ) )
2015-01-01 01:43:16 +03:00
return - EALREADY ;
if ( enable ) {
struct l2cap_chan * chan ;
chan = smp_add_cid ( hdev , L2CAP_CID_SMP_BREDR ) ;
if ( IS_ERR ( chan ) )
return PTR_ERR ( chan ) ;
hdev - > smp_bredr_data = chan ;
} else {
struct l2cap_chan * chan ;
chan = hdev - > smp_bredr_data ;
hdev - > smp_bredr_data = NULL ;
smp_del_chan ( chan ) ;
}
2015-03-13 20:20:35 +03:00
hci_dev_change_flag ( hdev , HCI_FORCE_BREDR_SMP ) ;
2015-01-01 01:43:16 +03:00
return count ;
}
static const struct file_operations force_bredr_smp_fops = {
. open = simple_open ,
. read = force_bredr_smp_read ,
. write = force_bredr_smp_write ,
. llseek = default_llseek ,
} ;
2015-06-11 13:52:27 +03:00
static ssize_t le_min_key_size_read ( struct file * file ,
char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct hci_dev * hdev = file - > private_data ;
char buf [ 4 ] ;
snprintf ( buf , sizeof ( buf ) , " %2u \n " , SMP_DEV ( hdev ) - > min_key_size ) ;
return simple_read_from_buffer ( user_buf , count , ppos , buf , strlen ( buf ) ) ;
}
static ssize_t le_min_key_size_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct hci_dev * hdev = file - > private_data ;
char buf [ 32 ] ;
size_t buf_size = min ( count , ( sizeof ( buf ) - 1 ) ) ;
u8 key_size ;
if ( copy_from_user ( buf , user_buf , buf_size ) )
return - EFAULT ;
buf [ buf_size ] = ' \0 ' ;
sscanf ( buf , " %hhu " , & key_size ) ;
if ( key_size > SMP_DEV ( hdev ) - > max_key_size | |
key_size < SMP_MIN_ENC_KEY_SIZE )
return - EINVAL ;
SMP_DEV ( hdev ) - > min_key_size = key_size ;
return count ;
}
static const struct file_operations le_min_key_size_fops = {
. open = simple_open ,
. read = le_min_key_size_read ,
. write = le_min_key_size_write ,
. llseek = default_llseek ,
} ;
2015-06-11 13:52:26 +03:00
static ssize_t le_max_key_size_read ( struct file * file ,
char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct hci_dev * hdev = file - > private_data ;
char buf [ 4 ] ;
snprintf ( buf , sizeof ( buf ) , " %2u \n " , SMP_DEV ( hdev ) - > max_key_size ) ;
return simple_read_from_buffer ( user_buf , count , ppos , buf , strlen ( buf ) ) ;
}
static ssize_t le_max_key_size_write ( struct file * file ,
const char __user * user_buf ,
size_t count , loff_t * ppos )
{
struct hci_dev * hdev = file - > private_data ;
char buf [ 32 ] ;
size_t buf_size = min ( count , ( sizeof ( buf ) - 1 ) ) ;
u8 key_size ;
if ( copy_from_user ( buf , user_buf , buf_size ) )
return - EFAULT ;
buf [ buf_size ] = ' \0 ' ;
sscanf ( buf , " %hhu " , & key_size ) ;
2015-06-11 13:52:27 +03:00
if ( key_size > SMP_MAX_ENC_KEY_SIZE | |
key_size < SMP_DEV ( hdev ) - > min_key_size )
2015-06-11 13:52:26 +03:00
return - EINVAL ;
SMP_DEV ( hdev ) - > max_key_size = key_size ;
return count ;
}
static const struct file_operations le_max_key_size_fops = {
. open = simple_open ,
. read = le_max_key_size_read ,
. write = le_max_key_size_write ,
. llseek = default_llseek ,
} ;
2014-08-13 16:12:32 +04:00
int smp_register ( struct hci_dev * hdev )
{
struct l2cap_chan * chan ;
BT_DBG ( " %s " , hdev - > name ) ;
2015-01-15 02:43:10 +03:00
/* If the controller does not support Low Energy operation, then
* there is also no need to register any SMP channel .
*/
if ( ! lmp_le_capable ( hdev ) )
return 0 ;
2015-01-15 19:04:21 +03:00
if ( WARN_ON ( hdev - > smp_data ) ) {
chan = hdev - > smp_data ;
hdev - > smp_data = NULL ;
smp_del_chan ( chan ) ;
}
2014-08-13 16:12:32 +04:00
chan = smp_add_cid ( hdev , L2CAP_CID_SMP ) ;
if ( IS_ERR ( chan ) )
return PTR_ERR ( chan ) ;
hdev - > smp_data = chan ;
2015-06-11 13:52:27 +03:00
debugfs_create_file ( " le_min_key_size " , 0644 , hdev - > debugfs , hdev ,
& le_min_key_size_fops ) ;
2015-06-11 13:52:26 +03:00
debugfs_create_file ( " le_max_key_size " , 0644 , hdev - > debugfs , hdev ,
& le_max_key_size_fops ) ;
2015-01-01 01:43:16 +03:00
/* If the controller does not support BR/EDR Secure Connections
* feature , then the BR / EDR SMP channel shall not be present .
*
* To test this with Bluetooth 4.0 controllers , create a debugfs
* switch that allows forcing BR / EDR SMP support and accepting
* cross - transport pairing on non - AES encrypted connections .
*/
if ( ! lmp_sc_capable ( hdev ) ) {
debugfs_create_file ( " force_bredr_smp " , 0644 , hdev - > debugfs ,
hdev , & force_bredr_smp_fops ) ;
2014-08-13 16:12:32 +04:00
return 0 ;
2015-01-01 01:43:16 +03:00
}
2014-08-13 16:12:32 +04:00
2015-01-15 19:04:21 +03:00
if ( WARN_ON ( hdev - > smp_bredr_data ) ) {
chan = hdev - > smp_bredr_data ;
hdev - > smp_bredr_data = NULL ;
smp_del_chan ( chan ) ;
}
2014-08-13 16:12:32 +04:00
chan = smp_add_cid ( hdev , L2CAP_CID_SMP_BREDR ) ;
if ( IS_ERR ( chan ) ) {
int err = PTR_ERR ( chan ) ;
chan = hdev - > smp_data ;
hdev - > smp_data = NULL ;
smp_del_chan ( chan ) ;
return err ;
}
hdev - > smp_bredr_data = chan ;
return 0 ;
}
void smp_unregister ( struct hci_dev * hdev )
{
struct l2cap_chan * chan ;
if ( hdev - > smp_bredr_data ) {
chan = hdev - > smp_bredr_data ;
hdev - > smp_bredr_data = NULL ;
smp_del_chan ( chan ) ;
}
if ( hdev - > smp_data ) {
chan = hdev - > smp_data ;
hdev - > smp_data = NULL ;
smp_del_chan ( chan ) ;
}
}
2014-12-30 10:50:39 +03:00
# if IS_ENABLED(CONFIG_BT_SELFTEST_SMP)
2016-01-24 16:18:30 +03:00
static int __init test_ah ( struct crypto_skcipher * tfm_aes )
2014-12-30 10:50:40 +03:00
{
const u8 irk [ 16 ] = {
0x9b , 0x7d , 0x39 , 0x0a , 0xa6 , 0x10 , 0x10 , 0x34 ,
0x05 , 0xad , 0xc8 , 0x57 , 0xa3 , 0x34 , 0x02 , 0xec } ;
const u8 r [ 3 ] = { 0x94 , 0x81 , 0x70 } ;
const u8 exp [ 3 ] = { 0xaa , 0xfb , 0x0d } ;
u8 res [ 3 ] ;
int err ;
err = smp_ah ( tfm_aes , irk , r , res ) ;
if ( err )
return err ;
if ( memcmp ( res , exp , 3 ) )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_c1 ( struct crypto_skcipher * tfm_aes )
2014-12-30 10:50:40 +03:00
{
const u8 k [ 16 ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
const u8 r [ 16 ] = {
0xe0 , 0x2e , 0x70 , 0xc6 , 0x4e , 0x27 , 0x88 , 0x63 ,
0x0e , 0x6f , 0xad , 0x56 , 0x21 , 0xd5 , 0x83 , 0x57 } ;
const u8 preq [ 7 ] = { 0x01 , 0x01 , 0x00 , 0x00 , 0x10 , 0x07 , 0x07 } ;
const u8 pres [ 7 ] = { 0x02 , 0x03 , 0x00 , 0x00 , 0x08 , 0x00 , 0x05 } ;
const u8 _iat = 0x01 ;
const u8 _rat = 0x00 ;
const bdaddr_t ra = { { 0xb6 , 0xb5 , 0xb4 , 0xb3 , 0xb2 , 0xb1 } } ;
const bdaddr_t ia = { { 0xa6 , 0xa5 , 0xa4 , 0xa3 , 0xa2 , 0xa1 } } ;
const u8 exp [ 16 ] = {
0x86 , 0x3b , 0xf1 , 0xbe , 0xc5 , 0x4d , 0xa7 , 0xd2 ,
0xea , 0x88 , 0x89 , 0x87 , 0xef , 0x3f , 0x1e , 0x1e } ;
u8 res [ 16 ] ;
int err ;
err = smp_c1 ( tfm_aes , k , r , preq , pres , _iat , & ia , _rat , & ra , res ) ;
if ( err )
return err ;
if ( memcmp ( res , exp , 16 ) )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_s1 ( struct crypto_skcipher * tfm_aes )
2014-12-30 10:50:40 +03:00
{
const u8 k [ 16 ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
const u8 r1 [ 16 ] = {
0x88 , 0x77 , 0x66 , 0x55 , 0x44 , 0x33 , 0x22 , 0x11 } ;
const u8 r2 [ 16 ] = {
0x00 , 0xff , 0xee , 0xdd , 0xcc , 0xbb , 0xaa , 0x99 } ;
const u8 exp [ 16 ] = {
0x62 , 0xa0 , 0x6d , 0x79 , 0xae , 0x16 , 0x42 , 0x5b ,
0x9b , 0xf4 , 0xb0 , 0xe8 , 0xf0 , 0xe1 , 0x1f , 0x9a } ;
u8 res [ 16 ] ;
int err ;
err = smp_s1 ( tfm_aes , k , r1 , r2 , res ) ;
if ( err )
return err ;
if ( memcmp ( res , exp , 16 ) )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_f4 ( struct crypto_shash * tfm_cmac )
2014-12-30 10:50:41 +03:00
{
const u8 u [ 32 ] = {
0xe6 , 0x9d , 0x35 , 0x0e , 0x48 , 0x01 , 0x03 , 0xcc ,
0xdb , 0xfd , 0xf4 , 0xac , 0x11 , 0x91 , 0xf4 , 0xef ,
0xb9 , 0xa5 , 0xf9 , 0xe9 , 0xa7 , 0x83 , 0x2c , 0x5e ,
0x2c , 0xbe , 0x97 , 0xf2 , 0xd2 , 0x03 , 0xb0 , 0x20 } ;
const u8 v [ 32 ] = {
0xfd , 0xc5 , 0x7f , 0xf4 , 0x49 , 0xdd , 0x4f , 0x6b ,
0xfb , 0x7c , 0x9d , 0xf1 , 0xc2 , 0x9a , 0xcb , 0x59 ,
0x2a , 0xe7 , 0xd4 , 0xee , 0xfb , 0xfc , 0x0a , 0x90 ,
0x9a , 0xbb , 0xf6 , 0x32 , 0x3d , 0x8b , 0x18 , 0x55 } ;
const u8 x [ 16 ] = {
0xab , 0xae , 0x2b , 0x71 , 0xec , 0xb2 , 0xff , 0xff ,
0x3e , 0x73 , 0x77 , 0xd1 , 0x54 , 0x84 , 0xcb , 0xd5 } ;
const u8 z = 0x00 ;
const u8 exp [ 16 ] = {
0x2d , 0x87 , 0x74 , 0xa9 , 0xbe , 0xa1 , 0xed , 0xf1 ,
0x1c , 0xbd , 0xa9 , 0x07 , 0xf1 , 0x16 , 0xc9 , 0xf2 } ;
u8 res [ 16 ] ;
int err ;
err = smp_f4 ( tfm_cmac , u , v , x , z , res ) ;
if ( err )
return err ;
if ( memcmp ( res , exp , 16 ) )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_f5 ( struct crypto_shash * tfm_cmac )
2014-12-30 10:50:41 +03:00
{
const u8 w [ 32 ] = {
0x98 , 0xa6 , 0xbf , 0x73 , 0xf3 , 0x34 , 0x8d , 0x86 ,
0xf1 , 0x66 , 0xf8 , 0xb4 , 0x13 , 0x6b , 0x79 , 0x99 ,
0x9b , 0x7d , 0x39 , 0x0a , 0xa6 , 0x10 , 0x10 , 0x34 ,
0x05 , 0xad , 0xc8 , 0x57 , 0xa3 , 0x34 , 0x02 , 0xec } ;
const u8 n1 [ 16 ] = {
0xab , 0xae , 0x2b , 0x71 , 0xec , 0xb2 , 0xff , 0xff ,
0x3e , 0x73 , 0x77 , 0xd1 , 0x54 , 0x84 , 0xcb , 0xd5 } ;
const u8 n2 [ 16 ] = {
0xcf , 0xc4 , 0x3d , 0xff , 0xf7 , 0x83 , 0x65 , 0x21 ,
0x6e , 0x5f , 0xa7 , 0x25 , 0xcc , 0xe7 , 0xe8 , 0xa6 } ;
const u8 a1 [ 7 ] = { 0xce , 0xbf , 0x37 , 0x37 , 0x12 , 0x56 , 0x00 } ;
const u8 a2 [ 7 ] = { 0xc1 , 0xcf , 0x2d , 0x70 , 0x13 , 0xa7 , 0x00 } ;
const u8 exp_ltk [ 16 ] = {
0x38 , 0x0a , 0x75 , 0x94 , 0xb5 , 0x22 , 0x05 , 0x98 ,
0x23 , 0xcd , 0xd7 , 0x69 , 0x11 , 0x79 , 0x86 , 0x69 } ;
const u8 exp_mackey [ 16 ] = {
0x20 , 0x6e , 0x63 , 0xce , 0x20 , 0x6a , 0x3f , 0xfd ,
0x02 , 0x4a , 0x08 , 0xa1 , 0x76 , 0xf1 , 0x65 , 0x29 } ;
u8 mackey [ 16 ] , ltk [ 16 ] ;
int err ;
err = smp_f5 ( tfm_cmac , w , n1 , n2 , a1 , a2 , mackey , ltk ) ;
if ( err )
return err ;
if ( memcmp ( mackey , exp_mackey , 16 ) )
return - EINVAL ;
if ( memcmp ( ltk , exp_ltk , 16 ) )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_f6 ( struct crypto_shash * tfm_cmac )
2014-12-30 10:50:41 +03:00
{
const u8 w [ 16 ] = {
0x20 , 0x6e , 0x63 , 0xce , 0x20 , 0x6a , 0x3f , 0xfd ,
0x02 , 0x4a , 0x08 , 0xa1 , 0x76 , 0xf1 , 0x65 , 0x29 } ;
const u8 n1 [ 16 ] = {
0xab , 0xae , 0x2b , 0x71 , 0xec , 0xb2 , 0xff , 0xff ,
0x3e , 0x73 , 0x77 , 0xd1 , 0x54 , 0x84 , 0xcb , 0xd5 } ;
const u8 n2 [ 16 ] = {
0xcf , 0xc4 , 0x3d , 0xff , 0xf7 , 0x83 , 0x65 , 0x21 ,
0x6e , 0x5f , 0xa7 , 0x25 , 0xcc , 0xe7 , 0xe8 , 0xa6 } ;
const u8 r [ 16 ] = {
0xc8 , 0x0f , 0x2d , 0x0c , 0xd2 , 0x42 , 0xda , 0x08 ,
0x54 , 0xbb , 0x53 , 0xb4 , 0x3b , 0x34 , 0xa3 , 0x12 } ;
const u8 io_cap [ 3 ] = { 0x02 , 0x01 , 0x01 } ;
const u8 a1 [ 7 ] = { 0xce , 0xbf , 0x37 , 0x37 , 0x12 , 0x56 , 0x00 } ;
const u8 a2 [ 7 ] = { 0xc1 , 0xcf , 0x2d , 0x70 , 0x13 , 0xa7 , 0x00 } ;
const u8 exp [ 16 ] = {
0x61 , 0x8f , 0x95 , 0xda , 0x09 , 0x0b , 0x6c , 0xd2 ,
0xc5 , 0xe8 , 0xd0 , 0x9c , 0x98 , 0x73 , 0xc4 , 0xe3 } ;
u8 res [ 16 ] ;
int err ;
err = smp_f6 ( tfm_cmac , w , n1 , n2 , r , io_cap , a1 , a2 , res ) ;
if ( err )
return err ;
if ( memcmp ( res , exp , 16 ) )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_g2 ( struct crypto_shash * tfm_cmac )
2014-12-30 10:50:41 +03:00
{
const u8 u [ 32 ] = {
0xe6 , 0x9d , 0x35 , 0x0e , 0x48 , 0x01 , 0x03 , 0xcc ,
0xdb , 0xfd , 0xf4 , 0xac , 0x11 , 0x91 , 0xf4 , 0xef ,
0xb9 , 0xa5 , 0xf9 , 0xe9 , 0xa7 , 0x83 , 0x2c , 0x5e ,
0x2c , 0xbe , 0x97 , 0xf2 , 0xd2 , 0x03 , 0xb0 , 0x20 } ;
const u8 v [ 32 ] = {
0xfd , 0xc5 , 0x7f , 0xf4 , 0x49 , 0xdd , 0x4f , 0x6b ,
0xfb , 0x7c , 0x9d , 0xf1 , 0xc2 , 0x9a , 0xcb , 0x59 ,
0x2a , 0xe7 , 0xd4 , 0xee , 0xfb , 0xfc , 0x0a , 0x90 ,
0x9a , 0xbb , 0xf6 , 0x32 , 0x3d , 0x8b , 0x18 , 0x55 } ;
const u8 x [ 16 ] = {
0xab , 0xae , 0x2b , 0x71 , 0xec , 0xb2 , 0xff , 0xff ,
0x3e , 0x73 , 0x77 , 0xd1 , 0x54 , 0x84 , 0xcb , 0xd5 } ;
const u8 y [ 16 ] = {
0xcf , 0xc4 , 0x3d , 0xff , 0xf7 , 0x83 , 0x65 , 0x21 ,
0x6e , 0x5f , 0xa7 , 0x25 , 0xcc , 0xe7 , 0xe8 , 0xa6 } ;
const u32 exp_val = 0x2f9ed5ba % 1000000 ;
u32 val ;
int err ;
err = smp_g2 ( tfm_cmac , u , v , x , y , & val ) ;
if ( err )
return err ;
if ( val ! = exp_val )
return - EINVAL ;
return 0 ;
}
2016-01-24 16:18:30 +03:00
static int __init test_h6 ( struct crypto_shash * tfm_cmac )
2014-12-30 10:50:41 +03:00
{
const u8 w [ 16 ] = {
0x9b , 0x7d , 0x39 , 0x0a , 0xa6 , 0x10 , 0x10 , 0x34 ,
0x05 , 0xad , 0xc8 , 0x57 , 0xa3 , 0x34 , 0x02 , 0xec } ;
const u8 key_id [ 4 ] = { 0x72 , 0x62 , 0x65 , 0x6c } ;
const u8 exp [ 16 ] = {
0x99 , 0x63 , 0xb1 , 0x80 , 0xe2 , 0xa9 , 0xd3 , 0xe8 ,
0x1c , 0xc9 , 0x6d , 0xe7 , 0x02 , 0xe1 , 0x9a , 0x2d } ;
u8 res [ 16 ] ;
int err ;
err = smp_h6 ( tfm_cmac , w , key_id , res ) ;
if ( err )
return err ;
if ( memcmp ( res , exp , 16 ) )
return - EINVAL ;
return 0 ;
}
2015-04-01 22:52:13 +03:00
static char test_smp_buffer [ 32 ] ;
static ssize_t test_smp_read ( struct file * file , char __user * user_buf ,
size_t count , loff_t * ppos )
{
return simple_read_from_buffer ( user_buf , count , ppos , test_smp_buffer ,
strlen ( test_smp_buffer ) ) ;
}
static const struct file_operations test_smp_fops = {
. open = simple_open ,
. read = test_smp_read ,
. llseek = default_llseek ,
} ;
2016-01-24 16:18:30 +03:00
static int __init run_selftests ( struct crypto_skcipher * tfm_aes ,
struct crypto_shash * tfm_cmac )
2014-12-30 10:50:39 +03:00
{
2014-12-30 11:11:20 +03:00
ktime_t calltime , delta , rettime ;
unsigned long long duration ;
2014-12-30 10:50:40 +03:00
int err ;
2014-12-30 11:11:20 +03:00
calltime = ktime_get ( ) ;
2014-12-30 10:50:40 +03:00
err = test_ah ( tfm_aes ) ;
if ( err ) {
BT_ERR ( " smp_ah test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:40 +03:00
}
err = test_c1 ( tfm_aes ) ;
if ( err ) {
BT_ERR ( " smp_c1 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:40 +03:00
}
err = test_s1 ( tfm_aes ) ;
if ( err ) {
BT_ERR ( " smp_s1 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:40 +03:00
}
2014-12-30 10:50:41 +03:00
err = test_f4 ( tfm_cmac ) ;
if ( err ) {
BT_ERR ( " smp_f4 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:41 +03:00
}
err = test_f5 ( tfm_cmac ) ;
if ( err ) {
BT_ERR ( " smp_f5 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:41 +03:00
}
err = test_f6 ( tfm_cmac ) ;
if ( err ) {
BT_ERR ( " smp_f6 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:41 +03:00
}
err = test_g2 ( tfm_cmac ) ;
if ( err ) {
BT_ERR ( " smp_g2 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:41 +03:00
}
err = test_h6 ( tfm_cmac ) ;
if ( err ) {
BT_ERR ( " smp_h6 test failed " ) ;
2015-04-01 22:52:13 +03:00
goto done ;
2014-12-30 10:50:41 +03:00
}
2014-12-30 11:11:20 +03:00
rettime = ktime_get ( ) ;
delta = ktime_sub ( rettime , calltime ) ;
duration = ( unsigned long long ) ktime_to_ns ( delta ) > > 10 ;
2015-01-13 10:09:48 +03:00
BT_INFO ( " SMP test passed in %llu usecs " , duration ) ;
2014-12-30 10:50:39 +03:00
2015-04-01 22:52:13 +03:00
done :
if ( ! err )
snprintf ( test_smp_buffer , sizeof ( test_smp_buffer ) ,
" PASS (%llu usecs) \n " , duration ) ;
else
snprintf ( test_smp_buffer , sizeof ( test_smp_buffer ) , " FAIL \n " ) ;
debugfs_create_file ( " selftest_smp " , 0444 , bt_debugfs , NULL ,
& test_smp_fops ) ;
return err ;
2014-12-30 10:50:39 +03:00
}
int __init bt_selftest_smp ( void )
{
2016-01-24 16:18:30 +03:00
struct crypto_skcipher * tfm_aes ;
struct crypto_shash * tfm_cmac ;
2014-12-30 10:50:39 +03:00
int err ;
2016-01-24 16:18:30 +03:00
tfm_aes = crypto_alloc_skcipher ( " ecb(aes) " , 0 , CRYPTO_ALG_ASYNC ) ;
2014-12-30 10:50:39 +03:00
if ( IS_ERR ( tfm_aes ) ) {
BT_ERR ( " Unable to create ECB crypto context " ) ;
return PTR_ERR ( tfm_aes ) ;
}
2016-01-24 16:18:30 +03:00
tfm_cmac = crypto_alloc_shash ( " cmac(aes) " , 0 , CRYPTO_ALG_ASYNC ) ;
2014-12-30 10:50:39 +03:00
if ( IS_ERR ( tfm_cmac ) ) {
BT_ERR ( " Unable to create CMAC crypto context " ) ;
2016-01-24 16:18:30 +03:00
crypto_free_skcipher ( tfm_aes ) ;
2014-12-30 10:50:39 +03:00
return PTR_ERR ( tfm_cmac ) ;
}
err = run_selftests ( tfm_aes , tfm_cmac ) ;
2016-01-24 16:18:30 +03:00
crypto_free_shash ( tfm_cmac ) ;
crypto_free_skcipher ( tfm_aes ) ;
2014-12-30 10:50:39 +03:00
return err ;
}
# endif