diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-06-06 04:30:08 -0400 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-12-03 10:51:17 -0500 |
commit | cbbbe3e242f5629fd34836e7e41737235c049ce2 (patch) | |
tree | 16f7b71216549669b67a464b39a8083cfda7914d | |
parent | d8f8edbe93979bdf1f74cd768e68c7705806f0b9 (diff) |
Bluetooth: Add support for sending LE SC Confirm value
Once the public key exchange is complete the next step is for the
non-initiating device to send a SMP Pairing Confirm PDU to the
initiating device. This requires the use of a new smp_f4 confirm value
generation function which in turn builds on the AES-CMAC cryptographic
function.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r-- | net/bluetooth/smp.c | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 1cc438c9c2cb..0980b86574bd 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -43,6 +43,9 @@ | |||
43 | 0x1f : 0x07) | 43 | 0x1f : 0x07) |
44 | #define KEY_DIST_MASK 0x07 | 44 | #define KEY_DIST_MASK 0x07 |
45 | 45 | ||
46 | /* Maximum message length that can be passed to aes_cmac */ | ||
47 | #define CMAC_MSG_MAX 80 | ||
48 | |||
46 | enum { | 49 | enum { |
47 | SMP_FLAG_TK_VALID, | 50 | SMP_FLAG_TK_VALID, |
48 | SMP_FLAG_CFM_PENDING, | 51 | SMP_FLAG_CFM_PENDING, |
@@ -94,6 +97,84 @@ static inline void swap_buf(const u8 *src, u8 *dst, size_t len) | |||
94 | dst[len - 1 - i] = src[i]; | 97 | dst[len - 1 - i] = src[i]; |
95 | } | 98 | } |
96 | 99 | ||
100 | static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m, | ||
101 | size_t len, u8 mac[16]) | ||
102 | { | ||
103 | uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX]; | ||
104 | struct hash_desc desc; | ||
105 | struct scatterlist sg; | ||
106 | int err; | ||
107 | |||
108 | if (len > CMAC_MSG_MAX) | ||
109 | return -EFBIG; | ||
110 | |||
111 | if (!tfm) { | ||
112 | BT_ERR("tfm %p", tfm); | ||
113 | return -EINVAL; | ||
114 | } | ||
115 | |||
116 | desc.tfm = tfm; | ||
117 | desc.flags = 0; | ||
118 | |||
119 | crypto_hash_init(&desc); | ||
120 | |||
121 | /* Swap key and message from LSB to MSB */ | ||
122 | swap_buf(k, tmp, 16); | ||
123 | swap_buf(m, msg_msb, len); | ||
124 | |||
125 | BT_DBG("msg (len %zu) %*phN", len, (int) len, m); | ||
126 | BT_DBG("key %16phN", k); | ||
127 | |||
128 | err = crypto_hash_setkey(tfm, tmp, 16); | ||
129 | if (err) { | ||
130 | BT_ERR("cipher setkey failed: %d", err); | ||
131 | return err; | ||
132 | } | ||
133 | |||
134 | sg_init_one(&sg, msg_msb, len); | ||
135 | |||
136 | err = crypto_hash_update(&desc, &sg, len); | ||
137 | if (err) { | ||
138 | BT_ERR("Hash update error %d", err); | ||
139 | return err; | ||
140 | } | ||
141 | |||
142 | err = crypto_hash_final(&desc, mac_msb); | ||
143 | if (err) { | ||
144 | BT_ERR("Hash final error %d", err); | ||
145 | return err; | ||
146 | } | ||
147 | |||
148 | swap_buf(mac_msb, mac, 16); | ||
149 | |||
150 | BT_DBG("mac %16phN", mac); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32], | ||
156 | const u8 x[16], u8 z, u8 res[16]) | ||
157 | { | ||
158 | u8 m[65]; | ||
159 | int err; | ||
160 | |||
161 | BT_DBG("u %32phN", u); | ||
162 | BT_DBG("v %32phN", v); | ||
163 | BT_DBG("x %16phN z %02x", x, z); | ||
164 | |||
165 | m[0] = z; | ||
166 | memcpy(m + 1, v, 32); | ||
167 | memcpy(m + 33, u, 32); | ||
168 | |||
169 | err = aes_cmac(tfm_cmac, x, m, sizeof(m), res); | ||
170 | if (err) | ||
171 | return err; | ||
172 | |||
173 | BT_DBG("res %16phN", res); | ||
174 | |||
175 | return err; | ||
176 | } | ||
177 | |||
97 | static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | 178 | static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) |
98 | { | 179 | { |
99 | struct blkcipher_desc desc; | 180 | struct blkcipher_desc desc; |
@@ -1522,6 +1603,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1522 | struct hci_conn *hcon = conn->hcon; | 1603 | struct hci_conn *hcon = conn->hcon; |
1523 | struct l2cap_chan *chan = conn->smp; | 1604 | struct l2cap_chan *chan = conn->smp; |
1524 | struct smp_chan *smp = chan->data; | 1605 | struct smp_chan *smp = chan->data; |
1606 | struct smp_cmd_pairing_confirm cfm; | ||
1525 | int err; | 1607 | int err; |
1526 | 1608 | ||
1527 | BT_DBG("conn %p", conn); | 1609 | BT_DBG("conn %p", conn); |
@@ -1550,6 +1632,20 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1550 | 1632 | ||
1551 | set_bit(SMP_FLAG_REMOTE_PK, &smp->flags); | 1633 | set_bit(SMP_FLAG_REMOTE_PK, &smp->flags); |
1552 | 1634 | ||
1635 | /* The Initiating device waits for the non-initiating device to | ||
1636 | * send the confirm value. | ||
1637 | */ | ||
1638 | if (conn->hcon->out) | ||
1639 | return 0; | ||
1640 | |||
1641 | err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, | ||
1642 | 0, cfm.confirm_val); | ||
1643 | if (err) | ||
1644 | return SMP_UNSPECIFIED; | ||
1645 | |||
1646 | smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm); | ||
1647 | SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM); | ||
1648 | |||
1553 | return 0; | 1649 | return 0; |
1554 | } | 1650 | } |
1555 | 1651 | ||