linux/drivers/net/wireless/orinoco/mic.c
<<
>>
Prefs
   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/********************************************************************/
  17int orinoco_mic_init(struct orinoco_private *priv)
  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
  38void orinoco_mic_free(struct orinoco_private *priv)
  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
  46int 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}
  80