aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/smp.c
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 /net/bluetooth/smp.c
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>
Diffstat (limited to 'net/bluetooth/smp.c')
-rw-r--r--net/bluetooth/smp.c54
1 files changed, 41 insertions, 13 deletions
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;