0001
0002
0003
0004
0005 #include <linux/kernel.h>
0006 #include <linux/string.h>
0007 #include <linux/if_ether.h>
0008 #include <linux/scatterlist.h>
0009 #include <crypto/hash.h>
0010
0011 #include "orinoco.h"
0012 #include "mic.h"
0013
0014
0015
0016
0017 int orinoco_mic_init(struct orinoco_private *priv)
0018 {
0019 priv->tx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
0020 if (IS_ERR(priv->tx_tfm_mic)) {
0021 printk(KERN_DEBUG "%s: could not allocate "
0022 "crypto API michael_mic\n", __func__);
0023 priv->tx_tfm_mic = NULL;
0024 return -ENOMEM;
0025 }
0026
0027 priv->rx_tfm_mic = crypto_alloc_shash("michael_mic", 0, 0);
0028 if (IS_ERR(priv->rx_tfm_mic)) {
0029 printk(KERN_DEBUG "%s: could not allocate "
0030 "crypto API michael_mic\n", __func__);
0031 priv->rx_tfm_mic = NULL;
0032 return -ENOMEM;
0033 }
0034
0035 return 0;
0036 }
0037
0038 void orinoco_mic_free(struct orinoco_private *priv)
0039 {
0040 if (priv->tx_tfm_mic)
0041 crypto_free_shash(priv->tx_tfm_mic);
0042 if (priv->rx_tfm_mic)
0043 crypto_free_shash(priv->rx_tfm_mic);
0044 }
0045
0046 int orinoco_mic(struct crypto_shash *tfm_michael, u8 *key,
0047 u8 *da, u8 *sa, u8 priority,
0048 u8 *data, size_t data_len, u8 *mic)
0049 {
0050 SHASH_DESC_ON_STACK(desc, tfm_michael);
0051 u8 hdr[ETH_HLEN + 2];
0052 int err;
0053
0054 if (tfm_michael == NULL) {
0055 printk(KERN_WARNING "%s: tfm_michael == NULL\n", __func__);
0056 return -1;
0057 }
0058
0059
0060 memcpy(&hdr[0], da, ETH_ALEN);
0061 memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
0062 hdr[ETH_ALEN * 2] = priority;
0063 hdr[ETH_ALEN * 2 + 1] = 0;
0064 hdr[ETH_ALEN * 2 + 2] = 0;
0065 hdr[ETH_ALEN * 2 + 3] = 0;
0066
0067 desc->tfm = tfm_michael;
0068
0069 err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN);
0070 if (err)
0071 return err;
0072
0073 err = crypto_shash_init(desc);
0074 if (err)
0075 return err;
0076
0077 err = crypto_shash_update(desc, hdr, sizeof(hdr));
0078 if (err)
0079 return err;
0080
0081 err = crypto_shash_update(desc, data, data_len);
0082 if (err)
0083 return err;
0084
0085 err = crypto_shash_final(desc, mic);
0086 shash_desc_zero(desc);
0087
0088 return err;
0089 }