Message ID | 20150430223652.10157.86151.stgit@tstruk-mobl1 (mailing list archive) |
---|---|
State | RFC |
Headers | show |
On Thu, Apr 30, 2015 at 03:36:52PM -0700, Tadeusz Struk wrote: > > +struct pke_alg { > + int (*sign)(struct pke_request *pkereq); > + int (*verify)(struct pke_request *pkereq); > + int (*encrypt)(struct pke_request *pkereq); > + int (*decrypt)(struct pke_request *pkereq); > + > + u8 pub_mpis; /* Number of MPIs in public key */ > + u8 sec_mpis; /* Number of MPIs in secret key */ > + u8 sig_mpis; /* Number of MPIs in a signature */ > +#define PKEY_CAN_ENCRYPT 0x01 > +#define PKEY_CAN_DECRYPT 0x02 > +#define PKEY_CAN_SIGN 0x04 > +#define PKEY_CAN_VERIFY 0x08 > + u8 capabilities; > +}; Please remodel it after pcompress or the newly converted rng type. This union stuff has been obsolete since 2008 and it's time for it to die. Thanks,
On 04/30/2015 03:43 PM, Herbert Xu wrote: > Please remodel it after pcompress or the newly converted rng type. > > This union stuff has been obsolete since 2008 and it's time for > it to die. Ok, I didn't realize. Will send v2 shortly. Thanks -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Am Donnerstag, 30. April 2015, 15:36:52 schrieb Tadeusz Struk: Hi Tadeusz, >Add Public Key Encryption API. > >Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> >--- > crypto/Kconfig | 6 + > crypto/Makefile | 1 > crypto/crypto_user.c | 23 +++++ > crypto/pke.c | 114 ++++++++++++++++++++++++++ > include/crypto/algapi.h | 6 + > include/linux/crypto.h | 191 >++++++++++++++++++++++++++++++++++++++++++++ include/linux/cryptouser.h | >7 ++ > 7 files changed, 347 insertions(+), 1 deletion(-) > create mode 100644 crypto/pke.c > >diff --git a/crypto/Kconfig b/crypto/Kconfig >index 8aaf298..9a14b33 100644 >--- a/crypto/Kconfig >+++ b/crypto/Kconfig >@@ -87,6 +87,12 @@ config CRYPTO_PCOMP2 > tristate > select CRYPTO_ALGAPI2 > >+config CRYPTO_PKE >+ tristate "Public Key Algorithms API" >+ select CRYPTO_ALGAPI >+ help >+ Crypto API interface for public key algorithms. >+ > config CRYPTO_MANAGER > tristate "Cryptographic algorithm manager" > select CRYPTO_MANAGER2 >diff --git a/crypto/Makefile b/crypto/Makefile >index 97b7d3a..e7dd283 100644 >--- a/crypto/Makefile >+++ b/crypto/Makefile >@@ -27,6 +27,7 @@ crypto_hash-y += shash.o > obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o > > obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o >+obj-$(CONFIG_CRYPTO_PKE) += pke.o > > cryptomgr-y := algboss.o testmgr.o > >diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c >index 41dfe76..83b4d0f 100644 >--- a/crypto/crypto_user.c >+++ b/crypto/crypto_user.c >@@ -110,6 +110,23 @@ nla_put_failure: > return -EMSGSIZE; > } > >+static int crypto_report_pke(struct sk_buff *skb, struct crypto_alg *alg) >+{ >+ struct crypto_report_pke rpke; >+ >+ strncpy(rpke.type, "pke", sizeof(rpke.type)); >+ strncpy(rpke.subtype, alg->cra_name, sizeof(rpke.subtype)); >+ rpke.capabilities = alg->cra_pke.capabilities; >+ >+ if (nla_put(skb, CRYPTOCFGA_REPORT_PKE, >+ sizeof(struct crypto_report_pke), &rpke)) >+ goto nla_put_failure; >+ return 0; >+ >+nla_put_failure: >+ return -EMSGSIZE; >+} >+ > static int crypto_report_one(struct crypto_alg *alg, > struct crypto_user_alg *ualg, struct sk_buff *skb) > { >@@ -154,6 +171,12 @@ static int crypto_report_one(struct crypto_alg *alg, > goto nla_put_failure; > > break; >+ >+ case CRYPTO_ALG_TYPE_PKE: >+ if (crypto_report_pke(skb, alg)) >+ goto nla_put_failure; >+ >+ break; > } > > out: >diff --git a/crypto/pke.c b/crypto/pke.c >new file mode 100644 >index 0000000..c1350fa >--- /dev/null >+++ b/crypto/pke.c >@@ -0,0 +1,114 @@ >+/* >+ * Public Key Encryption operations. >+ * >+ * Copyright (c) 2015, Intel Corporation >+ * Authors: Tadeusz Struk <tadeusz.struk@intel.com> >+ * >+ * 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. >+ * >+ */ >+#include <linux/errno.h> >+#include <linux/kernel.h> >+#include <linux/module.h> >+#include <linux/seq_file.h> >+#include <linux/slab.h> >+#include <linux/string.h> >+#include <linux/crypto.h> >+#include <linux/cryptouser.h> >+#include <net/netlink.h> >+#include "internal.h" >+ >+static unsigned int crypto_pke_ctxsize(struct crypto_alg *alg, u32 type, >+ u32 mask) >+{ >+ unsigned int len = alg->cra_ctxsize; >+ >+ return ALIGN(len, (unsigned long)alg->cra_alignmask + 1); >+} >+ >+static int crypto_init_pke_ops(struct crypto_tfm *tfm, u32 type, u32 mask) >+{ >+ struct pke_tfm *crt = &tfm->crt_pke; >+ struct pke_alg *alg = &tfm->__crt_alg->cra_pke; >+ >+ if (alg->pub_mpis > 5 || alg->sec_mpis > 5 || alg->sig_mpis > 2) >+ return -EINVAL; >+ >+ if ((alg->capabilities & PKEY_CAN_ENCRYPT) && !alg->encrypt) >+ return -EINVAL; >+ >+ if ((alg->capabilities & PKEY_CAN_DECRYPT) && !alg->decrypt) >+ return -EINVAL; >+ >+ if ((alg->capabilities & PKEY_CAN_SIGN) && !alg->sign) >+ return -EINVAL; >+ >+ if ((alg->capabilities & PKEY_CAN_VERIFY) && !alg->verify) >+ return -EINVAL; >+ >+ crt->sign = alg->sign; >+ crt->verify = alg->verify; >+ crt->encrypt = alg->encrypt; >+ crt->decrypt = alg->decrypt; >+ crt->base = __crypto_pke_cast(tfm); >+ >+ return 0; >+} >+ >+#ifdef CONFIG_NET >+static int crypto_pke_report(struct sk_buff *skb, struct crypto_alg *alg) >+{ >+ struct crypto_report_pke rep_pke; >+ >+ strncpy(rep_pke.type, "pke", sizeof(rep_pke.type)); >+ strncpy(rep_pke.subtype, alg->cra_name, sizeof(rep_pke.subtype)); >+ rep_pke.capabilities = alg->cra_pke.capabilities; >+ >+ if (nla_put(skb, CRYPTOCFGA_REPORT_PKE, >+ sizeof(struct crypto_report_pke), &rep_pke)) >+ goto nla_put_failure; >+ return 0; >+ >+nla_put_failure: >+ return -EMSGSIZE; >+} >+#else >+static int crypto_pke_report(struct sk_buff *skb, struct crypto_alg *alg) >+{ >+ return -ENOSYS; >+} >+#endif >+ >+static void crypto_pke_show(struct seq_file *m, struct crypto_alg *alg) >+ __attribute__ ((unused)); >+static void crypto_pke_show(struct seq_file *m, struct crypto_alg *alg) >+{ >+ int cap = alg->cra_pke.capabilities; >+ >+ seq_puts(m, "type : pke\n"); >+ seq_printf(m, "subtype : %s\n", alg->cra_name); >+ seq_printf(m, "can encrypt : %s\n", cap & PKEY_CAN_ENCRYPT ? >+ "yes" : "no"); >+ seq_printf(m, "can decrypt : %s\n", cap & PKEY_CAN_DECRYPT ? >+ "yes" : "no"); >+ seq_printf(m, "can sign : %s\n", cap & PKEY_CAN_SIGN ? >+ "yes" : "no"); >+ seq_printf(m, "can verify : %s\n", cap & PKEY_CAN_VERIFY ? >+ "yes" : "no"); >+} >+ >+const struct crypto_type crypto_pke_type = { >+ .ctxsize = crypto_pke_ctxsize, >+ .init = crypto_init_pke_ops, >+#ifdef CONFIG_PROC_FS >+ .show = crypto_pke_show, >+#endif >+ .report = crypto_pke_report, >+}; >+EXPORT_SYMBOL_GPL(crypto_pke_type); >+ >+MODULE_LICENSE("GPL"); >+MODULE_DESCRIPTION("Generic public key type"); >diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h >index 0ecb768..5c46eb8 100644 >--- a/include/crypto/algapi.h >+++ b/include/crypto/algapi.h >@@ -128,6 +128,7 @@ struct ablkcipher_walk { > 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_pke_type; > > void crypto_mod_put(struct crypto_alg *alg); > >@@ -378,6 +379,11 @@ static inline u32 aead_request_flags(struct aead_request >*req) return req->base.flags; > } > >+static inline void pke_request_complete(struct pke_request *req, int err) >+{ >+ req->base.complete(&req->base, err); >+} >+ > static inline struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, > u32 type, u32 mask) > { >diff --git a/include/linux/crypto.h b/include/linux/crypto.h >index ee14140..9538e2e 100644 >--- a/include/linux/crypto.h >+++ b/include/linux/crypto.h >@@ -52,6 +52,7 @@ > #define CRYPTO_ALG_TYPE_HASH 0x00000008 > #define CRYPTO_ALG_TYPE_SHASH 0x00000009 > #define CRYPTO_ALG_TYPE_AHASH 0x0000000a >+#define CRYPTO_ALG_TYPE_PKE 0x0000000b > #define CRYPTO_ALG_TYPE_RNG 0x0000000c > #define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f > >@@ -142,6 +143,8 @@ struct crypto_tfm; > struct crypto_type; > struct aead_givcrypt_request; > struct skcipher_givcrypt_request; >+struct public_key; >+struct public_key_signature; Wouldn't it make sense to move the struct definitions here and have them documented? > > typedef void (*crypto_completion_t)(struct crypto_async_request *req, int >err); > >@@ -200,6 +203,12 @@ struct aead_request { > void *__ctx[] CRYPTO_MINALIGN_ATTR; > }; > >+struct pke_request { >+ struct crypto_async_request base; >+ const struct public_key *pk; >+ const struct public_key_signature *pks; >+}; >+ > struct blkcipher_desc { > struct crypto_blkcipher *tfm; > void *info; >@@ -425,12 +434,28 @@ struct compress_alg { > unsigned int slen, u8 *dst, unsigned int *dlen); > }; > >+struct pke_alg { >+ int (*sign)(struct pke_request *pkereq); >+ int (*verify)(struct pke_request *pkereq); >+ int (*encrypt)(struct pke_request *pkereq); >+ int (*decrypt)(struct pke_request *pkereq); >+ >+ u8 pub_mpis; /* Number of MPIs in public key */ >+ u8 sec_mpis; /* Number of MPIs in secret key */ >+ u8 sig_mpis; /* Number of MPIs in a signature */ May I ask that for such new structs we add some documentation? Currently, I am unclear on what MPIs are. E.g. if somebody needs to add, say, Curve 25519, what shall he add here? >+#define PKEY_CAN_ENCRYPT 0x01 >+#define PKEY_CAN_DECRYPT 0x02 >+#define PKEY_CAN_SIGN 0x04 >+#define PKEY_CAN_VERIFY 0x08 >+ u8 capabilities; >+}; > > #define cra_ablkcipher cra_u.ablkcipher > #define cra_aead cra_u.aead > #define cra_blkcipher cra_u.blkcipher > #define cra_cipher cra_u.cipher > #define cra_compress cra_u.compress >+#define cra_pke cra_u.pke > > /** > * struct crypto_alg - definition of a cryptograpic cipher algorithm >@@ -530,6 +555,7 @@ struct crypto_alg { > struct blkcipher_alg blkcipher; > struct cipher_alg cipher; > struct compress_alg compress; >+ struct pke_alg pke; > } cra_u; > > int (*cra_init)(struct crypto_tfm *tfm); >@@ -625,12 +651,23 @@ struct compress_tfm { > u8 *dst, unsigned int *dlen); > }; > >+struct pke_tfm { >+ int (*sign)(struct pke_request *pkereq); >+ int (*verify)(struct pke_request *pkereq); >+ int (*encrypt)(struct pke_request *pkereq); >+ int (*decrypt)(struct pke_request *pkereq); >+ >+ struct crypto_pke *base; >+ unsigned int reqsize; >+}; >+ > #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_pke crt_u.pke > > struct crypto_tfm { > >@@ -643,6 +680,7 @@ struct crypto_tfm { > struct cipher_tfm cipher; > struct hash_tfm hash; > struct compress_tfm compress; >+ struct pke_tfm pke; > } crt_u; > > void (*exit)(struct crypto_tfm *tfm); >@@ -676,6 +714,10 @@ struct crypto_hash { > struct crypto_tfm base; > }; > >+struct crypto_pke { >+ struct crypto_tfm base; >+}; >+ > enum { > CRYPTOA_UNSPEC, > CRYPTOA_ALG, >@@ -2356,5 +2398,152 @@ static inline int crypto_comp_decompress(struct >crypto_comp *tfm, src, slen, dst, dlen); > } > >-#endif /* _LINUX_CRYPTO_H */ >+static inline struct crypto_pke *__crypto_pke_cast(struct crypto_tfm *tfm) >+{ >+ return (struct crypto_pke *)tfm; >+} >+ >+static inline struct crypto_pke *crypto_pke_cast(struct crypto_tfm *tfm) >+{ >+ BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_PKE); >+ return __crypto_pke_cast(tfm); >+} >+ >+static inline struct crypto_pke *crypto_alloc_pke(const char *alg_name, >+ u32 type, u32 mask) >+{ >+ type &= ~CRYPTO_ALG_TYPE_MASK; >+ type |= CRYPTO_ALG_TYPE_PKE; >+ mask |= CRYPTO_ALG_TYPE_MASK; >+ >+ return __crypto_pke_cast(crypto_alloc_base(alg_name, type, mask)); >+} >+ >+static inline struct crypto_tfm *crypto_pke_tfm(struct crypto_pke *tfm) >+{ >+ return &tfm->base; >+} >+ >+static inline struct pke_tfm *crypto_pke_crt(struct crypto_pke *tfm) >+{ >+ return &crypto_pke_tfm(tfm)->crt_pke; >+} >+ >+static inline void crypto_free_pke(struct crypto_pke *tfm) >+{ >+ crypto_free_tfm(crypto_pke_tfm(tfm)); >+} >+ >+static inline unsigned int crypto_pke_reqsize(struct crypto_pke *tfm) >+{ >+ return crypto_pke_crt(tfm)->reqsize; >+} >+ >+static inline void pke_request_set_tfm(struct pke_request *req, >+ struct crypto_pke *tfm) >+{ >+ req->base.tfm = crypto_pke_tfm(crypto_pke_crt(tfm)->base); >+} >+ >+static inline struct crypto_pke *crypto_pke_reqtfm(struct pke_request *req) >+{ >+ return __crypto_pke_cast(req->base.tfm); >+} >+ >+static inline struct pke_request *pke_request_alloc(struct crypto_pke *tfm, >+ gfp_t gfp) >+{ >+ struct pke_request *req; >+ >+ req = kmalloc(sizeof(*req) + crypto_pke_reqsize(tfm), gfp); >+ if (likely(req)) >+ pke_request_set_tfm(req, tfm); >+ >+ return req; >+} > >+static inline void pke_request_free(struct pke_request *req) >+{ >+ kzfree(req); >+} >+ >+static inline void pke_request_set_callback(struct pke_request *req, >+ u32 flags, crypto_completion_t cmpl, >+ void *data) >+{ >+ req->base.complete = cmpl; >+ req->base.data = data; >+ req->base.flags = flags; >+} >+ >+static inline void pke_request_set_crypt(struct pke_request *req, >+ const struct public_key *pk, >+ const struct public_key_signature *sig) >+{ >+ req->pk = pk; >+ req->pks = sig; >+} Up to here I am volunteering to add the documentation comments. But for the following functions, I am not sure how they are supposed to be used correctly. Thus, can you add the documentation for them or at least give me a hint so that I can add the documentation? >+ >+static inline u8 pke_num_sig_mpi(struct crypto_pke *tfm) >+{ >+ struct crypto_tfm *base_tfm = &tfm->base; >+ >+ return base_tfm->__crt_alg->cra_pke.sig_mpis; >+} >+ >+static inline u8 pke_num_pub_mpi(struct crypto_pke *tfm) >+{ >+ struct crypto_tfm *base_tfm = &tfm->base; >+ >+ return base_tfm->__crt_alg->cra_pke.pub_mpis; >+} >+ >+static inline u8 pke_num_sec_mpi(struct crypto_pke *tfm) >+{ >+ struct crypto_tfm *base_tfm = &tfm->base; >+ >+ return base_tfm->__crt_alg->cra_pke.sec_mpis; >+} >+ >+static inline u8 pke_capab(struct crypto_pke *tfm) >+{ >+ struct crypto_tfm *base_tfm = &tfm->base; >+ >+ return base_tfm->__crt_alg->cra_pke.capabilities; >+} >+ >+static inline const char *pke_alg_name(struct crypto_pke *tfm) >+{ >+ struct crypto_tfm *base_tfm = &tfm->base; >+ >+ return base_tfm->__crt_alg->cra_name; >+} >+ >+static inline int crypto_pke_encrypt(struct pke_request *req) >+{ >+ struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); >+ >+ return tfm->encrypt(req); >+} >+ >+static inline int crypto_pke_decrypt(struct pke_request *req) >+{ >+ struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); >+ >+ return tfm->decrypt(req); >+} >+ >+static inline int crypto_pke_sign(struct pke_request *req) >+{ >+ struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); >+ >+ return tfm->sign(req); >+} >+ >+static inline int crypto_pke_verify(struct pke_request *req) >+{ >+ struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); >+ >+ return tfm->verify(req); >+} >+#endif /* _LINUX_CRYPTO_H */ >diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h >index 4abf2ea..e801130 100644 >--- a/include/linux/cryptouser.h >+++ b/include/linux/cryptouser.h >@@ -43,6 +43,7 @@ enum crypto_attr_type_t { > CRYPTOCFGA_REPORT_COMPRESS, /* struct crypto_report_comp */ > CRYPTOCFGA_REPORT_RNG, /* struct crypto_report_rng */ > CRYPTOCFGA_REPORT_CIPHER, /* struct crypto_report_cipher */ >+ CRYPTOCFGA_REPORT_PKE, /* struct crypto_report_pke */ > __CRYPTOCFGA_MAX > > #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) >@@ -101,5 +102,11 @@ struct crypto_report_rng { > unsigned int seedsize; > }; > >+struct crypto_report_pke { >+ char type[CRYPTO_MAX_NAME]; >+ char subtype[CRYPTO_MAX_NAME]; >+ unsigned int capabilities; >+}; >+ > #define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \ > sizeof(struct crypto_report_blkcipher)) > >-- >To unsubscribe from this list: send the line "unsubscribe linux-crypto" in >the body of a message to majordomo@vger.kernel.org >More majordomo info at http://vger.kernel.org/majordomo-info.html Ciao Stephan -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Tadeusz Struk <tadeusz.struk@intel.com> wrote: > +config CRYPTO_PKE I would prefer CRYPTO_PKEY and pkey rather than pke generally and algo rather than alg where possible - this will have more consistency with what we have now. I understand, however, that in core crypto code, 'alg' is used. + seq_printf(m, "can encrypt : %s\n", cap & PKEY_CAN_ENCRYPT ? + "yes" : "no"); Please split the line after the comma. > #define CRYPTO_ALG_TYPE_AHASH 0x0000000a > +#define CRYPTO_ALG_TYPE_PKE 0x0000000b > #define CRYPTO_ALG_TYPE_RNG 0x0000000c Will filling a hole cause a problem with something that got obsoleted? > +struct pke_request { > + struct crypto_async_request base; > + const struct public_key *pk; > + const struct public_key_signature *pks; > +}; I recommend: pk -> key or pkey pks -> sig or signature > + u8 pub_mpis; /* Number of MPIs in public key */ > + u8 sec_mpis; /* Number of MPIs in secret key */ > + u8 sig_mpis; /* Number of MPIs in a signature */ Keep member names as: u8 n_pub_mpi; /* Number of MPIs in public key */ u8 n_sec_mpi; /* Number of MPIs in secret key */ u8 n_sig_mpi; /* Number of MPIs in a signature */ please. David -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Stephan, On 05/01/2015 12:24 AM, Stephan Mueller wrote: >> +struct public_key; >> >+struct public_key_signature; > Wouldn't it make sense to move the struct definitions here and have them > documented? I'm not sure if they belong here. I think we can add some documentation without moving them. >> +struct pke_alg { >> >+ int (*sign)(struct pke_request *pkereq); >> >+ int (*verify)(struct pke_request *pkereq); >> >+ int (*encrypt)(struct pke_request *pkereq); >> >+ int (*decrypt)(struct pke_request *pkereq); >> >+ >> >+ u8 pub_mpis; /* Number of MPIs in public key */ >> >+ u8 sec_mpis; /* Number of MPIs in secret key */ >> >+ u8 sig_mpis; /* Number of MPIs in a signature */ > May I ask that for such new structs we add some documentation? Currently, I am > unclear on what MPIs are. E.g. if somebody needs to add, say, Curve 25519, > what shall he add here? Sure, I'll add some description. > > Up to here I am volunteering to add the documentation comments. > > But for the following functions, I am not sure how they are supposed to be > used correctly. Thus, can you add the documentation for them or at least give > me a hint so that I can add the documentation? Same here, I'll add something. Thanks for volunteering. You did a good job documenting the rest and your help will be appreciated. -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 05/01/2015 09:04 AM, David Howells wrote: >> +config CRYPTO_PKE > I would prefer CRYPTO_PKEY and pkey rather than pke generally and algo rather > than alg where possible - this will have more consistency with what we have > now. > > I understand, however, that in core crypto code, 'alg' is used. I'm fine with pkey. Herbert do you have preference with regards 'algo' vs 'alg'? >> #define CRYPTO_ALG_TYPE_AHASH 0x0000000a >> > +#define CRYPTO_ALG_TYPE_PKE 0x0000000b >> > #define CRYPTO_ALG_TYPE_RNG 0x0000000c > Will filling a hole cause a problem with something that got obsoleted? I hope not. I checked as far back as 2.6.18 and I don't see any clash. Herbert, what do you think? > >> +struct pke_request { >> > + struct crypto_async_request base; >> > + const struct public_key *pk; >> > + const struct public_key_signature *pks; >> > +}; > I recommend: > > pk -> key or pkey > pks -> sig or signature no problem > >> + u8 pub_mpis; /* Number of MPIs in public key */ >> > + u8 sec_mpis; /* Number of MPIs in secret key */ >> > + u8 sig_mpis; /* Number of MPIs in a signature */ > Keep member names as: > > u8 n_pub_mpi; /* Number of MPIs in public key */ > u8 n_sec_mpi; /* Number of MPIs in secret key */ > u8 n_sig_mpi; /* Number of MPIs in a signature */ same here. thanks -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Fri, May 01, 2015 at 11:17:44AM -0700, Tadeusz Struk wrote: > > I'm fine with pkey. Herbert do you have preference with regards 'algo' vs 'alg'? For interfaces with the crypto API alg should be used otherwise you can use algo or whatever you like. > >> #define CRYPTO_ALG_TYPE_AHASH 0x0000000a > >> > +#define CRYPTO_ALG_TYPE_PKE 0x0000000b > >> > #define CRYPTO_ALG_TYPE_RNG 0x0000000c > > Will filling a hole cause a problem with something that got obsoleted? > > I hope not. I checked as far back as 2.6.18 and I don't see any clash. > Herbert, what do you think? Indeed you can't use this hole as it'll make you a hash algorithm. Cheers,
diff --git a/crypto/Kconfig b/crypto/Kconfig index 8aaf298..9a14b33 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -87,6 +87,12 @@ config CRYPTO_PCOMP2 tristate select CRYPTO_ALGAPI2 +config CRYPTO_PKE + tristate "Public Key Algorithms API" + select CRYPTO_ALGAPI + help + Crypto API interface for public key algorithms. + config CRYPTO_MANAGER tristate "Cryptographic algorithm manager" select CRYPTO_MANAGER2 diff --git a/crypto/Makefile b/crypto/Makefile index 97b7d3a..e7dd283 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -27,6 +27,7 @@ crypto_hash-y += shash.o obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o +obj-$(CONFIG_CRYPTO_PKE) += pke.o cryptomgr-y := algboss.o testmgr.o diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 41dfe76..83b4d0f 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -110,6 +110,23 @@ nla_put_failure: return -EMSGSIZE; } +static int crypto_report_pke(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_pke rpke; + + strncpy(rpke.type, "pke", sizeof(rpke.type)); + strncpy(rpke.subtype, alg->cra_name, sizeof(rpke.subtype)); + rpke.capabilities = alg->cra_pke.capabilities; + + if (nla_put(skb, CRYPTOCFGA_REPORT_PKE, + sizeof(struct crypto_report_pke), &rpke)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} + static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { @@ -154,6 +171,12 @@ static int crypto_report_one(struct crypto_alg *alg, goto nla_put_failure; break; + + case CRYPTO_ALG_TYPE_PKE: + if (crypto_report_pke(skb, alg)) + goto nla_put_failure; + + break; } out: diff --git a/crypto/pke.c b/crypto/pke.c new file mode 100644 index 0000000..c1350fa --- /dev/null +++ b/crypto/pke.c @@ -0,0 +1,114 @@ +/* + * Public Key Encryption operations. + * + * Copyright (c) 2015, Intel Corporation + * Authors: Tadeusz Struk <tadeusz.struk@intel.com> + * + * 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. + * + */ +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/seq_file.h> +#include <linux/slab.h> +#include <linux/string.h> +#include <linux/crypto.h> +#include <linux/cryptouser.h> +#include <net/netlink.h> +#include "internal.h" + +static unsigned int crypto_pke_ctxsize(struct crypto_alg *alg, u32 type, + u32 mask) +{ + unsigned int len = alg->cra_ctxsize; + + return ALIGN(len, (unsigned long)alg->cra_alignmask + 1); +} + +static int crypto_init_pke_ops(struct crypto_tfm *tfm, u32 type, u32 mask) +{ + struct pke_tfm *crt = &tfm->crt_pke; + struct pke_alg *alg = &tfm->__crt_alg->cra_pke; + + if (alg->pub_mpis > 5 || alg->sec_mpis > 5 || alg->sig_mpis > 2) + return -EINVAL; + + if ((alg->capabilities & PKEY_CAN_ENCRYPT) && !alg->encrypt) + return -EINVAL; + + if ((alg->capabilities & PKEY_CAN_DECRYPT) && !alg->decrypt) + return -EINVAL; + + if ((alg->capabilities & PKEY_CAN_SIGN) && !alg->sign) + return -EINVAL; + + if ((alg->capabilities & PKEY_CAN_VERIFY) && !alg->verify) + return -EINVAL; + + crt->sign = alg->sign; + crt->verify = alg->verify; + crt->encrypt = alg->encrypt; + crt->decrypt = alg->decrypt; + crt->base = __crypto_pke_cast(tfm); + + return 0; +} + +#ifdef CONFIG_NET +static int crypto_pke_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + struct crypto_report_pke rep_pke; + + strncpy(rep_pke.type, "pke", sizeof(rep_pke.type)); + strncpy(rep_pke.subtype, alg->cra_name, sizeof(rep_pke.subtype)); + rep_pke.capabilities = alg->cra_pke.capabilities; + + if (nla_put(skb, CRYPTOCFGA_REPORT_PKE, + sizeof(struct crypto_report_pke), &rep_pke)) + goto nla_put_failure; + return 0; + +nla_put_failure: + return -EMSGSIZE; +} +#else +static int crypto_pke_report(struct sk_buff *skb, struct crypto_alg *alg) +{ + return -ENOSYS; +} +#endif + +static void crypto_pke_show(struct seq_file *m, struct crypto_alg *alg) + __attribute__ ((unused)); +static void crypto_pke_show(struct seq_file *m, struct crypto_alg *alg) +{ + int cap = alg->cra_pke.capabilities; + + seq_puts(m, "type : pke\n"); + seq_printf(m, "subtype : %s\n", alg->cra_name); + seq_printf(m, "can encrypt : %s\n", cap & PKEY_CAN_ENCRYPT ? + "yes" : "no"); + seq_printf(m, "can decrypt : %s\n", cap & PKEY_CAN_DECRYPT ? + "yes" : "no"); + seq_printf(m, "can sign : %s\n", cap & PKEY_CAN_SIGN ? + "yes" : "no"); + seq_printf(m, "can verify : %s\n", cap & PKEY_CAN_VERIFY ? + "yes" : "no"); +} + +const struct crypto_type crypto_pke_type = { + .ctxsize = crypto_pke_ctxsize, + .init = crypto_init_pke_ops, +#ifdef CONFIG_PROC_FS + .show = crypto_pke_show, +#endif + .report = crypto_pke_report, +}; +EXPORT_SYMBOL_GPL(crypto_pke_type); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Generic public key type"); diff --git a/include/crypto/algapi.h b/include/crypto/algapi.h index 0ecb768..5c46eb8 100644 --- a/include/crypto/algapi.h +++ b/include/crypto/algapi.h @@ -128,6 +128,7 @@ struct ablkcipher_walk { 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_pke_type; void crypto_mod_put(struct crypto_alg *alg); @@ -378,6 +379,11 @@ static inline u32 aead_request_flags(struct aead_request *req) return req->base.flags; } +static inline void pke_request_complete(struct pke_request *req, int err) +{ + req->base.complete(&req->base, err); +} + static inline struct crypto_alg *crypto_get_attr_alg(struct rtattr **tb, u32 type, u32 mask) { diff --git a/include/linux/crypto.h b/include/linux/crypto.h index ee14140..9538e2e 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -52,6 +52,7 @@ #define CRYPTO_ALG_TYPE_HASH 0x00000008 #define CRYPTO_ALG_TYPE_SHASH 0x00000009 #define CRYPTO_ALG_TYPE_AHASH 0x0000000a +#define CRYPTO_ALG_TYPE_PKE 0x0000000b #define CRYPTO_ALG_TYPE_RNG 0x0000000c #define CRYPTO_ALG_TYPE_PCOMPRESS 0x0000000f @@ -142,6 +143,8 @@ struct crypto_tfm; struct crypto_type; struct aead_givcrypt_request; struct skcipher_givcrypt_request; +struct public_key; +struct public_key_signature; typedef void (*crypto_completion_t)(struct crypto_async_request *req, int err); @@ -200,6 +203,12 @@ struct aead_request { void *__ctx[] CRYPTO_MINALIGN_ATTR; }; +struct pke_request { + struct crypto_async_request base; + const struct public_key *pk; + const struct public_key_signature *pks; +}; + struct blkcipher_desc { struct crypto_blkcipher *tfm; void *info; @@ -425,12 +434,28 @@ struct compress_alg { unsigned int slen, u8 *dst, unsigned int *dlen); }; +struct pke_alg { + int (*sign)(struct pke_request *pkereq); + int (*verify)(struct pke_request *pkereq); + int (*encrypt)(struct pke_request *pkereq); + int (*decrypt)(struct pke_request *pkereq); + + u8 pub_mpis; /* Number of MPIs in public key */ + u8 sec_mpis; /* Number of MPIs in secret key */ + u8 sig_mpis; /* Number of MPIs in a signature */ +#define PKEY_CAN_ENCRYPT 0x01 +#define PKEY_CAN_DECRYPT 0x02 +#define PKEY_CAN_SIGN 0x04 +#define PKEY_CAN_VERIFY 0x08 + u8 capabilities; +}; #define cra_ablkcipher cra_u.ablkcipher #define cra_aead cra_u.aead #define cra_blkcipher cra_u.blkcipher #define cra_cipher cra_u.cipher #define cra_compress cra_u.compress +#define cra_pke cra_u.pke /** * struct crypto_alg - definition of a cryptograpic cipher algorithm @@ -530,6 +555,7 @@ struct crypto_alg { struct blkcipher_alg blkcipher; struct cipher_alg cipher; struct compress_alg compress; + struct pke_alg pke; } cra_u; int (*cra_init)(struct crypto_tfm *tfm); @@ -625,12 +651,23 @@ struct compress_tfm { u8 *dst, unsigned int *dlen); }; +struct pke_tfm { + int (*sign)(struct pke_request *pkereq); + int (*verify)(struct pke_request *pkereq); + int (*encrypt)(struct pke_request *pkereq); + int (*decrypt)(struct pke_request *pkereq); + + struct crypto_pke *base; + unsigned int reqsize; +}; + #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_pke crt_u.pke struct crypto_tfm { @@ -643,6 +680,7 @@ struct crypto_tfm { struct cipher_tfm cipher; struct hash_tfm hash; struct compress_tfm compress; + struct pke_tfm pke; } crt_u; void (*exit)(struct crypto_tfm *tfm); @@ -676,6 +714,10 @@ struct crypto_hash { struct crypto_tfm base; }; +struct crypto_pke { + struct crypto_tfm base; +}; + enum { CRYPTOA_UNSPEC, CRYPTOA_ALG, @@ -2356,5 +2398,152 @@ static inline int crypto_comp_decompress(struct crypto_comp *tfm, src, slen, dst, dlen); } -#endif /* _LINUX_CRYPTO_H */ +static inline struct crypto_pke *__crypto_pke_cast(struct crypto_tfm *tfm) +{ + return (struct crypto_pke *)tfm; +} + +static inline struct crypto_pke *crypto_pke_cast(struct crypto_tfm *tfm) +{ + BUG_ON(crypto_tfm_alg_type(tfm) != CRYPTO_ALG_TYPE_PKE); + return __crypto_pke_cast(tfm); +} + +static inline struct crypto_pke *crypto_alloc_pke(const char *alg_name, + u32 type, u32 mask) +{ + type &= ~CRYPTO_ALG_TYPE_MASK; + type |= CRYPTO_ALG_TYPE_PKE; + mask |= CRYPTO_ALG_TYPE_MASK; + + return __crypto_pke_cast(crypto_alloc_base(alg_name, type, mask)); +} + +static inline struct crypto_tfm *crypto_pke_tfm(struct crypto_pke *tfm) +{ + return &tfm->base; +} + +static inline struct pke_tfm *crypto_pke_crt(struct crypto_pke *tfm) +{ + return &crypto_pke_tfm(tfm)->crt_pke; +} + +static inline void crypto_free_pke(struct crypto_pke *tfm) +{ + crypto_free_tfm(crypto_pke_tfm(tfm)); +} + +static inline unsigned int crypto_pke_reqsize(struct crypto_pke *tfm) +{ + return crypto_pke_crt(tfm)->reqsize; +} + +static inline void pke_request_set_tfm(struct pke_request *req, + struct crypto_pke *tfm) +{ + req->base.tfm = crypto_pke_tfm(crypto_pke_crt(tfm)->base); +} + +static inline struct crypto_pke *crypto_pke_reqtfm(struct pke_request *req) +{ + return __crypto_pke_cast(req->base.tfm); +} + +static inline struct pke_request *pke_request_alloc(struct crypto_pke *tfm, + gfp_t gfp) +{ + struct pke_request *req; + + req = kmalloc(sizeof(*req) + crypto_pke_reqsize(tfm), gfp); + if (likely(req)) + pke_request_set_tfm(req, tfm); + + return req; +} +static inline void pke_request_free(struct pke_request *req) +{ + kzfree(req); +} + +static inline void pke_request_set_callback(struct pke_request *req, + u32 flags, crypto_completion_t cmpl, + void *data) +{ + req->base.complete = cmpl; + req->base.data = data; + req->base.flags = flags; +} + +static inline void pke_request_set_crypt(struct pke_request *req, + const struct public_key *pk, + const struct public_key_signature *sig) +{ + req->pk = pk; + req->pks = sig; +} + +static inline u8 pke_num_sig_mpi(struct crypto_pke *tfm) +{ + struct crypto_tfm *base_tfm = &tfm->base; + + return base_tfm->__crt_alg->cra_pke.sig_mpis; +} + +static inline u8 pke_num_pub_mpi(struct crypto_pke *tfm) +{ + struct crypto_tfm *base_tfm = &tfm->base; + + return base_tfm->__crt_alg->cra_pke.pub_mpis; +} + +static inline u8 pke_num_sec_mpi(struct crypto_pke *tfm) +{ + struct crypto_tfm *base_tfm = &tfm->base; + + return base_tfm->__crt_alg->cra_pke.sec_mpis; +} + +static inline u8 pke_capab(struct crypto_pke *tfm) +{ + struct crypto_tfm *base_tfm = &tfm->base; + + return base_tfm->__crt_alg->cra_pke.capabilities; +} + +static inline const char *pke_alg_name(struct crypto_pke *tfm) +{ + struct crypto_tfm *base_tfm = &tfm->base; + + return base_tfm->__crt_alg->cra_name; +} + +static inline int crypto_pke_encrypt(struct pke_request *req) +{ + struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); + + return tfm->encrypt(req); +} + +static inline int crypto_pke_decrypt(struct pke_request *req) +{ + struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); + + return tfm->decrypt(req); +} + +static inline int crypto_pke_sign(struct pke_request *req) +{ + struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); + + return tfm->sign(req); +} + +static inline int crypto_pke_verify(struct pke_request *req) +{ + struct pke_tfm *tfm = crypto_pke_crt(crypto_pke_reqtfm(req)); + + return tfm->verify(req); +} +#endif /* _LINUX_CRYPTO_H */ diff --git a/include/linux/cryptouser.h b/include/linux/cryptouser.h index 4abf2ea..e801130 100644 --- a/include/linux/cryptouser.h +++ b/include/linux/cryptouser.h @@ -43,6 +43,7 @@ enum crypto_attr_type_t { CRYPTOCFGA_REPORT_COMPRESS, /* struct crypto_report_comp */ CRYPTOCFGA_REPORT_RNG, /* struct crypto_report_rng */ CRYPTOCFGA_REPORT_CIPHER, /* struct crypto_report_cipher */ + CRYPTOCFGA_REPORT_PKE, /* struct crypto_report_pke */ __CRYPTOCFGA_MAX #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) @@ -101,5 +102,11 @@ struct crypto_report_rng { unsigned int seedsize; }; +struct crypto_report_pke { + char type[CRYPTO_MAX_NAME]; + char subtype[CRYPTO_MAX_NAME]; + unsigned int capabilities; +}; + #define CRYPTO_REPORT_MAXSIZE (sizeof(struct crypto_user_alg) + \ sizeof(struct crypto_report_blkcipher))
Add Public Key Encryption API. Signed-off-by: Tadeusz Struk <tadeusz.struk@intel.com> --- crypto/Kconfig | 6 + crypto/Makefile | 1 crypto/crypto_user.c | 23 +++++ crypto/pke.c | 114 ++++++++++++++++++++++++++ include/crypto/algapi.h | 6 + include/linux/crypto.h | 191 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/cryptouser.h | 7 ++ 7 files changed, 347 insertions(+), 1 deletion(-) create mode 100644 crypto/pke.c -- To unsubscribe from this list: send the line "unsubscribe linux-crypto" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html