2012-02-18 11:47:31 +01:00
/*
AES - CMAC - 128 ( rfc 4493 )
Copyright ( C ) Stefan Metzmacher 2012
Copyright ( C ) Jeremy Allison 2012
Copyright ( C ) Michael Adam 2012
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "replace.h"
2019-02-26 18:30:22 +01:00
# include "lib/crypto/aes.h"
# include "lib/crypto/aes_cmac_128.h"
2012-02-18 11:47:31 +01:00
static const uint8_t const_Zero [ ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
} ;
static const uint8_t const_Rb [ ] = {
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x87
} ;
# define _MSB(x) (((x)[0] & 0x80)?1:0)
void aes_cmac_128_init ( struct aes_cmac_128_context * ctx ,
const uint8_t K [ AES_BLOCK_SIZE ] )
{
ZERO_STRUCTP ( ctx ) ;
AES_set_encrypt_key ( K , 128 , & ctx - > aes_key ) ;
/* step 1 - generate subkeys k1 and k2 */
2015-08-12 00:59:58 +02:00
AES_encrypt ( const_Zero , ctx - > L , & ctx - > aes_key ) ;
2012-02-18 11:47:31 +01:00
2015-08-12 00:59:58 +02:00
if ( _MSB ( ctx - > L ) = = 0 ) {
aes_block_lshift ( ctx - > L , ctx - > K1 ) ;
2012-02-18 11:47:31 +01:00
} else {
2015-08-12 00:59:58 +02:00
aes_block_lshift ( ctx - > L , ctx - > tmp ) ;
aes_block_xor ( ctx - > tmp , const_Rb , ctx - > K1 ) ;
2012-02-18 11:47:31 +01:00
}
if ( _MSB ( ctx - > K1 ) = = 0 ) {
2015-08-12 00:59:58 +02:00
aes_block_lshift ( ctx - > K1 , ctx - > K2 ) ;
2012-02-18 11:47:31 +01:00
} else {
2015-08-12 00:59:58 +02:00
aes_block_lshift ( ctx - > K1 , ctx - > tmp ) ;
aes_block_xor ( ctx - > tmp , const_Rb , ctx - > K2 ) ;
2012-02-18 11:47:31 +01:00
}
}
void aes_cmac_128_update ( struct aes_cmac_128_context * ctx ,
2015-08-12 00:59:58 +02:00
const uint8_t * msg , size_t msg_len )
2012-02-18 11:47:31 +01:00
{
/*
* check if we expand the block
*/
if ( ctx - > last_len < AES_BLOCK_SIZE ) {
size_t len = MIN ( AES_BLOCK_SIZE - ctx - > last_len , msg_len ) ;
2019-05-24 11:00:05 +12:00
if ( len > 0 ) {
memcpy ( & ctx - > last [ ctx - > last_len ] , msg , len ) ;
msg + = len ;
msg_len - = len ;
ctx - > last_len + = len ;
}
2012-02-18 11:47:31 +01:00
}
if ( msg_len = = 0 ) {
/* if it is still the last block, we are done */
return ;
}
/*
* now checksum everything but the last block
*/
2015-08-12 00:59:58 +02:00
aes_block_xor ( ctx - > X , ctx - > last , ctx - > Y ) ;
AES_encrypt ( ctx - > Y , ctx - > X , & ctx - > aes_key ) ;
2012-02-18 11:47:31 +01:00
while ( msg_len > AES_BLOCK_SIZE ) {
2015-08-12 00:59:58 +02:00
aes_block_xor ( ctx - > X , msg , ctx - > Y ) ;
AES_encrypt ( ctx - > Y , ctx - > X , & ctx - > aes_key ) ;
2012-02-18 11:47:31 +01:00
msg + = AES_BLOCK_SIZE ;
msg_len - = AES_BLOCK_SIZE ;
}
/*
* copy the last block , it will be processed in
* aes_cmac_128_final ( ) .
*/
2015-08-12 00:59:58 +02:00
ZERO_STRUCT ( ctx - > last ) ;
2012-02-18 11:47:31 +01:00
memcpy ( ctx - > last , msg , msg_len ) ;
ctx - > last_len = msg_len ;
}
void aes_cmac_128_final ( struct aes_cmac_128_context * ctx ,
uint8_t T [ AES_BLOCK_SIZE ] )
{
if ( ctx - > last_len < AES_BLOCK_SIZE ) {
ctx - > last [ ctx - > last_len ] = 0x80 ;
2015-08-12 00:59:58 +02:00
aes_block_xor ( ctx - > last , ctx - > K2 , ctx - > tmp ) ;
2012-02-18 11:47:31 +01:00
} else {
2015-08-12 00:59:58 +02:00
aes_block_xor ( ctx - > last , ctx - > K1 , ctx - > tmp ) ;
2012-02-18 11:47:31 +01:00
}
2015-08-12 00:59:58 +02:00
aes_block_xor ( ctx - > tmp , ctx - > X , ctx - > Y ) ;
AES_encrypt ( ctx - > Y , T , & ctx - > aes_key ) ;
2012-02-18 11:47:31 +01:00
ZERO_STRUCTP ( ctx ) ;
}