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 /********************************************************************/ 17 int 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 38 void 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 46 int 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 desc->flags = 0; 69 70 err = crypto_shash_setkey(tfm_michael, key, MIC_KEYLEN); 71 if (err) 72 return err; 73 74 err = crypto_shash_init(desc); 75 if (err) 76 return err; 77 78 err = crypto_shash_update(desc, hdr, sizeof(hdr)); 79 if (err) 80 return err; 81 82 err = crypto_shash_update(desc, data, data_len); 83 if (err) 84 return err; 85 86 err = crypto_shash_final(desc, mic); 87 shash_desc_zero(desc); 88 89 return err; 90 } 91