mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	crypto: sig - Add interface for sign/verify
Split out the sign/verify functionality from the existing akcipher interface. Most algorithms in akcipher either support encryption and decryption, or signing and verify. Only one supports both. As a signature algorithm may not support encryption at all, these two should be spearated. For now sig is simply a wrapper around akcipher as all algorithms remain unchanged. This is a first step and allows users to start allocating sig instead of akcipher. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
		
							parent
							
								
									addde1f2c9
								
							
						
					
					
						commit
						6cb8815f41
					
				
					 8 changed files with 385 additions and 18 deletions
				
			
		| 
						 | 
					@ -72,6 +72,15 @@ config CRYPTO_AEAD2
 | 
				
			||||||
	tristate
 | 
						tristate
 | 
				
			||||||
	select CRYPTO_ALGAPI2
 | 
						select CRYPTO_ALGAPI2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config CRYPTO_SIG
 | 
				
			||||||
 | 
						tristate
 | 
				
			||||||
 | 
						select CRYPTO_SIG2
 | 
				
			||||||
 | 
						select CRYPTO_ALGAPI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					config CRYPTO_SIG2
 | 
				
			||||||
 | 
						tristate
 | 
				
			||||||
 | 
						select CRYPTO_ALGAPI2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
config CRYPTO_SKCIPHER
 | 
					config CRYPTO_SKCIPHER
 | 
				
			||||||
	tristate
 | 
						tristate
 | 
				
			||||||
	select CRYPTO_SKCIPHER2
 | 
						select CRYPTO_SKCIPHER2
 | 
				
			||||||
| 
						 | 
					@ -143,6 +152,7 @@ config CRYPTO_MANAGER2
 | 
				
			||||||
	select CRYPTO_ACOMP2
 | 
						select CRYPTO_ACOMP2
 | 
				
			||||||
	select CRYPTO_AEAD2
 | 
						select CRYPTO_AEAD2
 | 
				
			||||||
	select CRYPTO_AKCIPHER2
 | 
						select CRYPTO_AKCIPHER2
 | 
				
			||||||
 | 
						select CRYPTO_SIG2
 | 
				
			||||||
	select CRYPTO_HASH2
 | 
						select CRYPTO_HASH2
 | 
				
			||||||
	select CRYPTO_KPP2
 | 
						select CRYPTO_KPP2
 | 
				
			||||||
	select CRYPTO_RNG2
 | 
						select CRYPTO_RNG2
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ crypto_hash-y += shash.o
 | 
				
			||||||
obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 | 
					obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 | 
					obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o
 | 
				
			||||||
 | 
					obj-$(CONFIG_CRYPTO_SIG2) += sig.o
 | 
				
			||||||
obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
 | 
					obj-$(CONFIG_CRYPTO_KPP2) += kpp.o
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dh_generic-y := dh.o
 | 
					dh_generic-y := dh.o
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,18 +18,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "internal.h"
 | 
					#include "internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct crypto_akcipher_sync_data {
 | 
					#define CRYPTO_ALG_TYPE_AHASH_MASK	0x0000000e
 | 
				
			||||||
	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)
 | 
				
			||||||
