mirror of
https://github.com/torvalds/linux.git
synced 2024-11-21 19:46:16 +00:00
crypto: akcipher - Drop sign/verify operations
A sig_alg backend has just been introduced and all asymmetric sign/verify algorithms have been migrated to it. The sign/verify operations can thus be dropped from akcipher_alg. It is now purely for asymmetric encrypt/decrypt. Move struct crypto_akcipher_sync_data from internal.h to akcipher.c and unexport crypto_akcipher_sync_{prep,post}(): They're no longer used by sig.c but only locally in akcipher.c. In crypto_akcipher_sync_{prep,post}(), drop various NULL pointer checks for data->dst as they were only necessary for the verify operation. In the crypto_sig_*() API calls, remove the forks that were necessary while algorithms were converted from crypto_akcipher to crypto_sig one by one. In struct akcipher_testvec, remove the "params", "param_len" and "algo" elements as they were only needed for the ecrdsa verify operation. Remove corresponding dead code from test_akcipher_one() as well. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
a16a17d3ea
commit
6b34562f0c
@ -11,7 +11,7 @@ Asymmetric Cipher API
|
|||||||
:doc: Generic Public Key API
|
:doc: Generic Public Key API
|
||||||
|
|
||||||
.. kernel-doc:: include/crypto/akcipher.h
|
.. kernel-doc:: include/crypto/akcipher.h
|
||||||
:functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt crypto_akcipher_sign crypto_akcipher_verify
|
:functions: crypto_alloc_akcipher crypto_free_akcipher crypto_akcipher_set_pub_key crypto_akcipher_set_priv_key crypto_akcipher_maxsize crypto_akcipher_encrypt crypto_akcipher_decrypt
|
||||||
|
|
||||||
Asymmetric Cipher Request Handle
|
Asymmetric Cipher Request Handle
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
@ -20,6 +20,19 @@
|
|||||||
|
|
||||||
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
|
#define CRYPTO_ALG_TYPE_AHASH_MASK 0x0000000e
|
||||||
|
|
||||||
|
struct crypto_akcipher_sync_data {
|
||||||
|
struct crypto_akcipher *tfm;
|
||||||
|
const void *src;
|
||||||
|
void *dst;
|
||||||
|
unsigned int slen;
|
||||||
|
unsigned int dlen;
|
||||||
|
|
||||||
|
struct akcipher_request *req;
|
||||||
|
struct crypto_wait cwait;
|
||||||
|
struct scatterlist sg;
|
||||||
|
u8 *buf;
|
||||||
|
};
|
||||||
|
|
||||||
static int __maybe_unused crypto_akcipher_report(
|
static int __maybe_unused crypto_akcipher_report(
|
||||||
struct sk_buff *skb, struct crypto_alg *alg)
|
struct sk_buff *skb, struct crypto_alg *alg)
|
||||||
{
|
{
|
||||||
@ -126,10 +139,6 @@ int crypto_register_akcipher(struct akcipher_alg *alg)
|
|||||||
{
|
{
|
||||||
struct crypto_alg *base = &alg->base;
|
struct crypto_alg *base = &alg->base;
|
||||||
|
|
||||||
if (!alg->sign)
|
|
||||||
alg->sign = akcipher_default_op;
|
|
||||||
if (!alg->verify)
|
|
||||||
alg->verify = akcipher_default_op;
|
|
||||||
if (!alg->encrypt)
|
if (!alg->encrypt)
|
||||||
alg->encrypt = akcipher_default_op;
|
alg->encrypt = akcipher_default_op;
|
||||||
if (!alg->decrypt)
|
if (!alg->decrypt)
|
||||||
@ -158,7 +167,7 @@ int akcipher_register_instance(struct crypto_template *tmpl,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(akcipher_register_instance);
|
EXPORT_SYMBOL_GPL(akcipher_register_instance);
|
||||||
|
|
||||||
int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
|
static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
|
||||||
{
|
{
|
||||||
unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
|
unsigned int reqsize = crypto_akcipher_reqsize(data->tfm);
|
||||||
struct akcipher_request *req;
|
struct akcipher_request *req;
|
||||||
@ -167,10 +176,7 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
|
|||||||
unsigned int len;
|
unsigned int len;
|
||||||
u8 *buf;
|
u8 *buf;
|
||||||
|
|
||||||
if (data->dst)
|
mlen = max(data->slen, data->dlen);
|
||||||
mlen = max(data->slen, data->dlen);
|
|
||||||
else
|
|
||||||
mlen = data->slen + data->dlen;
|
|
||||||
|
|
||||||
len = sizeof(*req) + reqsize + mlen;
|
len = sizeof(*req) + reqsize + mlen;
|
||||||
if (len < mlen)
|
if (len < mlen)
|
||||||
@ -189,8 +195,7 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
|
|||||||
|
|
||||||
sg = &data->sg;
|
sg = &data->sg;
|
||||||
sg_init_one(sg, buf, mlen);
|
sg_init_one(sg, buf, mlen);
|
||||||
akcipher_request_set_crypt(req, sg, data->dst ? sg : NULL,
|
akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
|
||||||
data->slen, data->dlen);
|
|
||||||
|
|
||||||
crypto_init_wait(&data->cwait);
|
crypto_init_wait(&data->cwait);
|
||||||
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
|
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
|
||||||
@ -198,18 +203,16 @@ int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep);
|
|
||||||
|
|
||||||
int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err)
|
static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
|
||||||
|
int err)
|
||||||
{
|
{
|
||||||
err = crypto_wait_req(err, &data->cwait);
|
err = crypto_wait_req(err, &data->cwait);
|
||||||
if (data->dst)
|
memcpy(data->dst, data->buf, data->dlen);
|
||||||
memcpy(data->dst, data->buf, data->dlen);
|
|
||||||
data->dlen = data->req->dst_len;
|
data->dlen = data->req->dst_len;
|
||||||
kfree_sensitive(data->req);
|
kfree_sensitive(data->req);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_post);
|
|
||||||
|
|
||||||
int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
|
int crypto_akcipher_sync_encrypt(struct crypto_akcipher *tfm,
|
||||||
const void *src, unsigned int slen,
|
const void *src, unsigned int slen,
|
||||||
@ -248,34 +251,5 @@ int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
|
EXPORT_SYMBOL_GPL(crypto_akcipher_sync_decrypt);
|
||||||
|
|
||||||
static void crypto_exit_akcipher_ops_sig(struct crypto_tfm *tfm)
|
|
||||||
{
|
|
||||||
struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
|
|
||||||
|
|
||||||
crypto_free_akcipher(*ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm)
|
|
||||||
{
|
|
||||||
struct crypto_akcipher **ctx = crypto_tfm_ctx(tfm);
|
|
||||||
struct crypto_alg *calg = tfm->__crt_alg;
|
|
||||||
struct crypto_akcipher *akcipher;
|
|
||||||
|
|
||||||
if (!crypto_mod_get(calg))
|
|
||||||
return -EAGAIN;
|
|
||||||
|
|
||||||
akcipher = crypto_create_tfm(calg, &crypto_akcipher_type);
|
|
||||||
if (IS_ERR(akcipher)) {
|
|
||||||
crypto_mod_put(calg);
|
|
||||||
return PTR_ERR(akcipher);
|
|
||||||
}
|
|
||||||
|
|
||||||
*ctx = akcipher;
|
|
||||||
tfm->exit = crypto_exit_akcipher_ops_sig;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(crypto_init_akcipher_ops_sig);
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_DESCRIPTION("Generic public key cipher type");
|
MODULE_DESCRIPTION("Generic public key cipher type");
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
|
||||||
struct akcipher_request;
|
|
||||||
struct crypto_akcipher;
|
|
||||||
struct crypto_instance;
|
struct crypto_instance;
|
||||||
struct crypto_template;
|
struct crypto_template;
|
||||||
|
|
||||||
@ -35,19 +33,6 @@ struct crypto_larval {
|
|||||||
bool test_started;
|
bool test_started;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct crypto_akcipher_sync_data {
|
|
||||||
struct crypto_akcipher *tfm;
|
|
||||||
const void *src;
|
|
||||||
void *dst;
|
|
||||||
unsigned int slen;
|
|
||||||
unsigned int dlen;
|
|
||||||
|
|
||||||
struct akcipher_request *req;
|
|
||||||
struct crypto_wait cwait;
|
|
||||||
struct scatterlist sg;
|
|
||||||
u8 *buf;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
CRYPTOA_UNSPEC,
|
CRYPTOA_UNSPEC,
|
||||||
CRYPTOA_ALG,
|
CRYPTOA_ALG,
|
||||||
@ -129,10 +114,6 @@ void *crypto_create_tfm_node(struct crypto_alg *alg,
|
|||||||
void *crypto_clone_tfm(const struct crypto_type *frontend,
|
void *crypto_clone_tfm(const struct crypto_type *frontend,
|
||||||
struct crypto_tfm *otfm);
|
struct crypto_tfm *otfm);
|
||||||
|
|
||||||
int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data);
|
|
||||||
int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err);
|
|
||||||
int crypto_init_akcipher_ops_sig(struct crypto_tfm *tfm);
|
|
||||||
|
|
||||||
static inline void *crypto_create_tfm(struct crypto_alg *alg,
|
static inline void *crypto_create_tfm(struct crypto_alg *alg,
|
||||||
const struct crypto_type *frontend)
|
const struct crypto_type *frontend)
|
||||||
{
|
{
|
||||||
|
70
crypto/sig.c
70
crypto/sig.c
@ -5,12 +5,10 @@
|
|||||||
* Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
|
* Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <crypto/akcipher.h>
|
|
||||||
#include <crypto/internal/sig.h>
|
#include <crypto/internal/sig.h>
|
||||||
#include <linux/cryptouser.h>
|
#include <linux/cryptouser.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/scatterlist.h>
|
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <net/netlink.h>
|
#include <net/netlink.h>
|
||||||
@ -19,8 +17,6 @@
|
|||||||
|
|
||||||
#define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e
|
#define CRYPTO_ALG_TYPE_SIG_MASK 0x0000000e
|
||||||
|
|
||||||
static const struct crypto_type crypto_sig_type;
|
|
||||||
|
|
||||||
static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
|
static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
|
||||||
{
|
{
|
||||||
struct crypto_sig *sig = __crypto_sig_tfm(tfm);
|
struct crypto_sig *sig = __crypto_sig_tfm(tfm);
|
||||||
@ -31,9 +27,6 @@ static void crypto_sig_exit_tfm(struct crypto_tfm *tfm)
|
|||||||
|
|
||||||
static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
|
static int crypto_sig_init_tfm(struct crypto_tfm *tfm)
|
||||||
{
|
{
|
||||||
if (tfm->__crt_alg->cra_type != &crypto_sig_type)
|
|
||||||
return crypto_init_akcipher_ops_sig(tfm);
|
|
||||||
|
|
||||||
struct crypto_sig *sig = __crypto_sig_tfm(tfm);
|
struct crypto_sig *sig = __crypto_sig_tfm(tfm);
|
||||||
struct sig_alg *alg = crypto_sig_alg(sig);
|
struct sig_alg *alg = crypto_sig_alg(sig);
|
||||||
|
|
||||||
@ -93,17 +86,9 @@ EXPORT_SYMBOL_GPL(crypto_alloc_sig);
|
|||||||
|
|
||||||
int crypto_sig_maxsize(struct crypto_sig *tfm)
|
int crypto_sig_maxsize(struct crypto_sig *tfm)
|
||||||
{
|
{
|
||||||
if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
|
|
||||||
goto akcipher;
|
|
||||||
|
|
||||||
struct sig_alg *alg = crypto_sig_alg(tfm);
|
struct sig_alg *alg = crypto_sig_alg(tfm);
|
||||||
|
|
||||||
return alg->max_size(tfm);
|
return alg->max_size(tfm);
|
||||||
|
|
||||||
akcipher:
|
|
||||||
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
|
|
||||||
|
|
||||||
return crypto_akcipher_maxsize(*ctx);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
|
EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
|
||||||
|
|
||||||
@ -111,26 +96,9 @@ int crypto_sig_sign(struct crypto_sig *tfm,
|
|||||||
const void *src, unsigned int slen,
|
const void *src, unsigned int slen,
|
||||||
void *dst, unsigned int dlen)
|
void *dst, unsigned int dlen)
|
||||||
{
|
{
|
||||||
if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
|
|
||||||
goto akcipher;
|
|
||||||
|
|
||||||
struct sig_alg *alg = crypto_sig_alg(tfm);
|
struct sig_alg *alg = crypto_sig_alg(tfm);
|
||||||
|
|
||||||
return alg->sign(tfm, src, slen, dst, dlen);
|
return alg->sign(tfm, src, slen, dst, dlen);
|
||||||
|
|
||||||
akcipher:
|
|
||||||
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
|
|
||||||
struct crypto_akcipher_sync_data data = {
|
|
||||||
.tfm = *ctx,
|
|
||||||
.src = src,
|
|
||||||
.dst = dst,
|
|
||||||
.slen = slen,
|
|
||||||
.dlen = dlen,
|
|
||||||
};
|
|
||||||
|
|
||||||
return crypto_akcipher_sync_prep(&data) ?:
|
|
||||||
crypto_akcipher_sync_post(&data,
|
|
||||||
crypto_akcipher_sign(data.req));
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_sig_sign);
|
EXPORT_SYMBOL_GPL(crypto_sig_sign);
|
||||||
|
|
||||||
@ -138,65 +106,27 @@ int crypto_sig_verify(struct crypto_sig *tfm,
|
|||||||
const void *src, unsigned int slen,
|
const void *src, unsigned int slen,
|
||||||
const void *digest, unsigned int dlen)
|
const void *digest, unsigned int dlen)
|
||||||
{
|
{
|
||||||
if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
|
|
||||||
goto akcipher;
|
|
||||||
|
|
||||||
struct sig_alg *alg = crypto_sig_alg(tfm);
|
struct sig_alg *alg = crypto_sig_alg(tfm);
|
||||||
|
|
||||||
return alg->verify(tfm, src, slen, digest, dlen);
|
return alg->verify(tfm, src, slen, digest, dlen);
|
||||||
|
|
||||||
akcipher:
|
|
||||||
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
|
|
||||||
struct crypto_akcipher_sync_data data = {
|
|
||||||
.tfm = *ctx,
|
|
||||||
.src = src,
|
|
||||||
.slen = slen,
|
|
||||||
.dlen = dlen,
|
|
||||||
};
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err = crypto_akcipher_sync_prep(&data);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
memcpy(data.buf + slen, digest, dlen);
|
|
||||||
|
|
||||||
return crypto_akcipher_sync_post(&data,
|
|
||||||
crypto_akcipher_verify(data.req));
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_sig_verify);
|
EXPORT_SYMBOL_GPL(crypto_sig_verify);
|
||||||
|
|
||||||
int crypto_sig_set_pubkey(struct crypto_sig *tfm,
|
int crypto_sig_set_pubkey(struct crypto_sig *tfm,
|
||||||
const void *key, unsigned int keylen)
|
const void *key, unsigned int keylen)
|
||||||
{
|
{
|
||||||
if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
|
|
||||||
goto akcipher;
|
|
||||||
|
|
||||||
struct sig_alg *alg = crypto_sig_alg(tfm);
|
struct sig_alg *alg = crypto_sig_alg(tfm);
|
||||||
|
|
||||||
return alg->set_pub_key(tfm, key, keylen);
|
return alg->set_pub_key(tfm, key, keylen);
|
||||||
|
|
||||||
akcipher:
|
|
||||||
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
|
|
||||||
|
|
||||||
return crypto_akcipher_set_pub_key(*ctx, key, keylen);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
|
EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
|
||||||
|
|
||||||
int crypto_sig_set_privkey(struct crypto_sig *tfm,
|
int crypto_sig_set_privkey(struct crypto_sig *tfm,
|
||||||
const void *key, unsigned int keylen)
|
const void *key, unsigned int keylen)
|
||||||
{
|
{
|
||||||
if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type)
|
|
||||||
goto akcipher;
|
|
||||||
|
|
||||||
struct sig_alg *alg = crypto_sig_alg(tfm);
|
struct sig_alg *alg = crypto_sig_alg(tfm);
|
||||||
|
|
||||||
return alg->set_priv_key(tfm, key, keylen);
|
return alg->set_priv_key(tfm, key, keylen);
|
||||||
|
|
||||||
akcipher:
|
|
||||||
struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
|
|
||||||
|
|
||||||
return crypto_akcipher_set_priv_key(*ctx, key, keylen);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
|
EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
|
||||||
|
|
||||||
|
117
crypto/testmgr.c
117
crypto/testmgr.c
@ -4131,11 +4131,9 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
|
|||||||
struct crypto_wait wait;
|
struct crypto_wait wait;
|
||||||
unsigned int out_len_max, out_len = 0;
|
unsigned int out_len_max, out_len = 0;
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
struct scatterlist src, dst, src_tab[3];
|
struct scatterlist src, dst, src_tab[2];
|
||||||
const char *m, *c;
|
const char *c;
|
||||||
unsigned int m_size, c_size;
|
unsigned int c_size;
|
||||||
const char *op;
|
|
||||||
u8 *key, *ptr;
|
|
||||||
|
|
||||||
if (testmgr_alloc_buf(xbuf))
|
if (testmgr_alloc_buf(xbuf))
|
||||||
return err;
|
return err;
|
||||||
@ -4146,92 +4144,53 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
|
|||||||
|
|
||||||
crypto_init_wait(&wait);
|
crypto_init_wait(&wait);
|
||||||
|
|
||||||
key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len,
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!key)
|
|
||||||
goto free_req;
|
|
||||||
memcpy(key, vecs->key, vecs->key_len);
|
|
||||||
ptr = key + vecs->key_len;
|
|
||||||
ptr = test_pack_u32(ptr, vecs->algo);
|
|
||||||
ptr = test_pack_u32(ptr, vecs->param_len);
|
|
||||||
memcpy(ptr, vecs->params, vecs->param_len);
|
|
||||||
|
|
||||||
if (vecs->public_key_vec)
|
if (vecs->public_key_vec)
|
||||||
err = crypto_akcipher_set_pub_key(tfm, key, vecs->key_len);
|
err = crypto_akcipher_set_pub_key(tfm, vecs->key,
|
||||||
|
vecs->key_len);
|
||||||
else
|
else
|
||||||
err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len);
|
err = crypto_akcipher_set_priv_key(tfm, vecs->key,
|
||||||
|
vecs->key_len);
|
||||||
if (err)
|
if (err)
|
||||||
goto free_key;
|
goto free_req;
|
||||||
|
|
||||||
/*
|
/* First run encrypt test which does not require a private key */
|
||||||
* First run test which do not require a private key, such as
|
|
||||||
* encrypt or verify.
|
|
||||||
*/
|
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
out_len_max = crypto_akcipher_maxsize(tfm);
|
out_len_max = crypto_akcipher_maxsize(tfm);
|
||||||
outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
|
outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
|
||||||
if (!outbuf_enc)
|
if (!outbuf_enc)
|
||||||
goto free_key;
|
goto free_req;
|
||||||
|
|
||||||
if (!vecs->siggen_sigver_test) {
|
c = vecs->c;
|
||||||
m = vecs->m;
|
c_size = vecs->c_size;
|
||||||
m_size = vecs->m_size;
|
|
||||||
c = vecs->c;
|
|
||||||
c_size = vecs->c_size;
|
|
||||||
op = "encrypt";
|
|
||||||
} else {
|
|
||||||
/* Swap args so we could keep plaintext (digest)
|
|
||||||
* in vecs->m, and cooked signature in vecs->c.
|
|
||||||
*/
|
|
||||||
m = vecs->c; /* signature */
|
|
||||||
m_size = vecs->c_size;
|
|
||||||
c = vecs->m; /* digest */
|
|
||||||
c_size = vecs->m_size;
|
|
||||||
op = "verify";
|
|
||||||
}
|
|
||||||
|
|
||||||
err = -E2BIG;
|
err = -E2BIG;
|
||||||
if (WARN_ON(m_size > PAGE_SIZE))
|
if (WARN_ON(vecs->m_size > PAGE_SIZE))
|
||||||
goto free_all;
|
goto free_all;
|
||||||
memcpy(xbuf[0], m, m_size);
|
memcpy(xbuf[0], vecs->m, vecs->m_size);
|
||||||
|
|
||||||
sg_init_table(src_tab, 3);
|
sg_init_table(src_tab, 2);
|
||||||
sg_set_buf(&src_tab[0], xbuf[0], 8);
|
sg_set_buf(&src_tab[0], xbuf[0], 8);
|
||||||
sg_set_buf(&src_tab[1], xbuf[0] + 8, m_size - 8);
|
sg_set_buf(&src_tab[1], xbuf[0] + 8, vecs->m_size - 8);
|
||||||
if (vecs->siggen_sigver_test) {
|
sg_init_one(&dst, outbuf_enc, out_len_max);
|
||||||
if (WARN_ON(c_size > PAGE_SIZE))
|
akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
|
||||||
goto free_all;
|
out_len_max);
|
||||||
memcpy(xbuf[1], c, c_size);
|
|
||||||
sg_set_buf(&src_tab[2], xbuf[1], c_size);
|
|
||||||
akcipher_request_set_crypt(req, src_tab, NULL, m_size, c_size);
|
|
||||||
} else {
|
|
||||||
sg_init_one(&dst, outbuf_enc, out_len_max);
|
|
||||||
akcipher_request_set_crypt(req, src_tab, &dst, m_size,
|
|
||||||
out_len_max);
|
|
||||||
}
|
|
||||||
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
|
||||||
crypto_req_done, &wait);
|
crypto_req_done, &wait);
|
||||||
|
|
||||||
err = crypto_wait_req(vecs->siggen_sigver_test ?
|
err = crypto_wait_req(crypto_akcipher_encrypt(req), &wait);
|
||||||
/* Run asymmetric signature verification */
|
|
||||||
crypto_akcipher_verify(req) :
|
|
||||||
/* Run asymmetric encrypt */
|
|
||||||
crypto_akcipher_encrypt(req), &wait);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
|
pr_err("alg: akcipher: encrypt test failed. err %d\n", err);
|
||||||
goto free_all;
|
goto free_all;
|
||||||
}
|
}
|
||||||
if (!vecs->siggen_sigver_test && c) {
|
if (c) {
|
||||||
if (req->dst_len != c_size) {
|
if (req->dst_len != c_size) {
|
||||||
pr_err("alg: akcipher: %s test failed. Invalid output len\n",
|
pr_err("alg: akcipher: encrypt test failed. Invalid output len\n");
|
||||||
op);
|
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto free_all;
|
goto free_all;
|
||||||
}
|
}
|
||||||
/* verify that encrypted message is equal to expected */
|
/* verify that encrypted message is equal to expected */
|
||||||
if (memcmp(c, outbuf_enc, c_size) != 0) {
|
if (memcmp(c, outbuf_enc, c_size) != 0) {
|
||||||
pr_err("alg: akcipher: %s test failed. Invalid output\n",
|
pr_err("alg: akcipher: encrypt test failed. Invalid output\n");
|
||||||
op);
|
|
||||||
hexdump(outbuf_enc, c_size);
|
hexdump(outbuf_enc, c_size);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto free_all;
|
goto free_all;
|
||||||
@ -4239,7 +4198,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't invoke (decrypt or sign) test which require a private key
|
* Don't invoke decrypt test which requires a private key
|
||||||
* for vectors with only a public key.
|
* for vectors with only a public key.
|
||||||
*/
|
*/
|
||||||
if (vecs->public_key_vec) {
|
if (vecs->public_key_vec) {
|
||||||
@ -4252,13 +4211,12 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
|
|||||||
goto free_all;
|
goto free_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!vecs->siggen_sigver_test && !c) {
|
if (!c) {
|
||||||
c = outbuf_enc;
|
c = outbuf_enc;
|
||||||
c_size = req->dst_len;
|
c_size = req->dst_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = -E2BIG;
|
err = -E2BIG;
|
||||||
op = vecs->siggen_sigver_test ? "sign" : "decrypt";
|
|
||||||
if (WARN_ON(c_size > PAGE_SIZE))
|
if (WARN_ON(c_size > PAGE_SIZE))
|
||||||
goto free_all;
|
goto free_all;
|
||||||
memcpy(xbuf[0], c, c_size);
|
memcpy(xbuf[0], c, c_size);
|
||||||
@ -4268,34 +4226,29 @@ static int test_akcipher_one(struct crypto_akcipher *tfm,
|
|||||||
crypto_init_wait(&wait);
|
crypto_init_wait(&wait);
|
||||||
akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
|
akcipher_request_set_crypt(req, &src, &dst, c_size, out_len_max);
|
||||||
|
|
||||||
err = crypto_wait_req(vecs->siggen_sigver_test ?
|
err = crypto_wait_req(crypto_akcipher_decrypt(req), &wait);
|
||||||
/* Run asymmetric signature generation */
|
|
||||||
crypto_akcipher_sign(req) :
|
|
||||||
/* Run asymmetric decrypt */
|
|
||||||
crypto_akcipher_decrypt(req), &wait);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("alg: akcipher: %s test failed. err %d\n", op, err);
|
pr_err("alg: akcipher: decrypt test failed. err %d\n", err);
|
||||||
goto free_all;
|
goto free_all;
|
||||||
}
|
}
|
||||||
out_len = req->dst_len;
|
out_len = req->dst_len;
|
||||||
if (out_len < m_size) {
|
if (out_len < vecs->m_size) {
|
||||||
pr_err("alg: akcipher: %s test failed. Invalid output len %u\n",
|
pr_err("alg: akcipher: decrypt test failed. Invalid output len %u\n",
|
||||||
op, out_len);
|
out_len);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto free_all;
|
goto free_all;
|
||||||
}
|
}
|
||||||
/* verify that decrypted message is equal to the original msg */
|
/* verify that decrypted message is equal to the original msg */
|
||||||
if (memchr_inv(outbuf_dec, 0, out_len - m_size) ||
|
if (memchr_inv(outbuf_dec, 0, out_len - vecs->m_size) ||
|
||||||
memcmp(m, outbuf_dec + out_len - m_size, m_size)) {
|
memcmp(vecs->m, outbuf_dec + out_len - vecs->m_size,
|
||||||
pr_err("alg: akcipher: %s test failed. Invalid output\n", op);
|
vecs->m_size)) {
|
||||||
|
pr_err("alg: akcipher: decrypt test failed. Invalid output\n");
|
||||||
hexdump(outbuf_dec, out_len);
|
hexdump(outbuf_dec, out_len);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
}
|
}
|
||||||
free_all:
|
free_all:
|
||||||
kfree(outbuf_dec);
|
kfree(outbuf_dec);
|
||||||
kfree(outbuf_enc);
|
kfree(outbuf_enc);
|
||||||
free_key:
|
|
||||||
kfree(key);
|
|
||||||
free_req:
|
free_req:
|
||||||
akcipher_request_free(req);
|
akcipher_request_free(req);
|
||||||
free_xbuf:
|
free_xbuf:
|
||||||
|
@ -150,16 +150,12 @@ struct drbg_testvec {
|
|||||||
|
|
||||||
struct akcipher_testvec {
|
struct akcipher_testvec {
|
||||||
const unsigned char *key;
|
const unsigned char *key;
|
||||||
const unsigned char *params;
|
|
||||||
const unsigned char *m;
|
const unsigned char *m;
|
||||||
const unsigned char *c;
|
const unsigned char *c;
|
||||||
unsigned int key_len;
|
unsigned int key_len;
|
||||||
unsigned int param_len;
|
|
||||||
unsigned int m_size;
|
unsigned int m_size;
|
||||||
unsigned int c_size;
|
unsigned int c_size;
|
||||||
bool public_key_vec;
|
bool public_key_vec;
|
||||||
bool siggen_sigver_test;
|
|
||||||
enum OID algo;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sig_testvec {
|
struct sig_testvec {
|
||||||
|
@ -12,24 +12,19 @@
|
|||||||
#include <linux/crypto.h>
|
#include <linux/crypto.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct akcipher_request - public key request
|
* struct akcipher_request - public key cipher request
|
||||||
*
|
*
|
||||||
* @base: Common attributes for async crypto requests
|
* @base: Common attributes for async crypto requests
|
||||||
* @src: Source data
|
* @src: Source data
|
||||||
* For verify op this is signature + digest, in that case
|
* @dst: Destination data
|
||||||
* total size of @src is @src_len + @dst_len.
|
|
||||||
* @dst: Destination data (Should be NULL for verify op)
|
|
||||||
* @src_len: Size of the input buffer
|
* @src_len: Size of the input buffer
|
||||||
* For verify op it's size of signature part of @src, this part
|
* @dst_len: Size of @dst buffer
|
||||||
* is supposed to be operated by cipher.
|
|
||||||
* @dst_len: Size of @dst buffer (for all ops except verify).
|
|
||||||
* It needs to be at least as big as the expected result
|
* It needs to be at least as big as the expected result
|
||||||
* depending on the operation.
|
* depending on the operation.
|
||||||
* After operation it will be updated with the actual size of the
|
* After operation it will be updated with the actual size of the
|
||||||
* result.
|
* result.
|
||||||
* In case of error where the dst sgl size was insufficient,
|
* In case of error where the dst sgl size was insufficient,
|
||||||
* it will be updated to the size required for the operation.
|
* it will be updated to the size required for the operation.
|
||||||
* For verify op this is size of digest part in @src.
|
|
||||||
* @__ctx: Start of private context data
|
* @__ctx: Start of private context data
|
||||||
*/
|
*/
|
||||||
struct akcipher_request {
|
struct akcipher_request {
|
||||||
@ -55,15 +50,8 @@ struct crypto_akcipher {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct akcipher_alg - generic public key algorithm
|
* struct akcipher_alg - generic public key cipher algorithm
|
||||||
*
|
*
|
||||||
* @sign: Function performs a sign operation as defined by public key
|
|
||||||
* algorithm. In case of error, where the dst_len was insufficient,
|
|
||||||
* the req->dst_len will be updated to the size required for the
|
|
||||||
* operation
|
|
||||||
* @verify: Function performs a complete verify operation as defined by
|
|
||||||
* public key algorithm, returning verification status. Requires
|
|
||||||
* digest value as input parameter.
|
|
||||||
* @encrypt: Function performs an encrypt operation as defined by public key
|
* @encrypt: Function performs an encrypt operation as defined by public key
|
||||||
* algorithm. In case of error, where the dst_len was insufficient,
|
* algorithm. In case of error, where the dst_len was insufficient,
|
||||||
* the req->dst_len will be updated to the size required for the
|
* the req->dst_len will be updated to the size required for the
|
||||||
@ -94,8 +82,6 @@ struct crypto_akcipher {
|
|||||||
* @base: Common crypto API algorithm data structure
|
* @base: Common crypto API algorithm data structure
|
||||||
*/
|
*/
|
||||||
struct akcipher_alg {
|
struct akcipher_alg {
|
||||||
int (*sign)(struct akcipher_request *req);
|
|
||||||
int (*verify)(struct akcipher_request *req);
|
|
||||||
int (*encrypt)(struct akcipher_request *req);
|
int (*encrypt)(struct akcipher_request *req);
|
||||||
int (*decrypt)(struct akcipher_request *req);
|
int (*decrypt)(struct akcipher_request *req);
|
||||||
int (*set_pub_key)(struct crypto_akcipher *tfm, const void *key,
|
int (*set_pub_key)(struct crypto_akcipher *tfm, const void *key,
|
||||||
@ -110,9 +96,9 @@ struct akcipher_alg {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DOC: Generic Public Key API
|
* DOC: Generic Public Key Cipher API
|
||||||
*
|
*
|
||||||
* The Public Key API is used with the algorithms of type
|
* The Public Key Cipher API is used with the algorithms of type
|
||||||
* CRYPTO_ALG_TYPE_AKCIPHER (listed as type "akcipher" in /proc/crypto)
|
* CRYPTO_ALG_TYPE_AKCIPHER (listed as type "akcipher" in /proc/crypto)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -243,10 +229,9 @@ static inline void akcipher_request_set_callback(struct akcipher_request *req,
|
|||||||
*
|
*
|
||||||
* @req: public key request
|
* @req: public key request
|
||||||
* @src: ptr to input scatter list
|
* @src: ptr to input scatter list
|
||||||
* @dst: ptr to output scatter list or NULL for verify op
|
* @dst: ptr to output scatter list
|
||||||
* @src_len: size of the src input scatter list to be processed
|
* @src_len: size of the src input scatter list to be processed
|
||||||
* @dst_len: size of the dst output scatter list or size of signature
|
* @dst_len: size of the dst output scatter list
|
||||||
* portion in @src for verify op
|
|
||||||
*/
|
*/
|
||||||
static inline void akcipher_request_set_crypt(struct akcipher_request *req,
|
static inline void akcipher_request_set_crypt(struct akcipher_request *req,
|
||||||
struct scatterlist *src,
|
struct scatterlist *src,
|
||||||
@ -347,44 +332,6 @@ int crypto_akcipher_sync_decrypt(struct crypto_akcipher *tfm,
|
|||||||
const void *src, unsigned int slen,
|
const void *src, unsigned int slen,
|
||||||
void *dst, unsigned int dlen);
|
void *dst, unsigned int dlen);
|
||||||
|
|
||||||
/**
|
|
||||||
* crypto_akcipher_sign() - Invoke public key sign operation
|
|
||||||
*
|
|
||||||
* Function invokes the specific public key sign operation for a given
|
|
||||||
* public key algorithm
|
|
||||||
*
|
|
||||||
* @req: asymmetric key request
|
|
||||||
*
|
|
||||||
* Return: zero on success; error code in case of error
|
|
||||||
*/
|
|
||||||
static inline int crypto_akcipher_sign(struct akcipher_request *req)
|
|
||||||
{
|
|
||||||
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
|
|
||||||
|
|
||||||
return crypto_akcipher_alg(tfm)->sign(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* crypto_akcipher_verify() - Invoke public key signature verification
|
|
||||||
*
|
|
||||||
* Function invokes the specific public key signature verification operation
|
|
||||||
* for a given public key algorithm.
|
|
||||||
*
|
|
||||||
* @req: asymmetric key request
|
|
||||||
*
|
|
||||||
* Note: req->dst should be NULL, req->src should point to SG of size
|
|
||||||
* (req->src_size + req->dst_size), containing signature (of req->src_size
|
|
||||||
* length) with appended digest (of req->dst_size length).
|
|
||||||
*
|
|
||||||
* Return: zero on verification success; error code in case of error.
|
|
||||||
*/
|
|
||||||
static inline int crypto_akcipher_verify(struct akcipher_request *req)
|
|
||||||
{
|
|
||||||
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
|
|
||||||
|
|
||||||
return crypto_akcipher_alg(tfm)->verify(req);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* crypto_akcipher_set_pub_key() - Invoke set public key operation
|
* crypto_akcipher_set_pub_key() - Invoke set public key operation
|
||||||
*
|
*
|
||||||
|
@ -124,7 +124,7 @@ static inline struct akcipher_alg *crypto_spawn_akcipher_alg(
|
|||||||
/**
|
/**
|
||||||
* crypto_register_akcipher() -- Register public key algorithm
|
* crypto_register_akcipher() -- Register public key algorithm
|
||||||
*
|
*
|
||||||
* Function registers an implementation of a public key verify algorithm
|
* Function registers an implementation of a public key cipher algorithm
|
||||||
*
|
*
|
||||||
* @alg: algorithm definition
|
* @alg: algorithm definition
|
||||||
*
|
*
|
||||||
@ -135,7 +135,7 @@ int crypto_register_akcipher(struct akcipher_alg *alg);
|
|||||||
/**
|
/**
|
||||||
* crypto_unregister_akcipher() -- Unregister public key algorithm
|
* crypto_unregister_akcipher() -- Unregister public key algorithm
|
||||||
*
|
*
|
||||||
* Function unregisters an implementation of a public key verify algorithm
|
* Function unregisters an implementation of a public key cipher algorithm
|
||||||
*
|
*
|
||||||
* @alg: algorithm definition
|
* @alg: algorithm definition
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user