2009-01-08 14:32:01 +03:00
/*
* AES - 128 - CMAC with TLen 16 for IEEE 802.11 w BIP
* Copyright 2008 , Jouni Malinen < j @ w1 . fi >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/kernel.h>
# include <linux/types.h>
# include <linux/crypto.h>
2012-11-07 13:13:58 +04:00
# include <linux/export.h>
2009-01-08 14:32:01 +03:00
# include <linux/err.h>
2011-07-07 00:02:14 +04:00
# include <crypto/aes.h>
2009-01-08 14:32:01 +03:00
# include <net/mac80211.h>
# include "key.h"
# include "aes_cmac.h"
# define CMAC_TLEN 8 /* CMAC TLen = 64 bits (8 octets) */
2015-01-24 20:52:08 +03:00
# define CMAC_TLEN_256 16 /* CMAC TLen = 128 bits (16 octets) */
2009-01-08 14:32:01 +03:00
# define AAD_LEN 20
2017-02-06 13:49:28 +03:00
static const u8 zero [ CMAC_TLEN_256 ] ;
2009-01-08 14:32:01 +03:00
2017-02-06 13:49:28 +03:00
void ieee80211_aes_cmac ( struct crypto_shash * tfm , const u8 * aad ,
2009-01-08 14:32:01 +03:00
const u8 * data , size_t data_len , u8 * mic )
{
2017-02-06 13:49:28 +03:00
SHASH_DESC_ON_STACK ( desc , tfm ) ;
u8 out [ AES_BLOCK_SIZE ] ;
2009-01-08 14:32:01 +03:00
2017-02-06 13:49:28 +03:00
desc - > tfm = tfm ;
2009-01-08 14:32:01 +03:00
2017-02-06 13:49:28 +03:00
crypto_shash_init ( desc ) ;
crypto_shash_update ( desc , aad , AAD_LEN ) ;
crypto_shash_update ( desc , data , data_len - CMAC_TLEN ) ;
crypto_shash_finup ( desc , zero , CMAC_TLEN , out ) ;
memcpy ( mic , out , CMAC_TLEN ) ;
2009-01-08 14:32:01 +03:00
}
2017-02-06 13:49:28 +03:00
void ieee80211_aes_cmac_256 ( struct crypto_shash * tfm , const u8 * aad ,
2015-01-24 20:52:08 +03:00
const u8 * data , size_t data_len , u8 * mic )
{
2017-02-06 13:49:28 +03:00
SHASH_DESC_ON_STACK ( desc , tfm ) ;
2015-01-24 20:52:08 +03:00
2017-02-06 13:49:28 +03:00
desc - > tfm = tfm ;
2015-01-24 20:52:08 +03:00
2017-02-06 13:49:28 +03:00
crypto_shash_init ( desc ) ;
crypto_shash_update ( desc , aad , AAD_LEN ) ;
crypto_shash_update ( desc , data , data_len - CMAC_TLEN_256 ) ;
crypto_shash_finup ( desc , zero , CMAC_TLEN_256 , mic ) ;
2015-01-24 20:52:08 +03:00
}
2009-01-08 14:32:01 +03:00
2017-02-06 13:49:28 +03:00
struct crypto_shash * ieee80211_aes_cmac_key_setup ( const u8 key [ ] ,
size_t key_len )
2009-01-08 14:32:01 +03:00
{
2017-02-06 13:49:28 +03:00
struct crypto_shash * tfm ;
2009-01-08 14:32:01 +03:00
2017-02-06 13:49:28 +03:00
tfm = crypto_alloc_shash ( " cmac(aes) " , 0 , 0 ) ;
2010-08-01 20:37:03 +04:00
if ( ! IS_ERR ( tfm ) )
2017-02-06 13:49:28 +03:00
crypto_shash_setkey ( tfm , key , key_len ) ;
2009-01-08 14:32:01 +03:00
return tfm ;
}
2017-02-06 13:49:28 +03:00
void ieee80211_aes_cmac_key_free ( struct crypto_shash * tfm )
2009-01-08 14:32:01 +03:00
{
2017-02-06 13:49:28 +03:00
crypto_free_shash ( tfm ) ;
2009-01-08 14:32:01 +03:00
}