14adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy/* Orinoco MIC helpers 24adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy * 34adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy * See copyright notice in main.c 44adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy */ 54adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include <linux/kernel.h> 64adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include <linux/string.h> 74adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include <linux/if_ether.h> 84adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include <linux/scatterlist.h> 94adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include <linux/crypto.h> 104adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 114adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include "orinoco.h" 124adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy#include "mic.h" 134adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 144adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy/********************************************************************/ 154adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy/* Michael MIC crypto setup */ 164adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy/********************************************************************/ 174adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroyint orinoco_mic_init(struct orinoco_private *priv) 184adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy{ 194adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); 204adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy if (IS_ERR(priv->tx_tfm_mic)) { 214adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy printk(KERN_DEBUG "orinoco_mic_init: could not allocate " 224adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy "crypto API michael_mic\n"); 234adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy priv->tx_tfm_mic = NULL; 244adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy return -ENOMEM; 254adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy } 264adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 274adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); 284adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy if (IS_ERR(priv->rx_tfm_mic)) { 294adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy printk(KERN_DEBUG "orinoco_mic_init: could not allocate " 304adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy "crypto API michael_mic\n"); 314adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy priv->rx_tfm_mic = NULL; 324adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy return -ENOMEM; 334adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy } 344adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 354adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy return 0; 364adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy} 374adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 384adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroyvoid orinoco_mic_free(struct orinoco_private *priv) 394adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy{ 404adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy if (priv->tx_tfm_mic) 414adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy crypto_free_hash(priv->tx_tfm_mic); 424adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy if (priv->rx_tfm_mic) 434adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy crypto_free_hash(priv->rx_tfm_mic); 444adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy} 454adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 464adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroyint orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, 474adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy u8 *da, u8 *sa, u8 priority, 484adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy u8 *data, size_t data_len, u8 *mic) 494adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy{ 504adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy struct hash_desc desc; 514adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy struct scatterlist sg[2]; 524adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy u8 hdr[ETH_HLEN + 2]; /* size of header + padding */ 534adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 544adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy if (tfm_michael == NULL) { 554adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n"); 564adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy return -1; 574adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy } 584adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 594adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy /* Copy header into buffer. We need the padding on the end zeroed */ 604adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy memcpy(&hdr[0], da, ETH_ALEN); 614adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN); 62933d594313a5928ffc5325d7bbb6e2383d79622ePavel Roskin hdr[ETH_ALEN * 2] = priority; 63933d594313a5928ffc5325d7bbb6e2383d79622ePavel Roskin hdr[ETH_ALEN * 2 + 1] = 0; 64933d594313a5928ffc5325d7bbb6e2383d79622ePavel Roskin hdr[ETH_ALEN * 2 + 2] = 0; 65933d594313a5928ffc5325d7bbb6e2383d79622ePavel Roskin hdr[ETH_ALEN * 2 + 3] = 0; 664adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 674adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy /* Use scatter gather to MIC header and data in one go */ 684adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy sg_init_table(sg, 2); 694adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy sg_set_buf(&sg[0], hdr, sizeof(hdr)); 704adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy sg_set_buf(&sg[1], data, data_len); 714adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 724adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN)) 734adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy return -1; 744adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy 754adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy desc.tfm = tfm_michael; 764adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy desc.flags = 0; 774adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr), 784adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy mic); 794adb474b6b7e26e1318acab5e98864aa78f9b233David Kilroy} 80