2019-06-01 11:08:55 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2013-02-07 02:12:08 +04:00
/*
* Copyright ( C ) 2013 Intel Corporation
*
* Author :
* Dmitry Kasatkin < dmitry . kasatkin @ intel . com >
*/
# include <linux/err.h>
2014-07-02 16:12:26 +04:00
# include <linux/ratelimit.h>
2013-02-07 02:12:08 +04:00
# include <linux/key-type.h>
# include <crypto/public_key.h>
2016-03-04 00:49:27 +03:00
# include <crypto/hash_info.h>
2013-02-07 02:12:08 +04:00
# include <keys/asymmetric-type.h>
2015-12-02 18:47:55 +03:00
# include <keys/system_keyring.h>
2013-02-07 02:12:08 +04:00
# include "integrity.h"
/*
* Request an asymmetric key .
*/
static struct key * request_asymmetric_key ( struct key * keyring , uint32_t keyid )
{
struct key * key ;
char name [ 12 ] ;
2014-10-06 20:31:58 +04:00
sprintf ( name , " id:%08x " , keyid ) ;
2013-02-07 02:12:08 +04:00
pr_debug ( " key search: \" %s \" \n " , name ) ;
2015-12-02 18:47:55 +03:00
key = get_ima_blacklist_keyring ( ) ;
if ( key ) {
key_ref_t kref ;
kref = keyring_search ( make_key_ref ( key , 1 ) ,
2019-06-26 23:02:32 +03:00
& key_type_asymmetric , name , true ) ;
2015-12-02 18:47:55 +03:00
if ( ! IS_ERR ( kref ) ) {
pr_err ( " Key '%s' is in ima_blacklist_keyring \n " , name ) ;
return ERR_PTR ( - EKEYREJECTED ) ;
}
}
2013-02-07 02:12:08 +04:00
if ( keyring ) {
/* search in specific keyring */
key_ref_t kref ;
2015-12-02 18:47:55 +03:00
2013-02-07 02:12:08 +04:00
kref = keyring_search ( make_key_ref ( keyring , 1 ) ,
2019-06-26 23:02:32 +03:00
& key_type_asymmetric , name , true ) ;
2013-02-07 02:12:08 +04:00
if ( IS_ERR ( kref ) )
key = ERR_CAST ( kref ) ;
else
key = key_ref_to_ptr ( kref ) ;
} else {
2019-07-11 04:43:43 +03:00
key = request_key ( & key_type_asymmetric , name , NULL ) ;
2013-02-07 02:12:08 +04:00
}
if ( IS_ERR ( key ) ) {
2020-09-04 22:41:00 +03:00
if ( keyring )
pr_err_ratelimited ( " Request for unknown key '%s' in '%s' keyring. err %ld \n " ,
name , keyring - > description ,
PTR_ERR ( key ) ) ;
else
pr_err_ratelimited ( " Request for unknown key '%s' err %ld \n " ,
name , PTR_ERR ( key ) ) ;
2013-02-07 02:12:08 +04:00
switch ( PTR_ERR ( key ) ) {
/* Hide some search errors */
case - EACCES :
case - ENOTDIR :
case - EAGAIN :
return ERR_PTR ( - ENOKEY ) ;
default :
return key ;
}
}
pr_debug ( " %s() = 0 [%x] \n " , __func__ , key_serial ( key ) ) ;
return key ;
}
int asymmetric_verify ( struct key * keyring , const char * sig ,
int siglen , const char * data , int datalen )
{
struct public_key_signature pks ;
struct signature_v2_hdr * hdr = ( struct signature_v2_hdr * ) sig ;
2021-03-17 00:07:38 +03:00
const struct public_key * pk ;
2013-02-07 02:12:08 +04:00
struct key * key ;
2020-07-01 16:46:34 +03:00
int ret ;
2013-02-07 02:12:08 +04:00
if ( siglen < = sizeof ( * hdr ) )
return - EBADMSG ;
siglen - = sizeof ( * hdr ) ;
2017-06-08 04:49:10 +03:00
if ( siglen ! = be16_to_cpu ( hdr - > sig_size ) )
2013-02-07 02:12:08 +04:00
return - EBADMSG ;
2016-03-04 00:49:27 +03:00
if ( hdr - > hash_algo > = HASH_ALGO__LAST )
2013-02-07 02:12:08 +04:00
return - ENOPKG ;
2017-06-08 04:49:10 +03:00
key = request_asymmetric_key ( keyring , be32_to_cpu ( hdr - > keyid ) ) ;
2013-02-07 02:12:08 +04:00
if ( IS_ERR ( key ) )
return PTR_ERR ( key ) ;
memset ( & pks , 0 , sizeof ( pks ) ) ;
2016-03-04 00:49:27 +03:00
pks . hash_algo = hash_algo_name [ hdr - > hash_algo ] ;
2021-03-17 00:07:38 +03:00
pk = asymmetric_key_public_key ( key ) ;
pks . pkey_algo = pk - > pkey_algo ;
2022-01-13 22:44:38 +03:00
if ( ! strcmp ( pk - > pkey_algo , " rsa " ) ) {
2019-04-11 18:51:22 +03:00
pks . encoding = " pkcs1 " ;
2022-01-13 22:44:38 +03:00
} else if ( ! strncmp ( pk - > pkey_algo , " ecdsa- " , 6 ) ) {
2021-03-17 00:07:38 +03:00
/* edcsa-nist-p192 etc. */
pks . encoding = " x962 " ;
2022-01-13 22:44:38 +03:00
} else if ( ! strcmp ( pk - > pkey_algo , " ecrdsa " ) | |
! strcmp ( pk - > pkey_algo , " sm2 " ) ) {
2021-03-17 00:07:38 +03:00
pks . encoding = " raw " ;
2022-01-13 22:44:38 +03:00
} else {
ret = - ENOPKG ;
goto out ;
}
2021-03-17 00:07:38 +03:00
2013-02-07 02:12:08 +04:00
pks . digest = ( u8 * ) data ;
pks . digest_size = datalen ;
2016-02-02 21:08:58 +03:00
pks . s = hdr - > sig ;
pks . s_size = siglen ;
ret = verify_signature ( key , & pks ) ;
2022-01-13 22:44:38 +03:00
out :
2013-02-07 02:12:08 +04:00
key_put ( key ) ;
pr_debug ( " %s() = %d \n " , __func__ , ret ) ;
return ret ;
}