Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
mic.c
Go to the documentation of this file.
1 /* Orinoco MIC helpers
2  *
3  * See copyright notice in main.c
4  */
5 #include <linux/kernel.h>
6 #include <linux/string.h>
7 #include <linux/if_ether.h>
8 #include <linux/scatterlist.h>
9 #include <linux/crypto.h>
10 
11 #include "orinoco.h"
12 #include "mic.h"
13 
14 /********************************************************************/
15 /* Michael MIC crypto setup */
16 /********************************************************************/
18 {
19  priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
20  if (IS_ERR(priv->tx_tfm_mic)) {
21  printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
22  "crypto API michael_mic\n");
23  priv->tx_tfm_mic = NULL;
24  return -ENOMEM;
25  }
26 
27  priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
28  if (IS_ERR(priv->rx_tfm_mic)) {
29  printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
30  "crypto API michael_mic\n");
31  priv->rx_tfm_mic = NULL;
32  return -ENOMEM;
33  }
34 
35  return 0;
36 }
37 
39 {
40  if (priv->tx_tfm_mic)
41  crypto_free_hash(priv->tx_tfm_mic);
42  if (priv->rx_tfm_mic)
43  crypto_free_hash(priv->rx_tfm_mic);
44 }
45 
46 int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key,
47  u8 *da, u8 *sa, u8 priority,
48  u8 *data, size_t data_len, u8 *mic)
49 {
50  struct hash_desc desc;
51  struct scatterlist sg[2];
52  u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
53 
54  if (tfm_michael == NULL) {
55  printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n");
56  return -1;
57  }
58 
59  /* Copy header into buffer. We need the padding on the end zeroed */
60  memcpy(&hdr[0], da, ETH_ALEN);
61  memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
62  hdr[ETH_ALEN * 2] = priority;
63  hdr[ETH_ALEN * 2 + 1] = 0;
64  hdr[ETH_ALEN * 2 + 2] = 0;
65  hdr[ETH_ALEN * 2 + 3] = 0;
66 
67  /* Use scatter gather to MIC header and data in one go */
68  sg_init_table(sg, 2);
69  sg_set_buf(&sg[0], hdr, sizeof(hdr));
70  sg_set_buf(&sg[1], data, data_len);
71 
72  if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN))
73  return -1;
74 
75  desc.tfm = tfm_michael;
76  desc.flags = 0;
77  return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr),
78  mic);
79 }