| 
						 | 
					@ -119,7 +108,7 @@ static const struct crypto_type crypto_akcipher_type = {
 | 
				
			||||||
	.report_stat = crypto_akcipher_report_stat,
 | 
						.report_stat = crypto_akcipher_report_stat,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 | 
						.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 | 
				
			||||||
	.maskset = CRYPTO_ALG_TYPE_MASK,
 | 
						.maskset = CRYPTO_ALG_TYPE_AHASH_MASK,
 | 
				
			||||||
	.type = CRYPTO_ALG_TYPE_AKCIPHER,
 | 
						.type = CRYPTO_ALG_TYPE_AKCIPHER,
 | 
				
			||||||
	.tfmsize = offsetof(struct crypto_akcipher, base),
 | 
						.tfmsize = offsetof(struct crypto_akcipher, base),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -200,7 +189,7 @@ int akcipher_register_instance(struct crypto_template *tmpl,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(akcipher_register_instance);
 | 
					EXPORT_SYMBOL_GPL(akcipher_register_instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 | 
					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);
 | 
				
			||||||
	unsigned int mlen = max(data->slen, data->dlen);
 | 
						unsigned int mlen = max(data->slen, data->dlen);
 | 
				
			||||||
| 
						 | 
					@ -223,7 +212,7 @@ static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 | 
				
			||||||
	data->buf = buf;
 | 
						data->buf = buf;
 | 
				
			||||||
	memcpy(buf, data->src, data->slen);
 | 
						memcpy(buf, data->src, data->slen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sg = &data->sg;
 | 
						sg = data->sg;
 | 
				
			||||||
	sg_init_one(sg, buf, mlen);
 | 
						sg_init_one(sg, buf, mlen);
 | 
				
			||||||
	akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
 | 
						akcipher_request_set_crypt(req, sg, sg, data->slen, data->dlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -233,9 +222,9 @@ static int crypto_akcipher_sync_prep(struct crypto_akcipher_sync_data *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(crypto_akcipher_sync_prep);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
 | 
					int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data, int err)
 | 
				
			||||||
				     int err)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	err = crypto_wait_req(err, &data->cwait);
 | 
						err = crypto_wait_req(err, &data->cwait);
 | 
				
			||||||
	memcpy(data->dst, data->buf, data->dlen);
 | 
						memcpy(data->dst, data->buf, data->dlen);
 | 
				
			||||||
| 
						 | 
					@ -243,6 +232,7 @@ static int crypto_akcipher_sync_post(struct crypto_akcipher_sync_data *data,
 | 
				
			||||||
	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,
 | 
				
			||||||
| 
						 | 
					@ -281,5 +271,34 @@ 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");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,9 +18,12 @@
 | 
				
			||||||
#include <linux/numa.h>
 | 
					#include <linux/numa.h>
 | 
				
			||||||
#include <linux/refcount.h>
 | 
					#include <linux/refcount.h>
 | 
				
			||||||
#include <linux/rwsem.h>
 | 
					#include <linux/rwsem.h>
 | 
				
			||||||
 | 
					#include <linux/scatterlist.h>
 | 
				
			||||||
#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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,6 +35,19 @@ 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[2];
 | 
				
			||||||
 | 
						u8 *buf;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	CRYPTOA_UNSPEC,
 | 
						CRYPTOA_UNSPEC,
 | 
				
			||||||
	CRYPTOA_ALG,
 | 
						CRYPTOA_ALG,
 | 
				
			||||||
| 
						 | 
					@ -111,6 +127,10 @@ 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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										159
									
								
								crypto/sig.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								crypto/sig.c
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,159 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Public Key Signature Algorithm
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <crypto/akcipher.h>
 | 
				
			||||||
 | 
					#include <crypto/internal/sig.h>
 | 
				
			||||||
 | 
					#include <linux/cryptouser.h>
 | 
				
			||||||
 | 
					#include <linux/kernel.h>
 | 
				
			||||||
 | 
					#include <linux/module.h>
 | 
				
			||||||
 | 
					#include <linux/scatterlist.h>
 | 
				
			||||||
 | 
					#include <linux/seq_file.h>
 | 
				
			||||||
 | 
					#include <linux/string.h>
 | 
				
			||||||
 | 
					#include <net/netlink.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "internal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CRYPTO_ALG_TYPE_SIG_MASK	0x0000000e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct crypto_type crypto_sig_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return container_of(tfm, struct crypto_sig, base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void __maybe_unused crypto_sig_show(struct seq_file *m,
 | 
				
			||||||
 | 
										   struct crypto_alg *alg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						seq_puts(m, "type         : sig\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __maybe_unused crypto_sig_report(struct sk_buff *skb,
 | 
				
			||||||
 | 
										    struct crypto_alg *alg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_report_akcipher rsig = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strscpy(rsig.type, "sig", sizeof(rsig.type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int __maybe_unused crypto_sig_report_stat(struct sk_buff *skb,
 | 
				
			||||||
 | 
											 struct crypto_alg *alg)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_stat_akcipher rsig = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						strscpy(rsig.type, "sig", sizeof(rsig.type));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nla_put(skb, CRYPTOCFGA_STAT_AKCIPHER, sizeof(rsig), &rsig);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct crypto_type crypto_sig_type = {
 | 
				
			||||||
 | 
						.extsize = crypto_alg_extsize,
 | 
				
			||||||
 | 
						.init_tfm = crypto_sig_init_tfm,
 | 
				
			||||||
 | 
					#ifdef CONFIG_PROC_FS
 | 
				
			||||||
 | 
						.show = crypto_sig_show,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#if IS_ENABLED(CONFIG_CRYPTO_USER)
 | 
				
			||||||
 | 
						.report = crypto_sig_report,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef CONFIG_CRYPTO_STATS
 | 
				
			||||||
 | 
						.report_stat = crypto_sig_report_stat,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						.maskclear = ~CRYPTO_ALG_TYPE_MASK,
 | 
				
			||||||
 | 
						.maskset = CRYPTO_ALG_TYPE_SIG_MASK,
 | 
				
			||||||
 | 
						.type = CRYPTO_ALG_TYPE_SIG,
 | 
				
			||||||
 | 
						.tfmsize = offsetof(struct crypto_sig, base),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return crypto_alloc_tfm(alg_name, &crypto_sig_type, type, mask);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(crypto_alloc_sig);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int crypto_sig_maxsize(struct crypto_sig *tfm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return crypto_akcipher_maxsize(*ctx);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(crypto_sig_maxsize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int crypto_sig_sign(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
							    const void *src, unsigned int slen,
 | 
				
			||||||
 | 
							    void *dst, unsigned int dlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int crypto_sig_verify(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
							      const void *src, unsigned int slen,
 | 
				
			||||||
 | 
							      const void *digest, unsigned int dlen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sg_init_table(data.sg, 2);
 | 
				
			||||||
 | 
						sg_set_buf(&data.sg[0], src, slen);
 | 
				
			||||||
 | 
						sg_set_buf(&data.sg[1], digest, dlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return crypto_akcipher_sync_post(&data,
 | 
				
			||||||
 | 
										 crypto_akcipher_verify(data.req));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(crypto_sig_verify);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int crypto_sig_set_pubkey(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
								  const void *key, unsigned int keylen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return crypto_akcipher_set_pub_key(*ctx, key, keylen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(crypto_sig_set_pubkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int crypto_sig_set_privkey(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
								  const void *key, unsigned int keylen)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct crypto_akcipher **ctx = crypto_sig_ctx(tfm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return crypto_akcipher_set_priv_key(*ctx, key, keylen);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					EXPORT_SYMBOL_GPL(crypto_sig_set_privkey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MODULE_LICENSE("GPL");
 | 
				
			||||||
 | 
					MODULE_DESCRIPTION("Public Key Signature Algorithms");
 | 
				
			||||||
							
								
								
									
										17
									
								
								include/crypto/internal/sig.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								include/crypto/internal/sig.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Public Key Signature Algorithm
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _CRYPTO_INTERNAL_SIG_H
 | 
				
			||||||
 | 
					#define _CRYPTO_INTERNAL_SIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <crypto/algapi.h>
 | 
				
			||||||
 | 
					#include <crypto/sig.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void *crypto_sig_ctx(struct crypto_sig *tfm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return crypto_tfm_ctx(&tfm->base);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										140
									
								
								include/crypto/sig.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								include/crypto/sig.h
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,140 @@
 | 
				
			||||||
 | 
					/* SPDX-License-Identifier: GPL-2.0-or-later */
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Public Key Signature Algorithm
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (c) 2023 Herbert Xu <herbert@gondor.apana.org.au>
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#ifndef _CRYPTO_SIG_H
 | 
				
			||||||
 | 
					#define _CRYPTO_SIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <linux/crypto.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * struct crypto_sig - user-instantiated objects which encapsulate
 | 
				
			||||||
 | 
					 * algorithms and core processing logic
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @base:	Common crypto API algorithm data structure
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct crypto_sig {
 | 
				
			||||||
 | 
						struct crypto_tfm base;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * DOC: Generic Public Key Signature API
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * The Public Key Signature API is used with the algorithms of type
 | 
				
			||||||
 | 
					 * CRYPTO_ALG_TYPE_SIG (listed as type "sig" in /proc/crypto)
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_alloc_sig() - allocate signature tfm handle
 | 
				
			||||||
 | 
					 * @alg_name: is the cra_name / name or cra_driver_name / driver name of the
 | 
				
			||||||
 | 
					 *	      signing algorithm e.g. "ecdsa"
 | 
				
			||||||
 | 
					 * @type: specifies the type of the algorithm
 | 
				
			||||||
 | 
					 * @mask: specifies the mask for the algorithm
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Allocate a handle for public key signature algorithm. The returned struct
 | 
				
			||||||
 | 
					 * crypto_sig is the handle that is required for any subsequent
 | 
				
			||||||
 | 
					 * API invocation for signature operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: allocated handle in case of success; IS_ERR() is true in case
 | 
				
			||||||
 | 
					 *	   of an error, PTR_ERR() returns the error code.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct crypto_sig *crypto_alloc_sig(const char *alg_name, u32 type, u32 mask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct crypto_tfm *crypto_sig_tfm(struct crypto_sig *tfm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return &tfm->base;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_free_sig() - free signature tfm handle
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tfm: signature tfm handle allocated with crypto_alloc_sig()
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * If @tfm is a NULL or error pointer, this function does nothing.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					static inline void crypto_free_sig(struct crypto_sig *tfm)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						crypto_destroy_tfm(tfm, crypto_sig_tfm(tfm));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_sig_maxsize() - Get len for output buffer
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Function returns the dest buffer size required for a given key.
 | 
				
			||||||
 | 
					 * Function assumes that the key is already set in the transformation. If this
 | 
				
			||||||
 | 
					 * function is called without a setkey or with a failed setkey, you will end up
 | 
				
			||||||
 | 
					 * in a NULL dereference.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int crypto_sig_maxsize(struct crypto_sig *tfm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_sig_sign() - Invoke signing operation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Function invokes the specific signing operation for a given algorithm
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
 | 
				
			||||||
 | 
					 * @src:	source buffer
 | 
				
			||||||
 | 
					 * @slen:	source length
 | 
				
			||||||
 | 
					 * @dst:	destinatino obuffer
 | 
				
			||||||
 | 
					 * @dlen:	destination length
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: zero on success; error code in case of error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int crypto_sig_sign(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
							    const void *src, unsigned int slen,
 | 
				
			||||||
 | 
							    void *dst, unsigned int dlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_sig_verify() - Invoke signature verification
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Function invokes the specific signature verification operation
 | 
				
			||||||
 | 
					 * for a given algorithm.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tfm:	signature tfm handle allocated with crypto_alloc_sig()
 | 
				
			||||||
 | 
					 * @src:	source buffer
 | 
				
			||||||
 | 
					 * @slen:	source length
 | 
				
			||||||
 | 
					 * @digest:	digest
 | 
				
			||||||
 | 
					 * @dlen:	digest length
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: zero on verification success; error code in case of error.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int crypto_sig_verify(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
							      const void *src, unsigned int slen,
 | 
				
			||||||
 | 
							      const void *digest, unsigned int dlen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_sig_set_pubkey() - Invoke set public key operation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Function invokes the algorithm specific set key function, which knows
 | 
				
			||||||
 | 
					 * how to decode and interpret the encoded key and parameters
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tfm:	tfm handle
 | 
				
			||||||
 | 
					 * @key:	BER encoded public key, algo OID, paramlen, BER encoded
 | 
				
			||||||
 | 
					 *		parameters
 | 
				
			||||||
 | 
					 * @keylen:	length of the key (not including other data)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: zero on success; error code in case of error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int crypto_sig_set_pubkey(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
								  const void *key, unsigned int keylen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * crypto_sig_set_privkey() - Invoke set private key operation
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Function invokes the algorithm specific set key function, which knows
 | 
				
			||||||
 | 
					 * how to decode and interpret the encoded key and parameters
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @tfm:	tfm handle
 | 
				
			||||||
 | 
					 * @key:	BER encoded private key, algo OID, paramlen, BER encoded
 | 
				
			||||||
 | 
					 *		parameters
 | 
				
			||||||
 | 
					 * @keylen:	length of the key (not including other data)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Return: zero on success; error code in case of error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int crypto_sig_set_privkey(struct crypto_sig *tfm,
 | 
				
			||||||
 | 
								   const void *key, unsigned int keylen);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					@ -25,11 +25,12 @@
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_COMPRESS	0x00000002
 | 
					#define CRYPTO_ALG_TYPE_COMPRESS	0x00000002
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_AEAD		0x00000003
 | 
					#define CRYPTO_ALG_TYPE_AEAD		0x00000003
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_SKCIPHER	0x00000005
 | 
					#define CRYPTO_ALG_TYPE_SKCIPHER	0x00000005
 | 
				
			||||||
 | 
					#define CRYPTO_ALG_TYPE_AKCIPHER	0x00000006
 | 
				
			||||||
 | 
					#define CRYPTO_ALG_TYPE_SIG		0x00000007
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_KPP		0x00000008
 | 
					#define CRYPTO_ALG_TYPE_KPP		0x00000008
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_ACOMPRESS	0x0000000a
 | 
					#define CRYPTO_ALG_TYPE_ACOMPRESS	0x0000000a
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_SCOMPRESS	0x0000000b
 | 
					#define CRYPTO_ALG_TYPE_SCOMPRESS	0x0000000b
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_RNG		0x0000000c
 | 
					#define CRYPTO_ALG_TYPE_RNG		0x0000000c
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_AKCIPHER	0x0000000d
 | 
					 | 
				
			||||||
#define CRYPTO_ALG_TYPE_HASH		0x0000000e
 | 
					#define CRYPTO_ALG_TYPE_HASH		0x0000000e
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_SHASH		0x0000000e
 | 
					#define CRYPTO_ALG_TYPE_SHASH		0x0000000e
 | 
				
			||||||
#define CRYPTO_ALG_TYPE_AHASH		0x0000000f
 | 
					#define CRYPTO_ALG_TYPE_AHASH		0x0000000f
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue