2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2007-05-05 22:45:53 +04:00
/*
* Copyright 2003 - 2004 , Instant802 Networks , Inc .
* Copyright 2005 - 2006 , Devicescape Software , Inc .
2017-10-11 05:31:49 +03:00
* Copyright 2014 - 2015 , Qualcomm Atheros , Inc .
2007-05-05 22:45:53 +04:00
*
2013-10-10 11:55:20 +04:00
* Rewrite : Copyright ( C ) 2013 Linaro Ltd < ard . biesheuvel @ linaro . org >
2007-05-05 22:45:53 +04:00
*/
2007-08-29 02:50:33 +04:00
# include <linux/kernel.h>
2007-05-05 22:45:53 +04:00
# include <linux/types.h>
# include <linux/err.h>
2017-10-11 05:31:49 +03:00
# include <linux/scatterlist.h>
2015-04-22 10:06:32 +03:00
# include <crypto/aead.h>
2007-05-05 22:45:53 +04:00
2017-10-11 05:31:49 +03:00
# include "aead_api.h"
2007-05-05 22:45:53 +04:00
2017-10-11 05:31:49 +03:00
int aead_encrypt ( struct crypto_aead * tfm , u8 * b_0 , u8 * aad , size_t aad_len ,
u8 * data , size_t data_len , u8 * mic )
2007-05-05 22:45:53 +04:00
{
2017-10-11 16:46:45 +03:00
size_t mic_len = crypto_aead_authsize ( tfm ) ;
2015-05-27 11:03:50 +03:00
struct scatterlist sg [ 3 ] ;
2016-10-17 17:05:33 +03:00
struct aead_request * aead_req ;
int reqsize = sizeof ( * aead_req ) + crypto_aead_reqsize ( tfm ) ;
u8 * __aad ;
2021-03-09 23:41:36 +03:00
int ret ;
2007-05-05 22:45:53 +04:00
2017-10-11 05:31:49 +03:00
aead_req = kzalloc ( reqsize + aad_len , GFP_ATOMIC ) ;
2016-10-17 17:05:33 +03:00
if ( ! aead_req )
return - ENOMEM ;
2014-03-21 10:39:32 +04:00
2016-10-17 17:05:33 +03:00
__aad = ( u8 * ) aead_req + reqsize ;
2017-10-11 05:31:49 +03:00
memcpy ( __aad , aad , aad_len ) ;
2007-05-05 22:45:53 +04:00
2015-05-27 11:03:50 +03:00
sg_init_table ( sg , 3 ) ;
2017-10-11 05:31:49 +03:00
sg_set_buf ( & sg [ 0 ] , __aad , aad_len ) ;
2015-05-27 11:03:50 +03:00
sg_set_buf ( & sg [ 1 ] , data , data_len ) ;
sg_set_buf ( & sg [ 2 ] , mic , mic_len ) ;
2007-05-05 22:45:53 +04:00
2014-03-21 10:39:32 +04:00
aead_request_set_tfm ( aead_req , tfm ) ;
2015-05-27 11:03:50 +03:00
aead_request_set_crypt ( aead_req , sg , sg , data_len , b_0 ) ;
aead_request_set_ad ( aead_req , sg [ 0 ] . length ) ;
2007-05-05 22:45:53 +04:00
2021-03-09 23:41:36 +03:00
ret = crypto_aead_encrypt ( aead_req ) ;
2020-08-07 09:18:13 +03:00
kfree_sensitive ( aead_req ) ;
2016-10-17 17:05:33 +03:00
2021-03-09 23:41:36 +03:00
return ret ;
2007-05-05 22:45:53 +04:00
}
2017-10-11 05:31:49 +03:00
int aead_decrypt ( struct crypto_aead * tfm , u8 * b_0 , u8 * aad , size_t aad_len ,
u8 * data , size_t data_len , u8 * mic )
2007-05-05 22:45:53 +04:00
{
2017-10-11 16:46:45 +03:00
size_t mic_len = crypto_aead_authsize ( tfm ) ;
2015-05-27 11:03:50 +03:00
struct scatterlist sg [ 3 ] ;
2016-10-17 17:05:33 +03:00
struct aead_request * aead_req ;
int reqsize = sizeof ( * aead_req ) + crypto_aead_reqsize ( tfm ) ;
u8 * __aad ;
int err ;
2013-10-10 11:55:20 +04:00
2014-11-06 13:52:13 +03:00
if ( data_len = = 0 )
return - EINVAL ;
2017-10-11 05:31:49 +03:00
aead_req = kzalloc ( reqsize + aad_len , GFP_ATOMIC ) ;
2016-10-17 17:05:33 +03:00
if ( ! aead_req )
return - ENOMEM ;
__aad = ( u8 * ) aead_req + reqsize ;
2017-10-11 05:31:49 +03:00
memcpy ( __aad , aad , aad_len ) ;
2013-10-10 11:55:20 +04:00
2015-05-27 11:03:50 +03:00
sg_init_table ( sg , 3 ) ;
2017-10-11 05:31:49 +03:00
sg_set_buf ( & sg [ 0 ] , __aad , aad_len ) ;
2015-05-27 11:03:50 +03:00
sg_set_buf ( & sg [ 1 ] , data , data_len ) ;
sg_set_buf ( & sg [ 2 ] , mic , mic_len ) ;
2013-10-10 11:55:20 +04:00
2014-03-21 10:39:32 +04:00
aead_request_set_tfm ( aead_req , tfm ) ;
2015-05-27 11:03:50 +03:00
aead_request_set_crypt ( aead_req , sg , sg , data_len + mic_len , b_0 ) ;
aead_request_set_ad ( aead_req , sg [ 0 ] . length ) ;
2013-10-10 11:55:20 +04:00
2016-10-17 17:05:33 +03:00
err = crypto_aead_decrypt ( aead_req ) ;
2020-08-07 09:18:13 +03:00
kfree_sensitive ( aead_req ) ;
2016-10-17 17:05:33 +03:00
return err ;
2007-05-05 22:45:53 +04:00
}
2017-10-11 05:31:49 +03:00
struct crypto_aead *
aead_key_setup_encrypt ( const char * alg , const u8 key [ ] ,
size_t key_len , size_t mic_len )
2007-05-05 22:45:53 +04:00
{
2013-10-10 11:55:20 +04:00
struct crypto_aead * tfm ;
int err ;
2007-05-05 22:45:53 +04:00
2017-10-11 05:31:49 +03:00
tfm = crypto_alloc_aead ( alg , 0 , CRYPTO_ALG_ASYNC ) ;
2013-10-10 11:55:20 +04:00
if ( IS_ERR ( tfm ) )
return tfm ;
2007-05-05 22:45:53 +04:00
2015-01-24 20:52:07 +03:00
err = crypto_aead_setkey ( tfm , key , key_len ) ;
2015-03-23 17:08:14 +03:00
if ( err )
goto free_aead ;
err = crypto_aead_setauthsize ( tfm , mic_len ) ;
if ( err )
goto free_aead ;
return tfm ;
2007-05-05 22:45:53 +04:00
2015-03-23 17:08:14 +03:00
free_aead :
2013-10-10 11:55:20 +04:00
crypto_free_aead ( tfm ) ;
return ERR_PTR ( err ) ;
2007-05-05 22:45:53 +04:00
}
2017-10-11 05:31:49 +03:00
void aead_key_free ( struct crypto_aead * tfm )
2007-05-05 22:45:53 +04:00
{
2013-10-10 11:55:20 +04:00
crypto_free_aead ( tfm ) ;
2007-05-05 22:45:53 +04:00
}