From: Shasi Pulijala <[EMAIL PROTECTED]>
Hi Herbert,
This patch adds PKA support to Linux CryptoAPI. All the basic algorithms like
add, sub, div, expmod and expmod-crt can be supported by this interface.
Currently the max number of src and dst operands have been defined as 6 and 2
respectively. These values should fit all the above mentioned algorithms (for
example add needs 2 for input and 1 for output, expmod-crt 6 for input and 1
for output). Although, there is no specific mapping of operands, it is assumed
that for add, operand A would be the first entry, operand B would be the second
entry of the source. The output would be the first output.
Signed-off-by: Shasi Pulijala <[EMAIL PROTECTED]>
Acked-by: Loc Ho <[EMAIL PROTECTED]>
---
crypto/Kconfig | 4 +
crypto/Makefile | 1 +
crypto/pka.c | 107 +++++++++++++++++++++++++++++++++
include/crypto/algapi.h | 17 +++++
include/linux/crypto.h | 153 ++++++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 279 insertions(+), 3 deletions(-)
create mode 100644 crypto/pka.c
diff --git a/crypto/Kconfig b/crypto/Kconfig
index eb66c4e..4e112e9 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -38,6 +38,10 @@ config CRYPTO_HASH
tristate
select CRYPTO_ALGAPI
+config CRYPTO_PKA
+ tristate
+ select CRYPTO_ALGAPI
+
config CRYPTO_MANAGER
tristate "Cryptographic algorithm manager"
select CRYPTO_ALGAPI
diff --git a/crypto/Makefile b/crypto/Makefile
index 6819da9..949f08e 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -19,9 +19,9 @@ obj-$(CONFIG_CRYPTO_BLKCIPHER) += crypto_blkcipher.o
obj-$(CONFIG_CRYPTO_SEQIV) += seqiv.o
crypto_hash-objs := hash.o
+obj-$(CONFIG_CRYPTO_PKA) += pka.o
obj-$(CONFIG_CRYPTO_HASH) += crypto_hash.o
obj-$(CONFIG_CRYPTO_MANAGER) += cryptomgr.o
obj-$(CONFIG_CRYPTO_HMAC) += hmac.o
diff --git a/crypto/pka.c b/crypto/pka.c
new file mode 100644
index 0000000..532e8d5
--- /dev/null
+++ b/crypto/pka.c
@@ -0,0 +1,107 @@
+/*
+ * @ pka.c
+ * Linux CryptoAPI Module for PKA
+ *
+ * Copyright (c) 2008 Shasi Pulijala <[EMAIL PROTECTED]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <crypto/algapi.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+
+#include "internal.h"
+
+static unsigned int crypto_pka_ctxsize(struct crypto_alg *alg, u32 type,
+ u32 mask)
+{
+ return alg->cra_ctxsize;
+}
+
+static int crypto_init_pka_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
+{
+ struct pka_alg *alg = &tfm->__crt_alg->cra_pka;
+ struct pka_tfm *crt = &tfm->crt_pka;
+
+ crt->base = __crypto_pka_cast(tfm);
+ crt->pka_op = alg->pka_op;
+ return 0;
+}
+
+static void crypto_pka_show(struct seq_file *m, struct crypto_alg *alg)
+ __attribute__ ((unused));
+static void crypto_pka_show(struct seq_file *m, struct crypto_alg *alg)
+{
+ seq_printf(m, "type : pka\n");
+ seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ?
+ "yes" : "no");
+}
+
+const struct crypto_type crypto_pka_type = {
+ .ctxsize = crypto_pka_ctxsize,
+ .init = crypto_init_pka_ops,
+#ifdef CONFIG_PROC_FS
+ .show = crypto_pka_show,
+#endif
+};
+EXPORT_SYMBOL_GPL(crypto_pka_type);
+
+struct crypto_pka *crypto_alloc_pka(const char *alg_name,
+ u32 type, u32 mask)
+{
+ struct crypto_tfm *tfm;
+ int err;
+
+ mask &= ~CRYPTO_ALG_TYPE_MASK;
+
+ for (;;) {
+ struct crypto_alg *alg;
+
+ type &= ~CRYPTO_ALG_TYPE_MASK;
+ type |= CRYPTO_ALG_TYPE_ASYNC_PKA;
+ alg = crypto_alg_mod_lookup(alg_name, type, mask);
+ if (IS_ERR(alg)) {
+ type &= ~CRYPTO_ALG_TYPE_MASK;
+ type |= CRYPTO_ALG_TYPE_ASYNC_PKA;
+ alg = crypto_alg_mod_lookup(alg_name, type, mask);
+ if (IS_ERR(alg)) {
+ err = PTR_ERR(alg);
+ goto err;
+ }
+ }
+
+ tfm = __crypto_alloc_tfm(alg, type, mask | CRYPTO_ALG_ASYNC);
+ if (!IS_ERR(tfm))
+ return __crypto_pka_cast(tfm);
+
+ crypto_mod_put(alg);
+ err = PTR_ERR(tfm);
+
+err:
+ if (err != -EAGAIN)
+ break;
+ if (signal_pending(current)) {
+ err = -EINTR;
+ break;
+ }
+ }
+
+ return ERR_PTR(err);
+}
+EXPORT_SYMBOL_GPL(crypto_alloc_pka);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Cryptographic PKA type");
diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h
index 60d06e7..2498a9c 100644
--- a/include/crypto/algapi.h
+++ b/include/crypto/algapi.h
@@ -98,6 +98,7 @@ extern const struct crypto_type crypto_ablkcipher_type;
extern const struct crypto_type crypto_aead_type;
extern const struct crypto_type crypto_blkcipher_type;
extern const struct crypto_type crypto_hash_type;
+extern const struct crypto_type crypto_pka_type;
void crypto_mod_put(struct crypto_alg *alg);
@@ -314,5 +315,21 @@ static inline int crypto_requires_sync(u32 type, u32 mask)
return (type ^ CRYPTO_ALG_ASYNC) & mask & CRYPTO_ALG_ASYNC;
}
+static inline void *crypto_pka_ctx(struct crypto_pka *tfm)
+{
+ return crypto_tfm_ctx(&tfm->base);
+}
+
+static inline struct pka_alg *crypto_pka_alg(
+ struct crypto_pka *tfm)
+{
+ return &crypto_pka_tfm(tfm)->__crt_alg->cra_pka;
+}
+
+static inline void *pka_request_ctx(struct pka_request *req)
+{
+ return req->__ctx;
+}
+
#endif /* _CRYPTO_ALGAPI_H */
diff --git a/include/linux/crypto.h b/include/linux/crypto.h
index 425824b..ae697f6 100644
--- a/include/linux/crypto.h
+++ b/include/linux/crypto.h
@@ -37,6 +37,7 @@
#define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006
#define CRYPTO_ALG_TYPE_COMPRESS 0x00000008
#define CRYPTO_ALG_TYPE_AEAD 0x00000009
+#define CRYPTO_ALG_TYPE_ASYNC_PKA 0x0000000B
#define CRYPTO_ALG_TYPE_HASH_MASK 0x0000000e
#define CRYPTO_ALG_TYPE_BLKCIPHER_MASK 0x0000000c
@@ -102,6 +103,7 @@ struct crypto_async_request;
struct crypto_aead;
struct crypto_blkcipher;
struct crypto_hash;
+struct crypto_pka;
struct crypto_tfm;
struct crypto_type;
struct aead_givcrypt_request;
@@ -132,6 +134,33 @@ struct ablkcipher_request {
};
/**
+ * struct pka_request - PKA request
+ * @base: Common attributes for async pka requests
+ * @src: list of source operands
+ * @dst: result operands
+ * @shift_value: shift value for shift operation
+ * @__ctx: Start of private context data
+ */
+#define PKA_SRC_OPERANDS 6
+#define PKA_DST_OPERANDS 2
+
+struct pka_request {
+ struct crypto_async_request base;
+
+ struct scatterlist *src[6];
+ struct scatterlist *dst[2];
+ u32 operand_src_size[6];
+ u32 operand_dst_size[2];
+
+ int iops;
+ int oops;
+
+ u8 shift_value;
+
+ void *__ctx[] CRYPTO_MINALIGN_ATTR;
+};
+
+/**
* struct aead_request - AEAD request
* @base: Common attributes for async crypto requests
* @assoclen: Length in bytes of associated data for authentication
@@ -266,6 +295,10 @@ struct compress_alg {
unsigned int slen, u8 *dst, unsigned int *dlen);
};
+struct pka_alg {
+ int (*pka_op)(struct pka_request *req);
+};
+
#define cra_ablkcipher cra_u.ablkcipher
#define cra_aead cra_u.aead
#define cra_blkcipher cra_u.blkcipher
@@ -273,6 +306,7 @@ struct compress_alg {
#define cra_digest cra_u.digest
#define cra_hash cra_u.hash
#define cra_compress cra_u.compress
+#define cra_pka cra_u.pka
struct crypto_alg {
struct list_head cra_list;
@@ -299,12 +333,13 @@ struct crypto_alg {
struct digest_alg digest;
struct hash_alg hash;
struct compress_alg compress;
+ struct pka_alg pka;
} cra_u;
int (*cra_init)(struct crypto_tfm *tfm);
void (*cra_exit)(struct crypto_tfm *tfm);
void (*cra_destroy)(struct crypto_alg *alg);
-
+
struct module *cra_module;
};
@@ -392,17 +427,23 @@ struct compress_tfm {
u8 *dst, unsigned int *dlen);
};
+struct pka_tfm {
+ struct crypto_pka *base;
+ int (*pka_op)(struct pka_request *req);
+};
+
#define crt_ablkcipher crt_u.ablkcipher
#define crt_aead crt_u.aead
#define crt_blkcipher crt_u.blkcipher
#define crt_cipher crt_u.cipher
#define crt_hash crt_u.hash
#define crt_compress crt_u.compress
+#define crt_pka crt_u.pka
struct crypto_tfm {
u32 crt_flags;
-
+
union {
struct ablkcipher_tfm ablkcipher;
struct aead_tfm aead;
@@ -410,8 +451,9 @@ struct crypto_tfm {
struct cipher_tfm cipher;
struct hash_tfm hash;
struct compress_tfm compress;
+ struct pka_tfm pka;
} crt_u;
-
+
struct crypto_alg *__crt_alg;
void *__crt_ctx[] CRYPTO_MINALIGN_ATTR;
@@ -441,6 +483,10 @@ struct crypto_hash {
struct crypto_tfm base;
};
+struct crypto_pka {
+ struct crypto_tfm base;
+};
+
enum {
CRYPTOA_UNSPEC,
CRYPTOA_ALG,
@@ -1264,5 +1310,106 @@ static inline int crypto_comp_decompress(struct
crypto_comp *tfm,
src, slen, dst, dlen);
}
+static inline struct crypto_digest *__crypto_digest_cast(
+ struct crypto_tfm *tfm)
+{
+ return (struct crypto_digest *) tfm;
+}
+
+static inline struct crypto_pka *__crypto_pka_cast(struct crypto_tfm *tfm)
+{
+ return (struct crypto_pka *) tfm;
+}
+
+static inline struct crypto_tfm *crypto_pka_tfm(
+ struct crypto_pka *tfm)
+{
+ return &tfm->base;
+}
+
+static inline struct pka_tfm *crypto_pka_crt(struct crypto_pka *tfm)
+{
+ return &crypto_pka_tfm(tfm)->crt_pka;
+}
+
+static inline struct crypto_pka *crypto_pka_reqtfm(
+ struct pka_request *req)
+{
+ return __crypto_pka_cast(req->base.tfm);
+}
+
+static inline int crypto_pka_op(struct pka_request *req)
+{
+ struct pka_tfm *crt = crypto_pka_crt(crypto_pka_reqtfm(req));
+ return crt->pka_op(req);
+}
+
+static inline void pka_request_set_tfm(
+ struct pka_request *req, struct crypto_pka *tfm)
+{
+ req->base.tfm = crypto_pka_tfm(crypto_pka_crt(tfm)->base);
+}
+
+static inline struct pka_request *pka_request_alloc(
+ struct crypto_pka *tfm, gfp_t gfp)
+{
+ struct pka_request *req;
+
+ req = kmalloc(sizeof(struct pka_request), gfp);
+
+ if (likely(req))
+ pka_request_set_tfm(req, tfm);
+
+ return req;
+}
+
+static inline void pka_request_free(struct pka_request *req)
+{
+ kfree(req);
+}
+
+static inline void crypto_free_pka(struct crypto_pka *tfm)
+{
+ crypto_free_tfm(crypto_pka_tfm(tfm));
+}
+
+static inline void pka_request_set_operands(
+ struct pka_request *req,
+ struct scatterlist **sg_src,
+ struct scatterlist **sg_dst,
+ u32 *ssize,
+ u32 *dsize,
+ int iops, int oops, u8 shift)
+{
+ int i;
+ req->iops = iops;
+ req->oops = oops;
+ req->shift_value = shift;
+
+ for (i = 0; i < iops; i++) {
+ req->src[i] = sg_src[i];
+ req->operand_src_size[i] = ssize[i];
+ }
+
+ for (i = 0; i < oops; i++) {
+ req->dst[i] = sg_dst[i];
+ req->operand_dst_size[i] = dsize[i];
+ }
+
+}
+
+static inline void pka_request_set_callback(
+ struct pka_request *req,
+ u32 flags, crypto_completion_t complete, void *data)
+{
+ req->base.complete = complete;
+ req->base.data = data;
+ req->base.flags = flags;
+}
+
+
+struct crypto_pka *crypto_alloc_pka(const char *alg_name,
+ u32 type, u32 mask);
+
#endif /* _LINUX_CRYPTO_H */
--
1.5.5
--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html