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,
  20                                              CRYPTO_ALG_ASYNC);
  21        if (IS_ERR(priv->tx_tfm_mic)) {
  22                printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
  23                       "crypto API michael_mic\n");
  24                priv->tx_tfm_mic = NULL;
  25                return -ENOMEM;
  26        }
  27
  28        priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0,
  29                                              CRYPTO_ALG_ASYNC);
  30        if (IS_ERR(priv->rx_tfm_mic)) {
  31                printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
  32                       "crypto API michael_mic\n");
  33                priv->rx_tfm_mic = NULL;
  34                return -ENOMEM;
  35        }
  36
  37        return 0;
  38}
  39
  40void orinoco_mic_free(struct orinoco_private *priv)
  41{
  42        if (priv->tx_tfm_mic)
  43                crypto_free_shash(priv->tx_tfm_mic);
  44        if (priv->rx_tfm_mic)
  45                crypto_free_shash(priv->rx_tfm_mic);
  46}
  47
  48int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
  49                u8 *da, u8 *sa, u8 priority,
  50                u8 *data, size_t data_len, u8 *mic)
  51{
  52        SHASH_DESC_ON_STACK(desc, tfm_michael);
  53        u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
  54        int err;
  55
  56        if (tfm_michael == NULL) {
  57                printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n");
  58                return -1;
  59        }
  60
  61        /* Copy header into buffer. We need the padding on the end zeroed */
  62        memcpy(&hdr[0], da, ETH_ALEN);
  63        memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
  64        hdr[ETH_ALEN * 2] = priority;
  65        hdr[ETH_ALEN * 2 + 1] = 0;
  66        hdr[ETH_ALEN * 2 + 2] = 0;
  67        hdr[ETH_ALEN * 2 + 3] = 0;
  68
  69        desc->tfm = tfm_michael;
  70        desc->flags = 0;
  71
  72        err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
  73        if (err)
  74                return err;
  75
  76        err = crypto_shash_init(desc);
  77        if (err)
  78                return err;
  79
  80        err = crypto_shash_update(desc, hdr, sizeof(hdr));
  81        if (err)
  82                return err;
  83
  84        err = crypto_shash_update(desc, data, data_len);
  85        if (err)
  86                return err;
  87
  88        err = crypto_shash_final(desc, mic);
  89        shash_desc_zero(desc);
  90
  91        return err;
  92}
  93