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 >
*/
2021-11-21 17:31:27 +03:00
# include <linux/fips.h>
2015-06-16 20:31:01 +03:00
# 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 ;
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
MPI p ;
MPI q ;
MPI dp ;
MPI dq ;
MPI qinv ;
2016-06-14 16:14:58 +03:00
} ;
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 ]
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
* m_1 = c ^ dP mod p ;
* m_2 = c ^ dQ mod q ;
* h = ( m_1 - m_2 ) * qInv mod p ;
* m = m_2 + q * h ;
2015-06-16 20:31:01 +03:00
*/
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
static int _rsa_dec_crt ( const struct rsa_mpi_key * key , MPI m_or_m1_or_h , MPI c )
2015-06-16 20:31:01 +03:00
{
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
MPI m2 , m12_or_qh ;
int ret = - ENOMEM ;
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 ;
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
m2 = mpi_alloc ( 0 ) ;
m12_or_qh = mpi_alloc ( 0 ) ;
if ( ! m2 | | ! m12_or_qh )
goto err_free_mpi ;
/* (2i) m_1 = c^dP mod p */
ret = mpi_powm ( m_or_m1_or_h , c , key - > dp , key - > p ) ;
if ( ret )
goto err_free_mpi ;
/* (2i) m_2 = c^dQ mod q */
ret = mpi_powm ( m2 , c , key - > dq , key - > q ) ;
if ( ret )
goto err_free_mpi ;
/* (2iii) h = (m_1 - m_2) * qInv mod p */
mpi_sub ( m12_or_qh , m_or_m1_or_h , m2 ) ;
mpi_mulm ( m_or_m1_or_h , m12_or_qh , key - > qinv , key - > p ) ;
/* (2iv) m = m_2 + q * h */
mpi_mul ( m12_or_qh , key - > q , m_or_m1_or_h ) ;
mpi_addm ( m_or_m1_or_h , m2 , m12_or_qh , key - > n ) ;
ret = 0 ;
err_free_mpi :
mpi_free ( m12_or_qh ) ;
mpi_free ( m2 ) ;
return ret ;
2015-06-16 20:31:01 +03:00
}
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 ;
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
ret = _rsa_dec_crt ( pkey , m , c ) ;
2015-06-16 20:31:01 +03:00
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 ) ;
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
mpi_free ( key - > p ) ;
mpi_free ( key - > q ) ;
mpi_free ( key - > dp ) ;
mpi_free ( key - > dq ) ;
mpi_free ( key - > qinv ) ;
2016-06-14 16:14:58 +03:00
key - > d = NULL ;
key - > e = NULL ;
key - > n = NULL ;
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
key - > p = NULL ;
key - > q = NULL ;
key - > dp = NULL ;
key - > dq = NULL ;
key - > qinv = NULL ;
2016-06-14 16:14:58 +03:00
}
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 :
2021-11-21 17:31:27 +03:00
if ( fips_enabled )
return - EINVAL ;
fallthrough ;
2015-07-16 01:28:43 +03:00
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 ;
crypto: rsa - implement Chinese Remainder Theorem for faster private key operations
Changes from v1:
* exported mpi_sub and mpi_mul, otherwise the build fails when RSA is a module
The kernel RSA ASN.1 private key parser already supports only private keys with
additional values to be used with the Chinese Remainder Theorem [1], but these
values are currently not used.
This rudimentary CRT implementation speeds up RSA private key operations for the
following Go benchmark up to ~3x.
This implementation also tries to minimise the allocation of additional MPIs,
so existing MPIs are reused as much as possible (hence the variable names are a
bit weird).
The benchmark used:
```
package keyring_test
import (
"crypto"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"io"
"syscall"
"testing"
"unsafe"
)
type KeySerial int32
type Keyring int32
const (
KEY_SPEC_PROCESS_KEYRING Keyring = -2
KEYCTL_PKEY_SIGN = 27
)
var (
keyTypeAsym = []byte("asymmetric\x00")
sha256pkcs1 = []byte("enc=pkcs1 hash=sha256\x00")
)
func (keyring Keyring) LoadAsym(desc string, payload []byte) (KeySerial, error) {
cdesc := []byte(desc + "\x00")
serial, _, errno := syscall.Syscall6(syscall.SYS_ADD_KEY, uintptr(unsafe.Pointer(&keyTypeAsym[0])), uintptr(unsafe.Pointer(&cdesc[0])), uintptr(unsafe.Pointer(&payload[0])), uintptr(len(payload)), uintptr(keyring), uintptr(0))
if errno == 0 {
return KeySerial(serial), nil
}
return KeySerial(serial), errno
}
type pkeyParams struct {
key_id KeySerial
in_len uint32
out_or_in2_len uint32
__spare [7]uint32
}
// the output signature buffer is an input parameter here, because we want to
// avoid Go buffer allocation leaking into our benchmarks
func (key KeySerial) Sign(info, digest, out []byte) error {
var params pkeyParams
params.key_id = key
params.in_len = uint32(len(digest))
params.out_or_in2_len = uint32(len(out))
_, _, errno := syscall.Syscall6(syscall.SYS_KEYCTL, KEYCTL_PKEY_SIGN, uintptr(unsafe.Pointer(¶ms)), uintptr(unsafe.Pointer(&info[0])), uintptr(unsafe.Pointer(&digest[0])), uintptr(unsafe.Pointer(&out[0])), uintptr(0))
if errno == 0 {
return nil
}
return errno
}
func BenchmarkSign(b *testing.B) {
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
b.Fatalf("failed to generate private key: %v", err)
}
pkcs8, err := x509.MarshalPKCS8PrivateKey(priv)
if err != nil {
b.Fatalf("failed to serialize the private key to PKCS8 blob: %v", err)
}
serial, err := KEY_SPEC_PROCESS_KEYRING.LoadAsym("test rsa key", pkcs8)
if err != nil {
b.Fatalf("failed to load the private key into the keyring: %v", err)
}
b.Logf("loaded test rsa key: %v", serial)
digest := make([]byte, 32)
_, err = io.ReadFull(rand.Reader, digest)
if err != nil {
b.Fatalf("failed to generate a random digest: %v", err)
}
sig := make([]byte, 256)
for n := 0; n < b.N; n++ {
err = serial.Sign(sha256pkcs1, digest, sig)
if err != nil {
b.Fatalf("failed to sign the digest: %v", err)
}
}
err = rsa.VerifyPKCS1v15(&priv.PublicKey, crypto.SHA256, digest, sig)
if err != nil {
b.Fatalf("failed to verify the signature: %v", err)
}
}
```
[1]: https://en.wikipedia.org/wiki/RSA_(cryptosystem)#Using_the_Chinese_remainder_algorithm
Signed-off-by: Ignat Korchagin <ignat@cloudflare.com>
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2022-06-17 11:42:10 +03:00
mpi_key - > p = mpi_read_raw_data ( raw_key . p , raw_key . p_sz ) ;
if ( ! mpi_key - > p )
goto err ;
mpi_key - > q = mpi_read_raw_data ( raw_key . q , raw_key . q_sz ) ;
if ( ! mpi_key - > q )
goto err ;
mpi_key - > dp = mpi_read_raw_data ( raw_key . dp , raw_key . dp_sz ) ;
if ( ! mpi_key - > dp )
goto err ;
mpi_key - > dq = mpi_read_raw_data ( raw_key . dq , raw_key . dq_sz ) ;
if ( ! mpi_key - > dq )
goto err ;
mpi_key - > qinv = mpi_read_raw_data ( raw_key . qinv , raw_key . qinv_sz ) ;
if ( ! mpi_key - > qinv )
goto err ;
2016-06-14 16:14:58 +03:00
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
} ,
} ;
2022-09-15 06:36:15 +03:00
static int __init rsa_init ( void )
2015-06-16 20:31:01 +03:00
{
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
}
2022-09-15 06:36:15 +03:00
static void __exit rsa_exit ( void )
2015-06-16 20:31:01 +03:00
{
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 " ) ;