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 /********************************************************************/ 17 int 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 38 void 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 46 int 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