2011-10-05 12:54:46 +04:00
/*
* Copyright ( C ) 2011 Intel Corporation
*
* Author :
* Dmitry Kasatkin < dmitry . kasatkin @ intel . com >
*
* 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 , version 2 of the License .
*
*/
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
# include <linux/err.h>
2013-08-13 16:47:43 +04:00
# include <linux/sched.h>
2014-11-05 18:01:13 +03:00
# include <linux/slab.h>
2013-08-13 16:47:43 +04:00
# include <linux/cred.h>
2011-10-05 12:54:46 +04:00
# include <linux/key-type.h>
# include <linux/digsig.h>
# include "integrity.h"
static struct key * keyring [ INTEGRITY_KEYRING_MAX ] ;
static const char * keyring_name [ INTEGRITY_KEYRING_MAX ] = {
2015-10-22 21:26:10 +03:00
# ifndef CONFIG_INTEGRITY_TRUSTED_KEYRING
2011-10-05 12:54:46 +04:00
" _evm " ,
" _ima " ,
2013-08-13 16:47:43 +04:00
# else
2015-10-22 21:26:10 +03:00
" .evm " ,
2013-08-13 16:47:43 +04:00
" .ima " ,
# endif
2015-10-22 21:26:10 +03:00
" _module " ,
2011-10-05 12:54:46 +04:00
} ;
2015-10-22 21:26:10 +03:00
# ifdef CONFIG_INTEGRITY_TRUSTED_KEYRING
static bool init_keyring __initdata = true ;
# else
static bool init_keyring __initdata ;
# endif
2011-10-05 12:54:46 +04:00
int integrity_digsig_verify ( const unsigned int id , const char * sig , int siglen ,
2013-10-10 10:56:13 +04:00
const char * digest , int digestlen )
2011-10-05 12:54:46 +04:00
{
if ( id > = INTEGRITY_KEYRING_MAX )
return - EINVAL ;
if ( ! keyring [ id ] ) {
keyring [ id ] =
2013-11-24 04:36:35 +04:00
request_key ( & key_type_keyring , keyring_name [ id ] , NULL ) ;
2011-10-05 12:54:46 +04:00
if ( IS_ERR ( keyring [ id ] ) ) {
int err = PTR_ERR ( keyring [ id ] ) ;
pr_err ( " no %s keyring: %d \n " , keyring_name [ id ] , err ) ;
keyring [ id ] = NULL ;
return err ;
}
}
2013-10-10 11:12:03 +04:00
switch ( sig [ 1 ] ) {
2013-02-07 02:12:08 +04:00
case 1 :
2013-10-10 11:12:03 +04:00
/* v1 API expect signature without xattr type */
return digsig_verify ( keyring [ id ] , sig + 1 , siglen - 1 ,
2013-02-07 02:12:08 +04:00
digest , digestlen ) ;
case 2 :
return asymmetric_verify ( keyring [ id ] , sig , siglen ,
digest , digestlen ) ;
}
return - EOPNOTSUPP ;
2011-10-05 12:54:46 +04:00
}
2013-08-13 16:47:43 +04:00
2014-10-01 22:43:07 +04:00
int __init integrity_init_keyring ( const unsigned int id )
2013-08-13 16:47:43 +04:00
{
const struct cred * cred = current_cred ( ) ;
int err = 0 ;
2015-10-22 21:26:10 +03:00
if ( ! init_keyring )
return 0 ;
2013-08-13 16:47:43 +04:00
keyring [ id ] = keyring_alloc ( keyring_name [ id ] , KUIDT_INIT ( 0 ) ,
KGIDT_INIT ( 0 ) , cred ,
( ( KEY_POS_ALL & ~ KEY_POS_SETATTR ) |
KEY_USR_VIEW | KEY_USR_READ |
KEY_USR_WRITE | KEY_USR_SEARCH ) ,
KEY_ALLOC_NOT_IN_QUOTA , NULL ) ;
if ( ! IS_ERR ( keyring [ id ] ) )
set_bit ( KEY_FLAG_TRUSTED_ONLY , & keyring [ id ] - > flags ) ;
else {
err = PTR_ERR ( keyring [ id ] ) ;
pr_info ( " Can't allocate %s keyring (%d) \n " ,
keyring_name [ id ] , err ) ;
keyring [ id ] = NULL ;
}
return err ;
}
2014-11-05 18:01:13 +03:00
2014-11-26 17:55:00 +03:00
int __init integrity_load_x509 ( const unsigned int id , const char * path )
2014-11-05 18:01:13 +03:00
{
key_ref_t key ;
char * data ;
int rc ;
if ( ! keyring [ id ] )
return - EINVAL ;
rc = integrity_read_file ( path , & data ) ;
if ( rc < 0 )
return rc ;
key = key_create_or_update ( make_key_ref ( keyring [ id ] , 1 ) ,
" asymmetric " ,
NULL ,
data ,
rc ,
( ( KEY_POS_ALL & ~ KEY_POS_SETATTR ) |
KEY_USR_VIEW | KEY_USR_READ ) ,
2015-09-10 22:06:15 +03:00
KEY_ALLOC_NOT_IN_QUOTA ) ;
2014-11-05 18:01:13 +03:00
if ( IS_ERR ( key ) ) {
rc = PTR_ERR ( key ) ;
pr_err ( " Problem loading X.509 certificate (%d): %s \n " ,
rc , path ) ;
} else {
pr_notice ( " Loaded X.509 cert '%s': %s \n " ,
key_ref_to_ptr ( key ) - > description , path ) ;
key_ref_put ( key ) ;
}
kfree ( data ) ;
return 0 ;
}