aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVinicius Costa Gomes <vinicius.gomes@openbossa.org>2011-06-14 12:37:42 -0400
committerGustavo F. Padovan <padovan@profusion.mobi>2011-06-14 13:54:10 -0400
commit3158c50c33c1acddcfa3c57fab812435aa459750 (patch)
tree24c74d141b44a26e788f4ce0e22767fd28ba9720
parent5d3de7df18077a0f508ae2c3e3f1866da65fdffd (diff)
Bluetooth: Add key size checks for SMP
This patch implements a check in smp cmd pairing request and pairing response to verify if encryption key maximum size is compatible in both slave and master when SMP Pairing is requested. Keys are also masked to the correct negotiated size. Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@openbossa.org> Signed-off-by: Anderson Briglia <anderson.briglia@openbossa.org> Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r--include/net/bluetooth/l2cap.h1
-rw-r--r--include/net/bluetooth/smp.h3
-rw-r--r--net/bluetooth/smp.c54
3 files changed, 45 insertions, 13 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 157419afe532..bf1c7f681932 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -400,6 +400,7 @@ struct l2cap_conn {
400 __u8 prnd[16]; /* SMP Pairing Random */ 400 __u8 prnd[16]; /* SMP Pairing Random */
401 __u8 pcnf[16]; /* SMP Pairing Confirm */ 401 __u8 pcnf[16]; /* SMP Pairing Confirm */
402 __u8 tk[16]; /* SMP Temporary Key */ 402 __u8 tk[16]; /* SMP Temporary Key */
403 __u8 smp_key_size;
403 404
404 struct timer_list security_timer; 405 struct timer_list security_timer;
405 406
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 111853ab239a..4fb7d198a876 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -112,6 +112,9 @@ struct smp_cmd_security_req {
112#define SMP_UNSPECIFIED 0x08 112#define SMP_UNSPECIFIED 0x08
113#define SMP_REPEATED_ATTEMPTS 0x09 113#define SMP_REPEATED_ATTEMPTS 0x09
114 114
115#define SMP_MIN_ENC_KEY_SIZE 7
116#define SMP_MAX_ENC_KEY_SIZE 16
117
115/* SMP Commands */ 118/* SMP Commands */
116int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level); 119int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
117int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); 120int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 39886786eb7f..52e9ec2644c1 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -200,35 +200,51 @@ static void build_pairing_cmd(struct l2cap_conn *conn,
200{ 200{
201 cmd->io_capability = conn->hcon->io_capability; 201 cmd->io_capability = conn->hcon->io_capability;
202 cmd->oob_flag = SMP_OOB_NOT_PRESENT; 202 cmd->oob_flag = SMP_OOB_NOT_PRESENT;
203 cmd->max_key_size = 16; 203 cmd->max_key_size = SMP_MAX_ENC_KEY_SIZE;
204 cmd->init_key_dist = 0x00; 204 cmd->init_key_dist = 0x00;
205 cmd->resp_key_dist = 0x00; 205 cmd->resp_key_dist = 0x00;
206 cmd->auth_req = authreq; 206 cmd->auth_req = authreq;
207} 207}
208 208
209static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size)
210{
211 if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) ||
212 (max_key_size < SMP_MIN_ENC_KEY_SIZE))
213 return SMP_ENC_KEY_SIZE;
214
215 conn->smp_key_size = max_key_size;
216
217 return 0;
218}
219
209static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) 220static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
210{ 221{
211 struct smp_cmd_pairing *rp = (void *) skb->data; 222 struct smp_cmd_pairing rsp, *req = (void *) skb->data;
223 u8 key_size;
212 224
213 BT_DBG("conn %p", conn); 225 BT_DBG("conn %p", conn);
214 226
215 conn->preq[0] = SMP_CMD_PAIRING_REQ; 227 conn->preq[0] = SMP_CMD_PAIRING_REQ;
216 memcpy(&conn->preq[1], rp, sizeof(*rp)); 228 memcpy(&conn->preq[1], req, sizeof(*req));
217 skb_pull(skb, sizeof(*rp)); 229 skb_pull(skb, sizeof(*req));
218 230
219 if (rp->oob_flag) 231 if (req->oob_flag)
220 return SMP_OOB_NOT_AVAIL; 232 return SMP_OOB_NOT_AVAIL;
221 233
222 /* We didn't start the pairing, so no requirements */ 234 /* We didn't start the pairing, so no requirements */
223 build_pairing_cmd(conn, rp, SMP_AUTH_NONE); 235 build_pairing_cmd(conn, &rsp, SMP_AUTH_NONE);
236
237 key_size = min(req->max_key_size, rsp.max_key_size);
238 if (check_enc_key_size(conn, key_size))
239 return SMP_ENC_KEY_SIZE;
224 240
225 /* Just works */ 241 /* Just works */
226 memset(conn->tk, 0, sizeof(conn->tk)); 242 memset(conn->tk, 0, sizeof(conn->tk));
227 243
228 conn->prsp[0] = SMP_CMD_PAIRING_RSP; 244 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
229 memcpy(&conn->prsp[1], rp, sizeof(*rp)); 245 memcpy(&conn->prsp[1], &rsp, sizeof(rsp));
230 246
231 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(*rp), rp); 247 smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
232 248
233 mod_timer(&conn->security_timer, jiffies + 249 mod_timer(&conn->security_timer, jiffies +
234 msecs_to_jiffies(SMP_TIMEOUT)); 250 msecs_to_jiffies(SMP_TIMEOUT));
@@ -238,24 +254,30 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
238 254
239static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) 255static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
240{ 256{
241 struct smp_cmd_pairing *rp = (void *) skb->data; 257 struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
242 struct smp_cmd_pairing_confirm cp; 258 struct smp_cmd_pairing_confirm cp;
243 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm; 259 struct crypto_blkcipher *tfm = conn->hcon->hdev->tfm;
244 int ret; 260 int ret;
245 u8 res[16]; 261 u8 res[16], key_size;
246 262
247 BT_DBG("conn %p", conn); 263 BT_DBG("conn %p", conn);
248 264
249 skb_pull(skb, sizeof(*rp)); 265 skb_pull(skb, sizeof(*rsp));
266
267 req = (void *) &conn->preq[1];
250 268
251 if (rp->oob_flag) 269 key_size = min(req->max_key_size, rsp->max_key_size);
270 if (check_enc_key_size(conn, key_size))
271 return SMP_ENC_KEY_SIZE;
272
273 if (rsp->oob_flag)
252 return SMP_OOB_NOT_AVAIL; 274 return SMP_OOB_NOT_AVAIL;
253 275
254 /* Just works */ 276 /* Just works */
255 memset(conn->tk, 0, sizeof(conn->tk)); 277 memset(conn->tk, 0, sizeof(conn->tk));
256 278
257 conn->prsp[0] = SMP_CMD_PAIRING_RSP; 279 conn->prsp[0] = SMP_CMD_PAIRING_RSP;
258 memcpy(&conn->prsp[1], rp, sizeof(*rp)); 280 memcpy(&conn->prsp[1], rsp, sizeof(*rsp));
259 281
260 ret = smp_rand(conn->prnd); 282 ret = smp_rand(conn->prnd);
261 if (ret) 283 if (ret)
@@ -353,6 +375,9 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
353 smp_s1(tfm, conn->tk, random, conn->prnd, key); 375 smp_s1(tfm, conn->tk, random, conn->prnd, key);
354 swap128(key, hcon->ltk); 376 swap128(key, hcon->ltk);
355 377
378 memset(hcon->ltk + conn->smp_key_size, 0,
379 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
380
356 memset(rand, 0, sizeof(rand)); 381 memset(rand, 0, sizeof(rand));
357 ediv = 0; 382 ediv = 0;
358 hci_le_start_enc(hcon, ediv, rand, hcon->ltk); 383 hci_le_start_enc(hcon, ediv, rand, hcon->ltk);
@@ -364,6 +389,9 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
364 389
365 smp_s1(tfm, conn->tk, conn->prnd, random, key); 390 smp_s1(tfm, conn->tk, conn->prnd, random, key);
366 swap128(key, hcon->ltk); 391 swap128(key, hcon->ltk);
392
393 memset(hcon->ltk + conn->smp_key_size, 0,
394 SMP_MAX_ENC_KEY_SIZE - conn->smp_key_size);
367 } 395 }
368 396
369 return 0; 397 return 0;