Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: kpp - Key-agreement Protocol Primitives API (KPP)

Add key-agreement protocol primitives (kpp) API which allows to
implement primitives required by protocols such as DH and ECDH.
The API is composed mainly by the following functions
* set_secret() - It allows the user to set his secret, also
referred to as his private key, along with the parameters
known to both parties involved in the key-agreement session.
* generate_public_key() - It generates the public key to be sent to
the other counterpart involved in the key-agreement session. The
function has to be called after set_params() and set_secret()
* generate_secret() - It generates the shared secret for the session

Other functions such as init() and exit() are provided for allowing
cryptographic hardware to be inizialized properly before use

Signed-off-by: Salvatore Benedetto <salvatore.benedetto@intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Salvatore Benedetto and committed by
Herbert Xu
4e5f2c40 331bf739

+552
+10
crypto/Kconfig
··· 93 93 select CRYPTO_AKCIPHER2 94 94 select CRYPTO_ALGAPI 95 95 96 + config CRYPTO_KPP2 97 + tristate 98 + select CRYPTO_ALGAPI2 99 + 100 + config CRYPTO_KPP 101 + tristate 102 + select CRYPTO_ALGAPI 103 + select CRYPTO_KPP2 104 + 96 105 config CRYPTO_RSA 97 106 tristate "RSA algorithm" 98 107 select CRYPTO_AKCIPHER ··· 124 115 select CRYPTO_HASH2 125 116 select CRYPTO_BLKCIPHER2 126 117 select CRYPTO_AKCIPHER2 118 + select CRYPTO_KPP2 127 119 128 120 config CRYPTO_USER 129 121 tristate "Userspace cryptographic algorithm configuration"
+1
crypto/Makefile
··· 30 30 obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o 31 31 32 32 obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o 33 + obj-$(CONFIG_CRYPTO_KPP2) += kpp.o 33 34 34 35 $(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h 35 36 $(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
+20
crypto/crypto_user.c
··· 28 28 #include <crypto/internal/skcipher.h> 29 29 #include <crypto/internal/rng.h> 30 30 #include <crypto/akcipher.h> 31 + #include <crypto/kpp.h> 31 32 32 33 #include "internal.h" 33 34 ··· 127 126 return -EMSGSIZE; 128 127 } 129 128 129 + static int crypto_report_kpp(struct sk_buff *skb, struct crypto_alg *alg) 130 + { 131 + struct crypto_report_kpp rkpp; 132 + 133 + strncpy(rkpp.type, "kpp", sizeof(rkpp.type)); 134 + 135 + if (nla_put(skb, CRYPTOCFGA_REPORT_KPP, 136 + sizeof(struct crypto_report_kpp), &rkpp)) 137 + goto nla_put_failure; 138 + return 0; 139 + 140 + nla_put_failure: 141 + return -EMSGSIZE; 142 + } 143 + 130 144 static int crypto_report_one(struct crypto_alg *alg, 131 145 struct crypto_user_alg *ualg, struct sk_buff *skb) 132 146 { ··· 191 175 if (crypto_report_akcipher(skb, alg)) 192 176 goto nla_put_failure; 193 177 178 + break; 179 + case CRYPTO_ALG_TYPE_KPP: 180 + if (crypto_report_kpp(skb, alg)) 181 + goto nla_put_failure; 194 182 break; 195 183 } 196 184
+123
crypto/kpp.c
··· 1 + /* 2 + * Key-agreement Protocol Primitives (KPP) 3 + * 4 + * Copyright (c) 2016, Intel Corporation 5 + * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License as published by the Free 9 + * Software Foundation; either version 2 of the License, or (at your option) 10 + * any later version. 11 + * 12 + */ 13 + #include <linux/errno.h> 14 + #include <linux/kernel.h> 15 + #include <linux/module.h> 16 + #include <linux/seq_file.h> 17 + #include <linux/slab.h> 18 + #include <linux/string.h> 19 + #include <linux/crypto.h> 20 + #include <crypto/algapi.h> 21 + #include <linux/cryptouser.h> 22 + #include <net/netlink.h> 23 + #include <crypto/kpp.h> 24 + #include <crypto/internal/kpp.h> 25 + #include "internal.h" 26 + 27 + #ifdef CONFIG_NET 28 + static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg) 29 + { 30 + struct crypto_report_kpp rkpp; 31 + 32 + strncpy(rkpp.type, "kpp", sizeof(rkpp.type)); 33 + 34 + if (nla_put(skb, CRYPTOCFGA_REPORT_KPP, 35 + sizeof(struct crypto_report_kpp), &rkpp)) 36 + goto nla_put_failure; 37 + return 0; 38 + 39 + nla_put_failure: 40 + return -EMSGSIZE; 41 + } 42 + #else 43 + static int crypto_kpp_report(struct sk_buff *skb, struct crypto_alg *alg) 44 + { 45 + return -ENOSYS; 46 + } 47 + #endif 48 + 49 + static void crypto_kpp_show(struct seq_file *m, struct crypto_alg *alg) 50 + __attribute__ ((unused)); 51 + 52 + static void crypto_kpp_show(struct seq_file *m, struct crypto_alg *alg) 53 + { 54 + seq_puts(m, "type : kpp\n"); 55 + } 56 + 57 + static void crypto_kpp_exit_tfm(struct crypto_tfm *tfm) 58 + { 59 + struct crypto_kpp *kpp = __crypto_kpp_tfm(tfm); 60 + struct kpp_alg *alg = crypto_kpp_alg(kpp); 61 + 62 + alg->exit(kpp); 63 + } 64 + 65 + static int crypto_kpp_init_tfm(struct crypto_tfm *tfm) 66 + { 67 + struct crypto_kpp *kpp = __crypto_kpp_tfm(tfm); 68 + struct kpp_alg *alg = crypto_kpp_alg(kpp); 69 + 70 + if (alg->exit) 71 + kpp->base.exit = crypto_kpp_exit_tfm; 72 + 73 + if (alg->init) 74 + return alg->init(kpp); 75 + 76 + return 0; 77 + } 78 + 79 + static const struct crypto_type crypto_kpp_type = { 80 + .extsize = crypto_alg_extsize, 81 + .init_tfm = crypto_kpp_init_tfm, 82 + #ifdef CONFIG_PROC_FS 83 + .show = crypto_kpp_show, 84 + #endif 85 + .report = crypto_kpp_report, 86 + .maskclear = ~CRYPTO_ALG_TYPE_MASK, 87 + .maskset = CRYPTO_ALG_TYPE_MASK, 88 + .type = CRYPTO_ALG_TYPE_KPP, 89 + .tfmsize = offsetof(struct crypto_kpp, base), 90 + }; 91 + 92 + struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask) 93 + { 94 + return crypto_alloc_tfm(alg_name, &crypto_kpp_type, type, mask); 95 + } 96 + EXPORT_SYMBOL_GPL(crypto_alloc_kpp); 97 + 98 + static void kpp_prepare_alg(struct kpp_alg *alg) 99 + { 100 + struct crypto_alg *base = &alg->base; 101 + 102 + base->cra_type = &crypto_kpp_type; 103 + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 104 + base->cra_flags |= CRYPTO_ALG_TYPE_KPP; 105 + } 106 + 107 + int crypto_register_kpp(struct kpp_alg *alg) 108 + { 109 + struct crypto_alg *base = &alg->base; 110 + 111 + kpp_prepare_alg(alg); 112 + return crypto_register_alg(base); 113 + } 114 + EXPORT_SYMBOL_GPL(crypto_register_kpp); 115 + 116 + void crypto_unregister_kpp(struct kpp_alg *alg) 117 + { 118 + crypto_unregister_alg(&alg->base); 119 + } 120 + EXPORT_SYMBOL_GPL(crypto_unregister_kpp); 121 + 122 + MODULE_LICENSE("GPL"); 123 + MODULE_DESCRIPTION("Key-agreement Protocol Primitives");
+64
include/crypto/internal/kpp.h
··· 1 + /* 2 + * Key-agreement Protocol Primitives (KPP) 3 + * 4 + * Copyright (c) 2016, Intel Corporation 5 + * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License as published by the Free 9 + * Software Foundation; either version 2 of the License, or (at your option) 10 + * any later version. 11 + * 12 + */ 13 + #ifndef _CRYPTO_KPP_INT_H 14 + #define _CRYPTO_KPP_INT_H 15 + #include <crypto/kpp.h> 16 + #include <crypto/algapi.h> 17 + 18 + /* 19 + * Transform internal helpers. 20 + */ 21 + static inline void *kpp_request_ctx(struct kpp_request *req) 22 + { 23 + return req->__ctx; 24 + } 25 + 26 + static inline void *kpp_tfm_ctx(struct crypto_kpp *tfm) 27 + { 28 + return tfm->base.__crt_ctx; 29 + } 30 + 31 + static inline void kpp_request_complete(struct kpp_request *req, int err) 32 + { 33 + req->base.complete(&req->base, err); 34 + } 35 + 36 + static inline const char *kpp_alg_name(struct crypto_kpp *tfm) 37 + { 38 + return crypto_kpp_tfm(tfm)->__crt_alg->cra_name; 39 + } 40 + 41 + /** 42 + * crypto_register_kpp() -- Register key-agreement protocol primitives algorithm 43 + * 44 + * Function registers an implementation of a key-agreement protocol primitive 45 + * algorithm 46 + * 47 + * @alg: algorithm definition 48 + * 49 + * Return: zero on success; error code in case of error 50 + */ 51 + int crypto_register_kpp(struct kpp_alg *alg); 52 + 53 + /** 54 + * crypto_unregister_kpp() -- Unregister key-agreement protocol primitive 55 + * algorithm 56 + * 57 + * Function unregisters an implementation of a key-agreement protocol primitive 58 + * algorithm 59 + * 60 + * @alg: algorithm definition 61 + */ 62 + void crypto_unregister_kpp(struct kpp_alg *alg); 63 + 64 + #endif
+328
include/crypto/kpp.h
··· 1 + /* 2 + * Key-agreement Protocol Primitives (KPP) 3 + * 4 + * Copyright (c) 2016, Intel Corporation 5 + * Authors: Salvatore Benedetto <salvatore.benedetto@intel.com> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License as published by the Free 9 + * Software Foundation; either version 2 of the License, or (at your option) 10 + * any later version. 11 + * 12 + */ 13 + 14 + #ifndef _CRYPTO_KPP_ 15 + #define _CRYPTO_KPP_ 16 + #include <linux/crypto.h> 17 + 18 + /** 19 + * struct kpp_request 20 + * 21 + * @base: Common attributes for async crypto requests 22 + * @src: Source data 23 + * @dst: Destination data 24 + * @src_len: Size of the input buffer 25 + * @dst_len: Size of the output buffer. It needs to be at least 26 + * as big as the expected result depending on the operation 27 + * After operation it will be updated with the actual size of the 28 + * result. In case of error where the dst sgl size was insufficient, 29 + * it will be updated to the size required for the operation. 30 + * @__ctx: Start of private context data 31 + */ 32 + struct kpp_request { 33 + struct crypto_async_request base; 34 + struct scatterlist *src; 35 + struct scatterlist *dst; 36 + unsigned int src_len; 37 + unsigned int dst_len; 38 + void *__ctx[] CRYPTO_MINALIGN_ATTR; 39 + }; 40 + 41 + /** 42 + * struct crypto_kpp - user-instantiated object which encapsulate 43 + * algorithms and core processing logic 44 + * 45 + * @base: Common crypto API algorithm data structure 46 + */ 47 + struct crypto_kpp { 48 + struct crypto_tfm base; 49 + }; 50 + 51 + /** 52 + * struct kpp_alg - generic key-agreement protocol primitives 53 + * 54 + * @set_secret: Function invokes the protocol specific function to 55 + * store the secret private key along with parameters. 56 + * The implementation knows how to decode thie buffer 57 + * @generate_public_key: Function generate the public key to be sent to the 58 + * counterpart. In case of error, where output is not big 59 + * enough req->dst_len will be updated to the size 60 + * required 61 + * @compute_shared_secret: Function compute the shared secret as defined by 62 + * the algorithm. The result is given back to the user. 63 + * In case of error, where output is not big enough, 64 + * req->dst_len will be updated to the size required 65 + * @max_size: Function returns the size of the output buffer 66 + * @init: Initialize the object. This is called only once at 67 + * instantiation time. In case the cryptographic hardware 68 + * needs to be initialized. Software fallback should be 69 + * put in place here. 70 + * @exit: Undo everything @init did. 71 + * 72 + * @reqsize: Request context size required by algorithm 73 + * implementation 74 + * @base Common crypto API algorithm data structure 75 + */ 76 + struct kpp_alg { 77 + int (*set_secret)(struct crypto_kpp *tfm, void *buffer, 78 + unsigned int len); 79 + int (*generate_public_key)(struct kpp_request *req); 80 + int (*compute_shared_secret)(struct kpp_request *req); 81 + 82 + int (*max_size)(struct crypto_kpp *tfm); 83 + 84 + int (*init)(struct crypto_kpp *tfm); 85 + void (*exit)(struct crypto_kpp *tfm); 86 + 87 + unsigned int reqsize; 88 + struct crypto_alg base; 89 + }; 90 + 91 + /** 92 + * DOC: Generic Key-agreement Protocol Primitevs API 93 + * 94 + * The KPP API is used with the algorithm type 95 + * CRYPTO_ALG_TYPE_KPP (listed as type "kpp" in /proc/crypto) 96 + */ 97 + 98 + /** 99 + * crypto_alloc_kpp() - allocate KPP tfm handle 100 + * @alg_name: is the name of the kpp algorithm (e.g. "dh", "ecdh") 101 + * @type: specifies the type of the algorithm 102 + * @mask: specifies the mask for the algorithm 103 + * 104 + * Allocate a handle for kpp algorithm. The returned struct crypto_kpp 105 + * is requeried for any following API invocation 106 + * 107 + * Return: allocated handle in case of success; IS_ERR() is true in case of 108 + * an error, PTR_ERR() returns the error code. 109 + */ 110 + struct crypto_kpp *crypto_alloc_kpp(const char *alg_name, u32 type, u32 mask); 111 + 112 + static inline struct crypto_tfm *crypto_kpp_tfm(struct crypto_kpp *tfm) 113 + { 114 + return &tfm->base; 115 + } 116 + 117 + static inline struct kpp_alg *__crypto_kpp_alg(struct crypto_alg *alg) 118 + { 119 + return container_of(alg, struct kpp_alg, base); 120 + } 121 + 122 + static inline struct crypto_kpp *__crypto_kpp_tfm(struct crypto_tfm *tfm) 123 + { 124 + return container_of(tfm, struct crypto_kpp, base); 125 + } 126 + 127 + static inline struct kpp_alg *crypto_kpp_alg(struct crypto_kpp *tfm) 128 + { 129 + return __crypto_kpp_alg(crypto_kpp_tfm(tfm)->__crt_alg); 130 + } 131 + 132 + static inline unsigned int crypto_kpp_reqsize(struct crypto_kpp *tfm) 133 + { 134 + return crypto_kpp_alg(tfm)->reqsize; 135 + } 136 + 137 + static inline void kpp_request_set_tfm(struct kpp_request *req, 138 + struct crypto_kpp *tfm) 139 + { 140 + req->base.tfm = crypto_kpp_tfm(tfm); 141 + } 142 + 143 + static inline struct crypto_kpp *crypto_kpp_reqtfm(struct kpp_request *req) 144 + { 145 + return __crypto_kpp_tfm(req->base.tfm); 146 + } 147 + 148 + /** 149 + * crypto_free_kpp() - free KPP tfm handle 150 + * 151 + * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() 152 + */ 153 + static inline void crypto_free_kpp(struct crypto_kpp *tfm) 154 + { 155 + crypto_destroy_tfm(tfm, crypto_kpp_tfm(tfm)); 156 + } 157 + 158 + /** 159 + * kpp_request_alloc() - allocates kpp request 160 + * 161 + * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() 162 + * @gfp: allocation flags 163 + * 164 + * Return: allocated handle in case of success or NULL in case of an error. 165 + */ 166 + static inline struct kpp_request *kpp_request_alloc(struct crypto_kpp *tfm, 167 + gfp_t gfp) 168 + { 169 + struct kpp_request *req; 170 + 171 + req = kmalloc(sizeof(*req) + crypto_kpp_reqsize(tfm), gfp); 172 + if (likely(req)) 173 + kpp_request_set_tfm(req, tfm); 174 + 175 + return req; 176 + } 177 + 178 + /** 179 + * kpp_request_free() - zeroize and free kpp request 180 + * 181 + * @req: request to free 182 + */ 183 + static inline void kpp_request_free(struct kpp_request *req) 184 + { 185 + kzfree(req); 186 + } 187 + 188 + /** 189 + * kpp_request_set_callback() - Sets an asynchronous callback. 190 + * 191 + * Callback will be called when an asynchronous operation on a given 192 + * request is finished. 193 + * 194 + * @req: request that the callback will be set for 195 + * @flgs: specify for instance if the operation may backlog 196 + * @cmpl: callback which will be called 197 + * @data: private data used by the caller 198 + */ 199 + static inline void kpp_request_set_callback(struct kpp_request *req, 200 + u32 flgs, 201 + crypto_completion_t cmpl, 202 + void *data) 203 + { 204 + req->base.complete = cmpl; 205 + req->base.data = data; 206 + req->base.flags = flgs; 207 + } 208 + 209 + /** 210 + * kpp_request_set_input() - Sets input buffer 211 + * 212 + * Sets parameters required by generate_public_key 213 + * 214 + * @req: kpp request 215 + * @input: ptr to input scatter list 216 + * @input_len: size of the input scatter list 217 + */ 218 + static inline void kpp_request_set_input(struct kpp_request *req, 219 + struct scatterlist *input, 220 + unsigned int input_len) 221 + { 222 + req->src = input; 223 + req->src_len = input_len; 224 + } 225 + 226 + /** 227 + * kpp_request_set_output() - Sets output buffer 228 + * 229 + * Sets parameters required by kpp operation 230 + * 231 + * @req: kpp request 232 + * @output: ptr to output scatter list 233 + * @output_len: size of the output scatter list 234 + */ 235 + static inline void kpp_request_set_output(struct kpp_request *req, 236 + struct scatterlist *output, 237 + unsigned int output_len) 238 + { 239 + req->dst = output; 240 + req->dst_len = output_len; 241 + } 242 + 243 + enum { 244 + CRYPTO_KPP_SECRET_TYPE_UNKNOWN, 245 + }; 246 + 247 + /** 248 + * struct kpp_secret - small header for packing secret buffer 249 + * 250 + * @type: define type of secret. Each kpp type will define its own 251 + * @len: specify the len of the secret, include the header, that 252 + * follows the struct 253 + */ 254 + struct kpp_secret { 255 + unsigned short type; 256 + unsigned short len; 257 + }; 258 + 259 + /** 260 + * crypto_kpp_set_secret() - Invoke kpp operation 261 + * 262 + * Function invokes the specific kpp operation for a given alg. 263 + * 264 + * @tfm: tfm handle 265 + * 266 + * Return: zero on success; error code in case of error 267 + */ 268 + static inline int crypto_kpp_set_secret(struct crypto_kpp *tfm, void *buffer, 269 + unsigned int len) 270 + { 271 + struct kpp_alg *alg = crypto_kpp_alg(tfm); 272 + 273 + return alg->set_secret(tfm, buffer, len); 274 + } 275 + 276 + /** 277 + * crypto_kpp_generate_public_key() - Invoke kpp operation 278 + * 279 + * Function invokes the specific kpp operation for generating the public part 280 + * for a given kpp algorithm 281 + * 282 + * @req: kpp key request 283 + * 284 + * Return: zero on success; error code in case of error 285 + */ 286 + static inline int crypto_kpp_generate_public_key(struct kpp_request *req) 287 + { 288 + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 289 + struct kpp_alg *alg = crypto_kpp_alg(tfm); 290 + 291 + return alg->generate_public_key(req); 292 + } 293 + 294 + /** 295 + * crypto_kpp_compute_shared_secret() - Invoke kpp operation 296 + * 297 + * Function invokes the specific kpp operation for computing the shared secret 298 + * for a given kpp algorithm. 299 + * 300 + * @req: kpp key request 301 + * 302 + * Return: zero on success; error code in case of error 303 + */ 304 + static inline int crypto_kpp_compute_shared_secret(struct kpp_request *req) 305 + { 306 + struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 307 + struct kpp_alg *alg = crypto_kpp_alg(tfm); 308 + 309 + return alg->compute_shared_secret(req); 310 + } 311 + 312 + /** 313 + * crypto_kpp_maxsize() - Get len for output buffer 314 + * 315 + * Function returns the output buffer size required 316 + * 317 + * @tfm: KPP tfm handle allocated with crypto_alloc_kpp() 318 + * 319 + * Return: minimum len for output buffer or error code if key hasn't been set 320 + */ 321 + static inline int crypto_kpp_maxsize(struct crypto_kpp *tfm) 322 + { 323 + struct kpp_alg *alg = crypto_kpp_alg(tfm); 324 + 325 + return alg->max_size(tfm); 326 + } 327 + 328 + #endif
+1
include/linux/crypto.h
··· 48 48 #define CRYPTO_ALG_TYPE_BLKCIPHER 0x00000004 49 49 #define CRYPTO_ALG_TYPE_ABLKCIPHER 0x00000005 50 50 #define CRYPTO_ALG_TYPE_GIVCIPHER 0x00000006 51 + #define CRYPTO_ALG_TYPE_KPP 0x00000008 51 52 #define CRYPTO_ALG_TYPE_RNG 0x0000000c 52 53 #define CRYPTO_ALG_TYPE_AKCIPHER 0x0000000d 53 54 #define CRYPTO_ALG_TYPE_DIGEST 0x0000000e
+5
include/uapi/linux/cryptouser.h
··· 45 45 CRYPTOCFGA_REPORT_RNG, /* struct crypto_report_rng */ 46 46 CRYPTOCFGA_REPORT_CIPHER, /* struct crypto_report_cipher */ 47 47 CRYPTOCFGA_REPORT_AKCIPHER, /* struct crypto_report_akcipher */ 48 + CRYPTOCFGA_REPORT_KPP, /* struct crypto_report_kpp */ 48 49 __CRYPTOCFGA_MAX 49 50 50 51 #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) ··· 105 104 }; 106 105 107 106 struct crypto_report_akcipher { 107 + char type[CRYPTO_MAX_NAME]; 108 + }; 109 + 110 + struct crypto_report_kpp { 108 111 char type[CRYPTO_MAX_NAME]; 109 112 }; 110 113