2019-05-20 20:08:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2012-09-22 02:24:55 +04:00
/* In-software asymmetric public-key crypto subtype
*
* See Documentation / crypto / asymmetric - keys . txt
*
* Copyright ( C ) 2012 Red Hat , Inc . All Rights Reserved .
* Written by David Howells ( dhowells @ redhat . com )
*/
# define pr_fmt(fmt) "PKEY: "fmt
# include <linux/module.h>
# include <linux/export.h>
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/seq_file.h>
2016-03-04 00:49:27 +03:00
# include <linux/scatterlist.h>
2012-09-22 02:24:55 +04:00
# include <keys/asymmetric-subtype.h>
2016-02-02 21:08:53 +03:00
# include <crypto/public_key.h>
2016-03-04 00:49:27 +03:00
# include <crypto/akcipher.h>
2012-09-22 02:24:55 +04:00
2017-11-15 19:38:45 +03:00
MODULE_DESCRIPTION ( " In-software asymmetric public-key subtype " ) ;
MODULE_AUTHOR ( " Red Hat, Inc. " ) ;
2012-09-22 02:24:55 +04:00
MODULE_LICENSE ( " GPL " ) ;
/*
* Provide a part of a description of the key for / proc / keys .
*/
static void public_key_describe ( const struct key * asymmetric_key ,
struct seq_file * m )
{
2015-10-21 16:04:48 +03:00
struct public_key * key = asymmetric_key - > payload . data [ asym_crypto ] ;
2012-09-22 02:24:55 +04:00
if ( key )
2016-03-04 00:49:27 +03:00
seq_printf ( m , " %s.%s " , key - > id_type , key - > pkey_algo ) ;
2012-09-22 02:24:55 +04:00
}
/*
* Destroy a public key algorithm key .
*/
2016-04-06 18:13:33 +03:00
void public_key_free ( struct public_key * key )
2012-09-22 02:24:55 +04:00
{
2016-04-06 18:13:33 +03:00
if ( key ) {
2016-02-02 21:08:53 +03:00
kfree ( key - > key ) ;
2019-04-11 18:51:17 +03:00
kfree ( key - > params ) ;
2016-04-06 18:13:33 +03:00
kfree ( key ) ;
}
}
EXPORT_SYMBOL_GPL ( public_key_free ) ;
/*
* Destroy a public key algorithm key .
*/
static void public_key_destroy ( void * payload0 , void * payload3 )
{
public_key_free ( payload0 ) ;
public_key_signature_free ( payload3 ) ;
2012-09-22 02:24:55 +04:00
}
2018-10-09 19:47:23 +03:00
/*
* Determine the crypto algorithm name .
*/
static
int software_key_determine_akcipher ( const char * encoding ,
const char * hash_algo ,
const struct public_key * pkey ,
char alg_name [ CRYPTO_MAX_ALG_NAME ] )
{
int n ;
if ( strcmp ( encoding , " pkcs1 " ) = = 0 ) {
/* The data wangled by the RSA algorithm is typically padded
* and encoded in some manner , such as EMSA - PKCS1 - 1 _5 [ RFC3447
* sec 8.2 ] .
*/
if ( ! hash_algo )
n = snprintf ( alg_name , CRYPTO_MAX_ALG_NAME ,
" pkcs1pad(%s) " ,
pkey - > pkey_algo ) ;
else
n = snprintf ( alg_name , CRYPTO_MAX_ALG_NAME ,
" pkcs1pad(%s,%s) " ,
pkey - > pkey_algo , hash_algo ) ;
return n > = CRYPTO_MAX_ALG_NAME ? - EINVAL : 0 ;
}
if ( strcmp ( encoding , " raw " ) = = 0 ) {
strcpy ( alg_name , pkey - > pkey_algo ) ;
return 0 ;
}
return - ENOPKG ;
}
2019-04-11 18:51:17 +03:00
static u8 * pkey_pack_u32 ( u8 * dst , u32 val )
{
memcpy ( dst , & val , sizeof ( val ) ) ;
return dst + sizeof ( val ) ;
}
2018-10-09 19:47:23 +03:00
/*
* Query information about a key .
*/
static int software_key_query ( const struct kernel_pkey_params * params ,
struct kernel_pkey_query * info )
{
struct crypto_akcipher * tfm ;
struct public_key * pkey = params - > key - > payload . data [ asym_crypto ] ;
char alg_name [ CRYPTO_MAX_ALG_NAME ] ;
2019-04-11 18:51:17 +03:00
u8 * key , * ptr ;
2018-10-09 19:47:23 +03:00
int ret , len ;
ret = software_key_determine_akcipher ( params - > encoding ,
params - > hash_algo ,
pkey , alg_name ) ;
if ( ret < 0 )
return ret ;
tfm = crypto_alloc_akcipher ( alg_name , 0 , 0 ) ;
if ( IS_ERR ( tfm ) )
return PTR_ERR ( tfm ) ;
2019-04-11 18:51:17 +03:00
key = kmalloc ( pkey - > keylen + sizeof ( u32 ) * 2 + pkey - > paramlen ,
GFP_KERNEL ) ;
if ( ! key )
goto error_free_tfm ;
memcpy ( key , pkey - > key , pkey - > keylen ) ;
ptr = key + pkey - > keylen ;
ptr = pkey_pack_u32 ( ptr , pkey - > algo ) ;
ptr = pkey_pack_u32 ( ptr , pkey - > paramlen ) ;
memcpy ( ptr , pkey - > params , pkey - > paramlen ) ;
2018-10-09 19:47:31 +03:00
if ( pkey - > key_is_private )
2019-04-11 18:51:17 +03:00
ret = crypto_akcipher_set_priv_key ( tfm , key , pkey - > keylen ) ;
2018-10-09 19:47:31 +03:00
else
2019-04-11 18:51:17 +03:00
ret = crypto_akcipher_set_pub_key ( tfm , key , pkey - > keylen ) ;
2018-10-09 19:47:23 +03:00
if ( ret < 0 )
2019-04-11 18:51:17 +03:00
goto error_free_key ;
2018-10-09 19:47:23 +03:00
len = crypto_akcipher_maxsize ( tfm ) ;
info - > key_size = len * 8 ;
info - > max_data_size = len ;
info - > max_sig_size = len ;
info - > max_enc_size = len ;
info - > max_dec_size = len ;
2018-10-09 19:47:38 +03:00
info - > supported_ops = ( KEYCTL_SUPPORTS_ENCRYPT |
KEYCTL_SUPPORTS_VERIFY ) ;
if ( pkey - > key_is_private )
info - > supported_ops | = ( KEYCTL_SUPPORTS_DECRYPT |
KEYCTL_SUPPORTS_SIGN ) ;
2018-10-09 19:47:23 +03:00
ret = 0 ;
2019-04-11 18:51:17 +03:00
error_free_key :
kfree ( key ) ;
2018-10-09 19:47:23 +03:00
error_free_tfm :
crypto_free_akcipher ( tfm ) ;
pr_devel ( " <==%s() = %d \n " , __func__ , ret ) ;
return ret ;
}
2018-10-09 19:47:38 +03:00
/*
* Do encryption , decryption and signing ops .
*/
static int software_key_eds_op ( struct kernel_pkey_params * params ,
const void * in , void * out )
{
const struct public_key * pkey = params - > key - > payload . data [ asym_crypto ] ;
struct akcipher_request * req ;
struct crypto_akcipher * tfm ;
struct crypto_wait cwait ;
struct scatterlist in_sg , out_sg ;
char alg_name [ CRYPTO_MAX_ALG_NAME ] ;
2019-04-11 18:51:17 +03:00
char * key , * ptr ;
2018-10-09 19:47:38 +03:00
int ret ;
pr_devel ( " ==>%s() \n " , __func__ ) ;
ret = software_key_determine_akcipher ( params - > encoding ,
params - > hash_algo ,
pkey , alg_name ) ;
if ( ret < 0 )
return ret ;
tfm = crypto_alloc_akcipher ( alg_name , 0 , 0 ) ;
if ( IS_ERR ( tfm ) )
return PTR_ERR ( tfm ) ;
req = akcipher_request_alloc ( tfm , GFP_KERNEL ) ;
if ( ! req )
goto error_free_tfm ;
2019-04-11 18:51:17 +03:00
key = kmalloc ( pkey - > keylen + sizeof ( u32 ) * 2 + pkey - > paramlen ,
GFP_KERNEL ) ;
if ( ! key )
goto error_free_req ;
memcpy ( key , pkey - > key , pkey - > keylen ) ;
ptr = key + pkey - > keylen ;
ptr = pkey_pack_u32 ( ptr , pkey - > algo ) ;
ptr = pkey_pack_u32 ( ptr , pkey - > paramlen ) ;
memcpy ( ptr , pkey - > params , pkey - > paramlen ) ;
2018-10-09 19:47:38 +03:00
if ( pkey - > key_is_private )
2019-04-11 18:51:17 +03:00
ret = crypto_akcipher_set_priv_key ( tfm , key , pkey - > keylen ) ;
2018-10-09 19:47:38 +03:00
else
2019-04-11 18:51:17 +03:00
ret = crypto_akcipher_set_pub_key ( tfm , key , pkey - > keylen ) ;
2018-10-09 19:47:38 +03:00
if ( ret )
2019-04-11 18:51:17 +03:00
goto error_free_key ;
2018-10-09 19:47:38 +03:00
sg_init_one ( & in_sg , in , params - > in_len ) ;
sg_init_one ( & out_sg , out , params - > out_len ) ;
akcipher_request_set_crypt ( req , & in_sg , & out_sg , params - > in_len ,
params - > out_len ) ;
crypto_init_wait ( & cwait ) ;
akcipher_request_set_callback ( req , CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP ,
crypto_req_done , & cwait ) ;
/* Perform the encryption calculation. */
switch ( params - > op ) {
case kernel_pkey_encrypt :
ret = crypto_akcipher_encrypt ( req ) ;
break ;
case kernel_pkey_decrypt :
ret = crypto_akcipher_decrypt ( req ) ;
break ;
case kernel_pkey_sign :
ret = crypto_akcipher_sign ( req ) ;
break ;
default :
BUG ( ) ;
}
ret = crypto_wait_req ( ret , & cwait ) ;
if ( ret = = 0 )
ret = req - > dst_len ;
2019-04-11 18:51:17 +03:00
error_free_key :
kfree ( key ) ;
2018-10-09 19:47:38 +03:00
error_free_req :
akcipher_request_free ( req ) ;
error_free_tfm :
crypto_free_akcipher ( tfm ) ;
pr_devel ( " <==%s() = %d \n " , __func__ , ret ) ;
return ret ;
}
2012-09-22 02:24:55 +04:00
/*
* Verify a signature using a public key .
*/
2016-02-02 21:08:53 +03:00
int public_key_verify_signature ( const struct public_key * pkey ,
2013-08-30 19:15:30 +04:00
const struct public_key_signature * sig )
2012-09-22 02:24:55 +04:00
{
2017-10-18 10:00:40 +03:00
struct crypto_wait cwait ;
2016-03-04 00:49:27 +03:00
struct crypto_akcipher * tfm ;
struct akcipher_request * req ;
crypto: akcipher - new verify API for public key algorithms
Previous akcipher .verify() just `decrypts' (using RSA encrypt which is
using public key) signature to uncover message hash, which was then
compared in upper level public_key_verify_signature() with the expected
hash value, which itself was never passed into verify().
This approach was incompatible with EC-DSA family of algorithms,
because, to verify a signature EC-DSA algorithm also needs a hash value
as input; then it's used (together with a signature divided into halves
`r||s') to produce a witness value, which is then compared with `r' to
determine if the signature is correct. Thus, for EC-DSA, nor
requirements of .verify() itself, nor its output expectations in
public_key_verify_signature() wasn't sufficient.
Make improved .verify() call which gets hash value as input and produce
complete signature check without any output besides status.
Now for the top level verification only crypto_akcipher_verify() needs
to be called and its return value inspected.
Make sure that `digest' is in kmalloc'd memory (in place of `output`) in
{public,tpm}_key_verify_signature() as insisted by Herbert Xu, and will
be changed in the following commit.
Cc: David Howells <dhowells@redhat.com>
Cc: keyrings@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Reviewed-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:15 +03:00
struct scatterlist src_sg [ 2 ] ;
2018-10-09 19:47:23 +03:00
char alg_name [ CRYPTO_MAX_ALG_NAME ] ;
2019-04-11 18:51:17 +03:00
char * key , * ptr ;
2017-12-08 18:13:29 +03:00
int ret ;
2016-03-04 00:49:27 +03:00
pr_devel ( " ==>%s() \n " , __func__ ) ;
2016-02-02 21:08:53 +03:00
BUG_ON ( ! pkey ) ;
2013-08-30 19:15:30 +04:00
BUG_ON ( ! sig ) ;
2016-02-02 21:08:53 +03:00
BUG_ON ( ! sig - > s ) ;
2012-09-22 02:24:55 +04:00
2018-10-09 19:47:23 +03:00
ret = software_key_determine_akcipher ( sig - > encoding ,
sig - > hash_algo ,
pkey , alg_name ) ;
if ( ret < 0 )
return ret ;
2016-03-04 00:49:27 +03:00
tfm = crypto_alloc_akcipher ( alg_name , 0 , 0 ) ;
if ( IS_ERR ( tfm ) )
return PTR_ERR ( tfm ) ;
2017-12-08 18:13:29 +03:00
ret = - ENOMEM ;
2016-03-04 00:49:27 +03:00
req = akcipher_request_alloc ( tfm , GFP_KERNEL ) ;
if ( ! req )
goto error_free_tfm ;
2019-04-11 18:51:17 +03:00
key = kmalloc ( pkey - > keylen + sizeof ( u32 ) * 2 + pkey - > paramlen ,
GFP_KERNEL ) ;
if ( ! key )
goto error_free_req ;
memcpy ( key , pkey - > key , pkey - > keylen ) ;
ptr = key + pkey - > keylen ;
ptr = pkey_pack_u32 ( ptr , pkey - > algo ) ;
ptr = pkey_pack_u32 ( ptr , pkey - > paramlen ) ;
memcpy ( ptr , pkey - > params , pkey - > paramlen ) ;
2018-10-09 19:47:31 +03:00
if ( pkey - > key_is_private )
2019-04-11 18:51:17 +03:00
ret = crypto_akcipher_set_priv_key ( tfm , key , pkey - > keylen ) ;
2018-10-09 19:47:31 +03:00
else
2019-04-11 18:51:17 +03:00
ret = crypto_akcipher_set_pub_key ( tfm , key , pkey - > keylen ) ;
2016-03-04 00:49:27 +03:00
if ( ret )
2019-04-11 18:51:17 +03:00
goto error_free_key ;
2016-03-04 00:49:27 +03:00
crypto: akcipher - new verify API for public key algorithms
Previous akcipher .verify() just `decrypts' (using RSA encrypt which is
using public key) signature to uncover message hash, which was then
compared in upper level public_key_verify_signature() with the expected
hash value, which itself was never passed into verify().
This approach was incompatible with EC-DSA family of algorithms,
because, to verify a signature EC-DSA algorithm also needs a hash value
as input; then it's used (together with a signature divided into halves
`r||s') to produce a witness value, which is then compared with `r' to
determine if the signature is correct. Thus, for EC-DSA, nor
requirements of .verify() itself, nor its output expectations in
public_key_verify_signature() wasn't sufficient.
Make improved .verify() call which gets hash value as input and produce
complete signature check without any output besides status.
Now for the top level verification only crypto_akcipher_verify() needs
to be called and its return value inspected.
Make sure that `digest' is in kmalloc'd memory (in place of `output`) in
{public,tpm}_key_verify_signature() as insisted by Herbert Xu, and will
be changed in the following commit.
Cc: David Howells <dhowells@redhat.com>
Cc: keyrings@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Reviewed-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:15 +03:00
sg_init_table ( src_sg , 2 ) ;
sg_set_buf ( & src_sg [ 0 ] , sig - > s , sig - > s_size ) ;
2019-04-11 18:51:16 +03:00
sg_set_buf ( & src_sg [ 1 ] , sig - > digest , sig - > digest_size ) ;
crypto: akcipher - new verify API for public key algorithms
Previous akcipher .verify() just `decrypts' (using RSA encrypt which is
using public key) signature to uncover message hash, which was then
compared in upper level public_key_verify_signature() with the expected
hash value, which itself was never passed into verify().
This approach was incompatible with EC-DSA family of algorithms,
because, to verify a signature EC-DSA algorithm also needs a hash value
as input; then it's used (together with a signature divided into halves
`r||s') to produce a witness value, which is then compared with `r' to
determine if the signature is correct. Thus, for EC-DSA, nor
requirements of .verify() itself, nor its output expectations in
public_key_verify_signature() wasn't sufficient.
Make improved .verify() call which gets hash value as input and produce
complete signature check without any output besides status.
Now for the top level verification only crypto_akcipher_verify() needs
to be called and its return value inspected.
Make sure that `digest' is in kmalloc'd memory (in place of `output`) in
{public,tpm}_key_verify_signature() as insisted by Herbert Xu, and will
be changed in the following commit.
Cc: David Howells <dhowells@redhat.com>
Cc: keyrings@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Reviewed-by: Denis Kenzior <denkenz@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-04-11 18:51:15 +03:00
akcipher_request_set_crypt ( req , src_sg , NULL , sig - > s_size ,
sig - > digest_size ) ;
2017-10-18 10:00:40 +03:00
crypto_init_wait ( & cwait ) ;
2016-03-04 00:49:27 +03:00
akcipher_request_set_callback ( req , CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP ,
2017-10-18 10:00:40 +03:00
crypto_req_done , & cwait ) ;
ret = crypto_wait_req ( crypto_akcipher_verify ( req ) , & cwait ) ;
2012-09-22 02:24:55 +04:00
2019-04-11 18:51:17 +03:00
error_free_key :
kfree ( key ) ;
2016-03-04 00:49:27 +03:00
error_free_req :
akcipher_request_free ( req ) ;
error_free_tfm :
crypto_free_akcipher ( tfm ) ;
pr_devel ( " <==%s() = %d \n " , __func__ , ret ) ;
2017-12-08 18:13:29 +03:00
if ( WARN_ON_ONCE ( ret > 0 ) )
ret = - EINVAL ;
2016-03-04 00:49:27 +03:00
return ret ;
2013-08-30 19:15:30 +04:00
}
EXPORT_SYMBOL_GPL ( public_key_verify_signature ) ;
static int public_key_verify_signature_2 ( const struct key * key ,
const struct public_key_signature * sig )
{
2015-10-21 16:04:48 +03:00
const struct public_key * pk = key - > payload . data [ asym_crypto ] ;
2013-08-30 19:15:30 +04:00
return public_key_verify_signature ( pk , sig ) ;
2012-09-22 02:24:55 +04:00
}
/*
* Public key algorithm asymmetric key subtype
*/
struct asymmetric_key_subtype public_key_subtype = {
. owner = THIS_MODULE ,
. name = " public_key " ,
2014-09-02 16:52:10 +04:00
. name_len = sizeof ( " public_key " ) - 1 ,
2012-09-22 02:24:55 +04:00
. describe = public_key_describe ,
. destroy = public_key_destroy ,
2018-10-09 19:47:23 +03:00
. query = software_key_query ,
2018-10-09 19:47:38 +03:00
. eds_op = software_key_eds_op ,
2013-08-30 19:15:30 +04:00
. verify_signature = public_key_verify_signature_2 ,
2012-09-22 02:24:55 +04:00
} ;
EXPORT_SYMBOL_GPL ( public_key_subtype ) ;