linux/drivers/net/wireless/intersil/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 <crypto/hash.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_shash("michael_mic", 0, 0);
  20        if (IS_ERR(priv->tx_tfm_mic)) {
  21                printk(KERN_DEBUG "%s: could not allocate "
  22                       "crypto API michael_mic\n", __func__);
  23                priv->tx_tfm_mic = NULL;
  24                return -ENOMEM;
  25        }
  26
  27        priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
  28        if (IS_ERR(priv->rx_tfm_mic)) {
  29                printk(KERN_DEBUG "%s: could not allocate "
  30                       "crypto API michael_mic\n", __func__);
  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_shash(priv->tx_tfm_mic);
  42        if (priv->rx_tfm_mic)
  43                crypto_free_shash(priv->rx_tfm_mic);
  44}
  45
  46int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
  47                u8 *da, u8 *sa, u8 priority,
  48                u8 *data, size_t data_len, u8 *mic)
  49{
  50        SHASH_DESC_ON_STACK(desc, tfm_michael);
  51        u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
  52        int err;
  53
  54        if (tfm_michael == NULL) {
  55                printk(KERN_WARNING "%s: tfm_michael == NULL\n", __func__);
  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        desc->tfm = tfm_michael;
  68
  69        err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
  70        if (err)
  71                return err;
  72
  73        err = crypto_shash_init(desc);
  74        if (err)
  75                return err;
  76
  77        err = crypto_shash_update(desc, hdr, sizeof(hdr));
  78        if (err)
  79                return err;
  80
  81        err = crypto_shash_update(desc, data, data_len);
  82        if (err)
  83                return err;
  84
  85        err = crypto_shash_final(desc, mic);
  86        shash_desc_zero(desc);
  87
  88        return err;
  89}
  90