diff options
author | Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | 2014-05-16 11:46:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-16 17:23:41 -0400 |
commit | f30be4d53cada48598dab0983866ae4b16af46dc (patch) | |
tree | 032e1761fd2a0f7ea4bb09f828d3938c99085725 /net/mac802154/wpan.c | |
parent | 4c14a2fb5d143e4ed94143be2b8c1961b47df9af (diff) |
mac802154: integrate llsec with wpan devices
Signed-off-by: Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/mac802154/wpan.c')
-rw-r--r-- | net/mac802154/wpan.c | 118 |
1 files changed, 90 insertions, 28 deletions
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c index ed105774c15d..00729ca1e30a 100644 --- a/net/mac802154/wpan.c +++ b/net/mac802154/wpan.c | |||
@@ -183,6 +183,38 @@ out: | |||
183 | return rc; | 183 | return rc; |
184 | } | 184 | } |
185 | 185 | ||
186 | static int mac802154_set_header_security(struct mac802154_sub_if_data *priv, | ||
187 | struct ieee802154_hdr *hdr, | ||
188 | const struct ieee802154_mac_cb *cb) | ||
189 | { | ||
190 | struct ieee802154_llsec_params params; | ||
191 | u8 level; | ||
192 | |||
193 | mac802154_llsec_get_params(&priv->sec, ¶ms); | ||
194 | |||
195 | if (!params.enabled && cb->secen_override && cb->secen) | ||
196 | return -EINVAL; | ||
197 | if (!params.enabled || | ||
198 | (cb->secen_override && !cb->secen) || | ||
199 | !params.out_level) | ||
200 | return 0; | ||
201 | if (cb->seclevel_override && !cb->seclevel) | ||
202 | return -EINVAL; | ||
203 | |||
204 | level = cb->seclevel_override ? cb->seclevel : params.out_level; | ||
205 | |||
206 | hdr->fc.security_enabled = 1; | ||
207 | hdr->sec.level = level; | ||
208 | hdr->sec.key_id_mode = params.out_key.mode; | ||
209 | if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX) | ||
210 | hdr->sec.short_src = params.out_key.short_source; | ||
211 | else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX) | ||
212 | hdr->sec.extended_src = params.out_key.extended_source; | ||
213 | hdr->sec.key_id = params.out_key.id; | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
186 | static int mac802154_header_create(struct sk_buff *skb, | 218 | static int mac802154_header_create(struct sk_buff *skb, |
187 | struct net_device *dev, | 219 | struct net_device *dev, |
188 | unsigned short type, | 220 | unsigned short type, |
@@ -204,6 +236,9 @@ static int mac802154_header_create(struct sk_buff *skb, | |||
204 | hdr.fc.ack_request = cb->ackreq; | 236 | hdr.fc.ack_request = cb->ackreq; |
205 | hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev); | 237 | hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev); |
206 | 238 | ||
239 | if (mac802154_set_header_security(priv, &hdr, cb) < 0) | ||
240 | return -EINVAL; | ||
241 | |||
207 | if (!saddr) { | 242 | if (!saddr) { |
208 | spin_lock_bh(&priv->mib_lock); | 243 | spin_lock_bh(&priv->mib_lock); |
209 | 244 | ||
@@ -259,6 +294,7 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
259 | { | 294 | { |
260 | struct mac802154_sub_if_data *priv; | 295 | struct mac802154_sub_if_data *priv; |
261 | u8 chan, page; | 296 | u8 chan, page; |
297 | int rc; | ||
262 | 298 | ||
263 | priv = netdev_priv(dev); | 299 | priv = netdev_priv(dev); |
264 | 300 | ||
@@ -274,6 +310,13 @@ mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
274 | return NETDEV_TX_OK; | 310 | return NETDEV_TX_OK; |
275 | } | 311 | } |
276 | 312 | ||
313 | rc = mac802154_llsec_encrypt(&priv->sec, skb); | ||
314 | if (rc) { | ||
315 | pr_warn("encryption failed: %i\n", rc); | ||
316 | kfree_skb(skb); | ||
317 | return NETDEV_TX_OK; | ||
318 | } | ||
319 | |||
277 | skb->skb_iif = dev->ifindex; | 320 | skb->skb_iif = dev->ifindex; |
278 | dev->stats.tx_packets++; | 321 | dev->stats.tx_packets++; |
279 | dev->stats.tx_bytes += skb->len; | 322 | dev->stats.tx_bytes += skb->len; |
@@ -294,6 +337,15 @@ static const struct net_device_ops mac802154_wpan_ops = { | |||
294 | .ndo_set_mac_address = mac802154_wpan_mac_addr, | 337 | .ndo_set_mac_address = mac802154_wpan_mac_addr, |
295 | }; | 338 | }; |
296 | 339 | ||
340 | static void mac802154_wpan_free(struct net_device *dev) | ||
341 | { | ||
342 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | ||
343 | |||
344 | mac802154_llsec_destroy(&priv->sec); | ||
345 | |||
346 | free_netdev(dev); | ||
347 | } | ||
348 | |||
297 | void mac802154_wpan_setup(struct net_device *dev) | 349 | void mac802154_wpan_setup(struct net_device *dev) |
298 | { | 350 | { |
299 | struct mac802154_sub_if_data *priv; | 351 | struct mac802154_sub_if_data *priv; |
@@ -303,14 +355,14 @@ void mac802154_wpan_setup(struct net_device *dev) | |||
303 | 355 | ||
304 | dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; | 356 | dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN; |
305 | dev->header_ops = &mac802154_header_ops; | 357 | dev->header_ops = &mac802154_header_ops; |
306 | dev->needed_tailroom = 2; /* FCS */ | 358 | dev->needed_tailroom = 2 + 16; /* FCS + MIC */ |
307 | dev->mtu = IEEE802154_MTU; | 359 | dev->mtu = IEEE802154_MTU; |
308 | dev->tx_queue_len = 300; | 360 | dev->tx_queue_len = 300; |
309 | dev->type = ARPHRD_IEEE802154; | 361 | dev->type = ARPHRD_IEEE802154; |
310 | dev->flags = IFF_NOARP | IFF_BROADCAST; | 362 | dev->flags = IFF_NOARP | IFF_BROADCAST; |
311 | dev->watchdog_timeo = 0; | 363 | dev->watchdog_timeo = 0; |
312 | 364 | ||
313 | dev->destructor = free_netdev; | 365 | dev->destructor = mac802154_wpan_free; |
314 | dev->netdev_ops = &mac802154_wpan_ops; | 366 | dev->netdev_ops = &mac802154_wpan_ops; |
315 | dev->ml_priv = &mac802154_mlme_wpan; | 367 | dev->ml_priv = &mac802154_mlme_wpan; |
316 | 368 | ||
@@ -321,6 +373,7 @@ void mac802154_wpan_setup(struct net_device *dev) | |||
321 | priv->page = 0; | 373 | priv->page = 0; |
322 | 374 | ||
323 | spin_lock_init(&priv->mib_lock); | 375 | spin_lock_init(&priv->mib_lock); |
376 | mutex_init(&priv->sec_mtx); | ||
324 | 377 | ||
325 | get_random_bytes(&priv->bsn, 1); | 378 | get_random_bytes(&priv->bsn, 1); |
326 | get_random_bytes(&priv->dsn, 1); | 379 | get_random_bytes(&priv->dsn, 1); |
@@ -333,6 +386,8 @@ void mac802154_wpan_setup(struct net_device *dev) | |||
333 | 386 | ||
334 | priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); | 387 | priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); |
335 | priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); | 388 | priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); |
389 | |||
390 | mac802154_llsec_init(&priv->sec); | ||
336 | } | 391 | } |
337 | 392 | ||
338 | static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) | 393 | static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) |
@@ -341,9 +396,11 @@ static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) | |||
341 | } | 396 | } |
342 | 397 | ||
343 | static int | 398 | static int |
344 | mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) | 399 | mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb, |
400 | const struct ieee802154_hdr *hdr) | ||
345 | { | 401 | { |
346 | __le16 span, sshort; | 402 | __le16 span, sshort; |
403 | int rc; | ||
347 | 404 | ||
348 | pr_debug("getting packet via slave interface %s\n", sdata->dev->name); | 405 | pr_debug("getting packet via slave interface %s\n", sdata->dev->name); |
349 | 406 | ||
@@ -390,6 +447,12 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) | |||
390 | 447 | ||
391 | skb->dev = sdata->dev; | 448 | skb->dev = sdata->dev; |
392 | 449 | ||
450 | rc = mac802154_llsec_decrypt(&sdata->sec, skb); | ||
451 | if (rc) { | ||
452 | pr_debug("decryption failed: %i\n", rc); | ||
453 | return NET_RX_DROP; | ||
454 | } | ||
455 | |||
393 | sdata->dev->stats.rx_packets++; | 456 | sdata->dev->stats.rx_packets++; |
394 | sdata->dev->stats.rx_bytes += skb->len; | 457 | sdata->dev->stats.rx_bytes += skb->len; |
395 | 458 | ||
@@ -421,60 +484,58 @@ static void mac802154_print_addr(const char *name, | |||
421 | } | 484 | } |
422 | } | 485 | } |
423 | 486 | ||
424 | static int mac802154_parse_frame_start(struct sk_buff *skb) | 487 | static int mac802154_parse_frame_start(struct sk_buff *skb, |
488 | struct ieee802154_hdr *hdr) | ||
425 | { | 489 | { |
426 | int hlen; | 490 | int hlen; |
427 | struct ieee802154_hdr hdr; | ||
428 | struct ieee802154_mac_cb *cb = mac_cb_init(skb); | 491 | struct ieee802154_mac_cb *cb = mac_cb_init(skb); |
429 | 492 | ||
430 | hlen = ieee802154_hdr_pull(skb, &hdr); | 493 | hlen = ieee802154_hdr_pull(skb, hdr); |
431 | if (hlen < 0) | 494 | if (hlen < 0) |
432 | return -EINVAL; | 495 | return -EINVAL; |
433 | 496 | ||
434 | skb->mac_len = hlen; | 497 | skb->mac_len = hlen; |
435 | 498 | ||
436 | pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr.fc), | 499 | pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc), |
437 | hdr.seq); | 500 | hdr->seq); |
438 | 501 | ||
439 | cb->type = hdr.fc.type; | 502 | cb->type = hdr->fc.type; |
440 | cb->ackreq = hdr.fc.ack_request; | 503 | cb->ackreq = hdr->fc.ack_request; |
441 | cb->secen = hdr.fc.security_enabled; | 504 | cb->secen = hdr->fc.security_enabled; |
442 | 505 | ||
443 | mac802154_print_addr("destination", &hdr.dest); | 506 | mac802154_print_addr("destination", &hdr->dest); |
444 | mac802154_print_addr("source", &hdr.source); | 507 | mac802154_print_addr("source", &hdr->source); |
445 | 508 | ||
446 | cb->source = hdr.source; | 509 | cb->source = hdr->source; |
447 | cb->dest = hdr.dest; | 510 | cb->dest = hdr->dest; |
448 | 511 | ||
449 | if (hdr.fc.security_enabled) { | 512 | if (hdr->fc.security_enabled) { |
450 | u64 key; | 513 | u64 key; |
451 | 514 | ||
452 | pr_debug("seclevel %i\n", hdr.sec.level); | 515 | pr_debug("seclevel %i\n", hdr->sec.level); |
453 | 516 | ||
454 | switch (hdr.sec.key_id_mode) { | 517 | switch (hdr->sec.key_id_mode) { |
455 | case IEEE802154_SCF_KEY_IMPLICIT: | 518 | case IEEE802154_SCF_KEY_IMPLICIT: |
456 | pr_debug("implicit key\n"); | 519 | pr_debug("implicit key\n"); |
457 | break; | 520 | break; |
458 | 521 | ||
459 | case IEEE802154_SCF_KEY_INDEX: | 522 | case IEEE802154_SCF_KEY_INDEX: |
460 | pr_debug("key %02x\n", hdr.sec.key_id); | 523 | pr_debug("key %02x\n", hdr->sec.key_id); |
461 | break; | 524 | break; |
462 | 525 | ||
463 | case IEEE802154_SCF_KEY_SHORT_INDEX: | 526 | case IEEE802154_SCF_KEY_SHORT_INDEX: |
464 | pr_debug("key %04x:%04x %02x\n", | 527 | pr_debug("key %04x:%04x %02x\n", |
465 | le32_to_cpu(hdr.sec.short_src) >> 16, | 528 | le32_to_cpu(hdr->sec.short_src) >> 16, |
466 | le32_to_cpu(hdr.sec.short_src) & 0xffff, | 529 | le32_to_cpu(hdr->sec.short_src) & 0xffff, |
467 | hdr.sec.key_id); | 530 | hdr->sec.key_id); |
468 | break; | 531 | break; |
469 | 532 | ||
470 | case IEEE802154_SCF_KEY_HW_INDEX: | 533 | case IEEE802154_SCF_KEY_HW_INDEX: |
471 | key = swab64((__force u64) hdr.sec.extended_src); | 534 | key = swab64((__force u64) hdr->sec.extended_src); |
472 | pr_debug("key source %8phC %02x\n", &key, | 535 | pr_debug("key source %8phC %02x\n", &key, |
473 | hdr.sec.key_id); | 536 | hdr->sec.key_id); |
474 | break; | 537 | break; |
475 | } | 538 | } |
476 | |||
477 | return -EINVAL; | ||
478 | } | 539 | } |
479 | 540 | ||
480 | return 0; | 541 | return 0; |
@@ -485,8 +546,9 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) | |||
485 | int ret; | 546 | int ret; |
486 | struct sk_buff *sskb; | 547 | struct sk_buff *sskb; |
487 | struct mac802154_sub_if_data *sdata; | 548 | struct mac802154_sub_if_data *sdata; |
549 | struct ieee802154_hdr hdr; | ||
488 | 550 | ||
489 | ret = mac802154_parse_frame_start(skb); | 551 | ret = mac802154_parse_frame_start(skb, &hdr); |
490 | if (ret) { | 552 | if (ret) { |
491 | pr_debug("got invalid frame\n"); | 553 | pr_debug("got invalid frame\n"); |
492 | return; | 554 | return; |
@@ -499,7 +561,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) | |||
499 | 561 | ||
500 | sskb = skb_clone(skb, GFP_ATOMIC); | 562 | sskb = skb_clone(skb, GFP_ATOMIC); |
501 | if (sskb) | 563 | if (sskb) |
502 | mac802154_subif_frame(sdata, sskb); | 564 | mac802154_subif_frame(sdata, sskb, &hdr); |
503 | } | 565 | } |
504 | rcu_read_unlock(); | 566 | rcu_read_unlock(); |
505 | } | 567 | } |