2019-05-20 20:08:01 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2015-06-16 20:31:01 +03:00
/* RSA asymmetric public-key algorithm [RFC3447]
*
* Copyright ( c ) 2015 , Intel Corporation
* Authors : Tadeusz Struk < tadeusz . struk @ intel . com >
*/
# include <linux/module.h>
2016-06-14 16:14:58 +03:00
# include <linux/mpi.h>
2015-06-16 20:31:01 +03:00
# include <crypto/internal/rsa.h>
# include <crypto/internal/akcipher.h>
# include <crypto/akcipher.h>
2015-12-05 19:09:34 +03:00
# include <crypto/algapi.h>
2015-06-16 20:31:01 +03:00
2016-06-14 16:14:58 +03:00
struct rsa_mpi_key {
MPI n ;
MPI e ;
MPI d ;
} ;
2015-06-16 20:31:01 +03:00
/*
* RSAEP function [ RFC3447 sec 5.1 .1 ]
* c = m ^ e mod n ;
*/
2016-06-14 16:14:58 +03:00
static int _rsa_enc ( const struct rsa_mpi_key * key , MPI c , MPI m )
2015-06-16 20:31:01 +03:00
{
/* (1) Validate 0 <= m < n */
if ( mpi_cmp_ui ( m , 0 ) < 0 | | mpi_cmp ( m , key - > n ) > = 0 )
return - EINVAL ;
/* (2) c = m^e mod n */
return mpi_powm ( c , m , key - > e , key - > n ) ;
}
/*
* RSADP function [ RFC3447 sec 5.1 .2 ]
* m = c ^ d mod n ;
*/
2016-06-14 16:14:58 +03:00
static int _rsa_dec ( const struct rsa_mpi_key * key , MPI m , MPI c )
2015-06-16 20:31:01 +03:00
{
/* (1) Validate 0 <= c < n */
if ( mpi_cmp_ui ( c , 0 ) < 0 | | mpi_cmp ( c , key - > n ) > = 0 )
return - EINVAL ;
/* (2) m = c^d mod n */
return mpi_powm ( m , c , key - > d , key - > n ) ;
}
2016-06-14 16:14:58 +03:00
static inline struct rsa_mpi_key * rsa_get_key ( struct crypto_akcipher * tfm )
2015-06-16 20:31:01 +03:00
{
return akcipher_tfm_ctx ( tfm ) ;
}
static int rsa_enc ( struct akcipher_request * req )
{
struct crypto_akcipher * tfm = crypto_akcipher_reqtfm ( req ) ;
2016-06-14 16:14:58 +03:00
const struct rsa_mpi_key * pkey = rsa_get_key ( tfm ) ;
2015-06-16 20:31:01 +03:00
MPI m , c = mpi_alloc ( 0 ) ;
int ret = 0 ;
int sign ;
if ( ! c )
return - ENOMEM ;
if ( unlikely ( ! pkey - > n | | ! pkey - > e ) ) {
ret = - EINVAL ;
goto err_free_c ;
}
2015-10-08 19:26:55 +03:00
ret = - ENOMEM ;
m = mpi_read_raw_from_sgl ( req - > src , req - > src_len ) ;
if ( ! m )
2015-06-16 20:31:01 +03:00
goto err_free_c ;
ret = _rsa_enc ( pkey , c , m ) ;
if ( ret )
goto err_free_m ;
2016-06-29 14:32:21 +03:00
ret = mpi_write_to_sgl ( c , req - > dst , req - > dst_len , & sign ) ;
2015-06-16 20:31:01 +03:00
if ( ret )
goto err_free_m ;
2015-10-08 19:26:55 +03:00
if ( sign < 0 )
2015-06-16 20:31:01 +03:00
ret = - EBADMSG ;
err_free_m :
mpi_free ( m ) ;
err_free_c :
mpi_free ( c ) ;
return ret ;
}
static int rsa_dec ( struct akcipher_request * req )
{
struct crypto_akcipher * tfm = crypto_akcipher_reqtfm ( req ) ;
2016-06-14 16:14:58 +03:00
const struct rsa_mpi_key * pkey = rsa_get_key ( tfm ) ;
2015-06-16 20:31:01 +03:00
MPI c , m = mpi_alloc ( 0 ) ;
int ret = 0 ;
int sign ;
if ( ! m )
return - ENOMEM ;
if ( unlikely ( ! pkey - > n | | ! pkey - > d ) ) {
ret = - EINVAL ;
goto err_free_m ;
}
2015-10-08 19:26:55 +03:00
ret = - ENOMEM ;
c = mpi_read_raw_from_sgl ( req - > src , req - > src_len ) ;
if ( ! c )
2015-06-16 20:31:01 +03:00
goto err_free_m ;
ret = _rsa_dec ( pkey , m , c ) ;
if ( ret )
goto err_free_c ;
2016-06-29 14:32:21 +03:00
ret = mpi_write_to_sgl ( m , req - > dst , req - > dst_len , & sign ) ;
2015-06-16 20:31:01 +03:00
if ( ret )
goto err_free_c ;
2015-10-08 19:26:55 +03:00
if ( sign < 0 )
2015-06-16 20:31:01 +03:00
ret = - EBADMSG ;
err_free_c :
mpi_free ( c ) ;
err_free_m :
mpi_free ( m ) ;
return ret ;
}
2016-06-14 16:14:58 +03:00
static void rsa_free_mpi_key ( struct rsa_mpi_key * key )
{
mpi_free ( key - > d ) ;
mpi_free ( key - > e ) ;
mpi_free ( key - > n ) ;
key - > d = NULL ;
key - > e = NULL ;
key - > n = NULL ;
}
2015-07-16 01:28:43 +03:00
static int rsa_check_key_length ( unsigned int len )
{
switch ( len ) {
case 512 :
case 1024 :
case 1536 :
case 2048 :
case 3072 :
case 4096 :
return 0 ;
}
return - EINVAL ;
}
2015-10-08 19:26:55 +03:00
static int rsa_set_pub_key ( struct crypto_akcipher * tfm , const void * key ,
unsigned int keylen )
2015-06-16 20:31:01 +03:00
{
2016-06-14 16:14:58 +03:00
struct rsa_mpi_key * mpi_key = akcipher_tfm_ctx ( tfm ) ;
struct rsa_key raw_key = { 0 } ;
2015-07-16 01:28:43 +03:00
int ret ;
2015-06-16 20:31:01 +03:00
2016-06-14 16:14:58 +03:00
/* Free the old MPI key if any */
rsa_free_mpi_key ( mpi_key ) ;
ret = rsa_parse_pub_key ( & raw_key , key , keylen ) ;
2015-07-16 01:28:43 +03:00
if ( ret )
return ret ;
2016-06-14 16:14:58 +03:00
mpi_key - > e = mpi_read_raw_data ( raw_key . e , raw_key . e_sz ) ;
if ( ! mpi_key - > e )
goto err ;
mpi_key - > n = mpi_read_raw_data ( raw_key . n , raw_key . n_sz ) ;
if ( ! mpi_key - > n )
goto err ;
if ( rsa_check_key_length ( mpi_get_size ( mpi_key - > n ) < < 3 ) ) {
rsa_free_mpi_key ( mpi_key ) ;
return - EINVAL ;
2015-07-16 01:28:43 +03:00
}
2016-06-14 16:14:58 +03:00
return 0 ;
err :
rsa_free_mpi_key ( mpi_key ) ;
return - ENOMEM ;
2015-06-16 20:31:01 +03:00
}
2015-10-08 19:26:55 +03:00
static int rsa_set_priv_key ( struct crypto_akcipher * tfm , const void * key ,
unsigned int keylen )
{
2016-06-14 16:14:58 +03:00
struct rsa_mpi_key * mpi_key = akcipher_tfm_ctx ( tfm ) ;
struct rsa_key raw_key = { 0 } ;
2015-10-08 19:26:55 +03:00
int ret ;
2016-06-14 16:14:58 +03:00
/* Free the old MPI key if any */
rsa_free_mpi_key ( mpi_key ) ;
ret = rsa_parse_priv_key ( & raw_key , key , keylen ) ;
2015-10-08 19:26:55 +03:00
if ( ret )
return ret ;
2016-06-14 16:14:58 +03:00
mpi_key - > d = mpi_read_raw_data ( raw_key . d , raw_key . d_sz ) ;
if ( ! mpi_key - > d )
goto err ;
mpi_key - > e = mpi_read_raw_data ( raw_key . e , raw_key . e_sz ) ;
if ( ! mpi_key - > e )
goto err ;
mpi_key - > n = mpi_read_raw_data ( raw_key . n , raw_key . n_sz ) ;
if ( ! mpi_key - > n )
goto err ;
if ( rsa_check_key_length ( mpi_get_size ( mpi_key - > n ) < < 3 ) ) {
rsa_free_mpi_key ( mpi_key ) ;
return - EINVAL ;
2015-10-08 19:26:55 +03:00
}
2016-06-14 16:14:58 +03:00
return 0 ;
err :
rsa_free_mpi_key ( mpi_key ) ;
return - ENOMEM ;
2015-10-08 19:26:55 +03:00
}
2017-05-25 10:18:13 +03:00
static unsigned int rsa_max_size ( struct crypto_akcipher * tfm )
2015-10-08 19:26:55 +03:00
{
2016-06-14 16:14:58 +03:00
struct rsa_mpi_key * pkey = akcipher_tfm_ctx ( tfm ) ;
2015-10-08 19:26:55 +03:00
2017-05-25 10:18:13 +03:00
return mpi_get_size ( pkey - > n ) ;
2015-10-08 19:26:55 +03:00
}
2015-06-16 20:31:01 +03:00
static void rsa_exit_tfm ( struct crypto_akcipher * tfm )
{
2016-06-14 16:14:58 +03:00
struct rsa_mpi_key * pkey = akcipher_tfm_ctx ( tfm ) ;
2015-06-16 20:31:01 +03:00
2016-06-14 16:14:58 +03:00
rsa_free_mpi_key ( pkey ) ;
2015-06-16 20:31:01 +03:00
}
static struct akcipher_alg rsa = {
. encrypt = rsa_enc ,
. decrypt = rsa_dec ,
2015-10-08 19:26:55 +03:00
. set_priv_key = rsa_set_priv_key ,
. set_pub_key = rsa_set_pub_key ,
. max_size = rsa_max_size ,
2015-06-16 20:31:01 +03:00
. exit = rsa_exit_tfm ,
. base = {
. cra_name = " rsa " ,
. cra_driver_name = " rsa-generic " ,
. cra_priority = 100 ,
. cra_module = THIS_MODULE ,
2016-06-14 16:14:58 +03:00
. cra_ctxsize = sizeof ( struct rsa_mpi_key ) ,
2015-06-16 20:31:01 +03:00
} ,
} ;
static int rsa_init ( void )
{
2015-12-05 19:09:34 +03:00
int err ;
err = crypto_register_akcipher ( & rsa ) ;
if ( err )
return err ;
err = crypto_register_template ( & rsa_pkcs1pad_tmpl ) ;
if ( err ) {
crypto_unregister_akcipher ( & rsa ) ;
return err ;
}
return 0 ;
2015-06-16 20:31:01 +03:00
}
static void rsa_exit ( void )
{
2015-12-05 19:09:34 +03:00
crypto_unregister_template ( & rsa_pkcs1pad_tmpl ) ;
2015-06-16 20:31:01 +03:00
crypto_unregister_akcipher ( & rsa ) ;
}
2019-04-12 07:57:42 +03:00
subsys_initcall ( rsa_init ) ;
2015-06-16 20:31:01 +03:00
module_exit ( rsa_exit ) ;
MODULE_ALIAS_CRYPTO ( " rsa " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " RSA generic algorithm " ) ;