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

crypto: sig - Introduce sig_alg backend

Commit 6cb8815f41a9 ("crypto: sig - Add interface for sign/verify")
began a transition of asymmetric sign/verify operations from
crypto_akcipher to a new crypto_sig frontend.

Internally, the crypto_sig frontend still uses akcipher_alg as backend,
however:

"The link between sig and akcipher is meant to be temporary. The
plan is to create a new low-level API for sig and then migrate
the signature code over to that from akcipher."
https://lore.kernel.org/r/ZrG6w9wsb-iiLZIF@gondor.apana.org.au/

"having a separate alg for sig is definitely where we want to
be since there is very little that the two types actually share."
https://lore.kernel.org/r/ZrHlpz4qnre0zWJO@gondor.apana.org.au/

Take the next step of that migration and augment the crypto_sig frontend
with a sig_alg backend to which all algorithms can be moved.

During the migration, there will briefly be signature algorithms that
are still based on crypto_akcipher, whilst others are already based on
crypto_sig. Allow for that by building a fork into crypto_sig_*() API
calls (i.e. crypto_sig_maxsize() and friends) such that one of the two
backends is selected based on the transform's cra_type.

Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Lukas Wunner and committed by
Herbert Xu
65c4c93c beea3201

+432 -2
+14
Documentation/crypto/api-sig.rst
··· 1 + Asymmetric Signature Algorithm Definitions 2 + ------------------------------------------ 3 + 4 + .. kernel-doc:: include/crypto/sig.h 5 + :functions: sig_alg 6 + 7 + Asymmetric Signature API 8 + ------------------------ 9 + 10 + .. kernel-doc:: include/crypto/sig.h 11 + :doc: Generic Public Key Signature API 12 + 13 + .. kernel-doc:: include/crypto/sig.h 14 + :functions: crypto_alloc_sig crypto_free_sig crypto_sig_set_pubkey crypto_sig_set_privkey crypto_sig_maxsize crypto_sig_sign crypto_sig_verify
+1
Documentation/crypto/api.rst
··· 10 10 api-digest 11 11 api-rng 12 12 api-akcipher 13 + api-sig 13 14 api-kpp
+2
Documentation/crypto/architecture.rst
··· 214 214 215 215 - CRYPTO_ALG_TYPE_AKCIPHER Asymmetric cipher 216 216 217 + - CRYPTO_ALG_TYPE_SIG Asymmetric signature 218 + 217 219 - CRYPTO_ALG_TYPE_PCOMPRESS Enhanced version of 218 220 CRYPTO_ALG_TYPE_COMPRESS allowing for segmented compression / 219 221 decompression instead of performing the operation on one segment
+141 -2
crypto/sig.c
··· 21 21 22 22 static const struct crypto_type crypto_sig_type; 23 23 24 + static void crypto_sig_exit_tfm(struct crypto_tfm *tfm) 25 + { 26 + struct crypto_sig *sig = __crypto_sig_tfm(tfm); 27 + struct sig_alg *alg = crypto_sig_alg(sig); 28 + 29 + alg->exit(sig); 30 + } 31 + 24 32 static int crypto_sig_init_tfm(struct crypto_tfm *tfm) 25 33 { 26 34 if (tfm->__crt_alg->cra_type != &crypto_sig_type) 27 35 return crypto_init_akcipher_ops_sig(tfm); 28 36 37 + struct crypto_sig *sig = __crypto_sig_tfm(tfm); 38 + struct sig_alg *alg = crypto_sig_alg(sig); 39 + 40 + if (alg->exit) 41 + sig->base.exit = crypto_sig_exit_tfm; 42 + 43 + if (alg->init) 44 + return alg->init(sig); 45 + 29 46 return 0; 47 + } 48 + 49 + static void crypto_sig_free_instance(struct crypto_instance *inst) 50 + { 51 + struct sig_instance *sig = sig_instance(inst); 52 + 53 + sig->free(sig); 30 54 } 31 55 32 56 static void __maybe_unused crypto_sig_show(struct seq_file *m, ··· 62 38 static int __maybe_unused crypto_sig_report(struct sk_buff *skb, 63 39 struct crypto_alg *alg) 64 40 { 65 - struct crypto_report_akcipher rsig = {}; 41 + struct crypto_report_sig rsig = {}; 66 42 67 43 strscpy(rsig.type, "sig", sizeof(rsig.type)); 68 44 69 - return nla_put(skb, CRYPTOCFGA_REPORT_AKCIPHER, sizeof(rsig), &rsig); 45 + return nla_put(skb, CRYPTOCFGA_REPORT_SIG, sizeof(rsig), &rsig); 70 46 } 71 47 72 48 static const struct crypto_type crypto_sig_type = { 73 49 .extsize = crypto_alg_extsize, 74 50 .init_tfm = crypto_sig_init_tfm, 51 + .free = crypto_sig_free_instance, 75 52 #ifdef CONFIG_PROC_FS 76 53 .show = crypto_sig_show, 77 54 #endif ··· 93 68 94 69 int crypto_sig_maxsize(struct crypto_sig *tfm) 95 70 { 71 + if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type) 72 + goto akcipher; 73 + 74 + struct sig_alg *alg = crypto_sig_alg(tfm); 75 + 76 + return alg->max_size(tfm); 77 + 78 + akcipher: 96 79 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 97 80 98 81 return crypto_akcipher_maxsize(*ctx); ··· 111 78 const void *src, unsigned int slen, 112 79 void *dst, unsigned int dlen) 113 80 { 81 + if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type) 82 + goto akcipher; 83 + 84 + struct sig_alg *alg = crypto_sig_alg(tfm); 85 + 86 + return alg->sign(tfm, src, slen, dst, dlen); 87 + 88 + akcipher: 114 89 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 115 90 struct crypto_akcipher_sync_data data = { 116 91 .tfm = *ctx, ··· 138 97 const void *src, unsigned int slen, 139 98 const void *digest, unsigned int dlen) 140 99 { 100 + if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type) 101 + goto akcipher; 102 + 103 + struct sig_alg *alg = crypto_sig_alg(tfm); 104 + 105 + return alg->verify(tfm, src, slen, digest, dlen); 106 + 107 + akcipher: 141 108 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 142 109 struct crypto_akcipher_sync_data data = { 143 110 .tfm = *ctx, ··· 169 120 int crypto_sig_set_pubkey(struct crypto_sig *tfm, 170 121 const void *key, unsigned int keylen) 171 122 { 123 + if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type) 124 + goto akcipher; 125 + 126 + struct sig_alg *alg = crypto_sig_alg(tfm); 127 + 128 + return alg->set_pub_key(tfm, key, keylen); 129 + 130 + akcipher: 172 131 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 173 132 174 133 return crypto_akcipher_set_pub_key(*ctx, key, keylen); ··· 186 129 int crypto_sig_set_privkey(struct crypto_sig *tfm, 187 130 const void *key, unsigned int keylen) 188 131 { 132 + if (crypto_sig_tfm(tfm)->__crt_alg->cra_type != &crypto_sig_type) 133 + goto akcipher; 134 + 135 + struct sig_alg *alg = crypto_sig_alg(tfm); 136 + 137 + return alg->set_priv_key(tfm, key, keylen); 138 + 139 + akcipher: 189 140 struct crypto_akcipher **ctx = crypto_sig_ctx(tfm); 190 141 191 142 return crypto_akcipher_set_priv_key(*ctx, key, keylen); 192 143 } 193 144 EXPORT_SYMBOL_GPL(crypto_sig_set_privkey); 145 + 146 + static void sig_prepare_alg(struct sig_alg *alg) 147 + { 148 + struct crypto_alg *base = &alg->base; 149 + 150 + base->cra_type = &crypto_sig_type; 151 + base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; 152 + base->cra_flags |= CRYPTO_ALG_TYPE_SIG; 153 + } 154 + 155 + static int sig_default_sign(struct crypto_sig *tfm, 156 + const void *src, unsigned int slen, 157 + void *dst, unsigned int dlen) 158 + { 159 + return -ENOSYS; 160 + } 161 + 162 + static int sig_default_verify(struct crypto_sig *tfm, 163 + const void *src, unsigned int slen, 164 + const void *dst, unsigned int dlen) 165 + { 166 + return -ENOSYS; 167 + } 168 + 169 + static int sig_default_set_key(struct crypto_sig *tfm, 170 + const void *key, unsigned int keylen) 171 + { 172 + return -ENOSYS; 173 + } 174 + 175 + int crypto_register_sig(struct sig_alg *alg) 176 + { 177 + struct crypto_alg *base = &alg->base; 178 + 179 + if (!alg->sign) 180 + alg->sign = sig_default_sign; 181 + if (!alg->verify) 182 + alg->verify = sig_default_verify; 183 + if (!alg->set_priv_key) 184 + alg->set_priv_key = sig_default_set_key; 185 + if (!alg->set_pub_key) 186 + return -EINVAL; 187 + if (!alg->max_size) 188 + return -EINVAL; 189 + 190 + sig_prepare_alg(alg); 191 + return crypto_register_alg(base); 192 + } 193 + EXPORT_SYMBOL_GPL(crypto_register_sig); 194 + 195 + void crypto_unregister_sig(struct sig_alg *alg) 196 + { 197 + crypto_unregister_alg(&alg->base); 198 + } 199 + EXPORT_SYMBOL_GPL(crypto_unregister_sig); 200 + 201 + int sig_register_instance(struct crypto_template *tmpl, 202 + struct sig_instance *inst) 203 + { 204 + if (WARN_ON(!inst->free)) 205 + return -EINVAL; 206 + sig_prepare_alg(&inst->alg); 207 + return crypto_register_instance(tmpl, sig_crypto_instance(inst)); 208 + } 209 + EXPORT_SYMBOL_GPL(sig_register_instance); 210 + 211 + int crypto_grab_sig(struct crypto_sig_spawn *spawn, 212 + struct crypto_instance *inst, 213 + const char *name, u32 type, u32 mask) 214 + { 215 + spawn->base.frontend = &crypto_sig_type; 216 + return crypto_grab_spawn(&spawn->base, inst, name, type, mask); 217 + } 218 + EXPORT_SYMBOL_GPL(crypto_grab_sig); 194 219 195 220 MODULE_LICENSE("GPL"); 196 221 MODULE_DESCRIPTION("Public Key Signature Algorithms");
+115
crypto/testmgr.c
··· 33 33 #include <crypto/akcipher.h> 34 34 #include <crypto/kpp.h> 35 35 #include <crypto/acompress.h> 36 + #include <crypto/sig.h> 36 37 #include <crypto/internal/cipher.h> 37 38 #include <crypto/internal/simd.h> 38 39 ··· 132 131 unsigned int count; 133 132 }; 134 133 134 + struct sig_test_suite { 135 + const struct sig_testvec *vecs; 136 + unsigned int count; 137 + }; 138 + 135 139 struct kpp_test_suite { 136 140 const struct kpp_testvec *vecs; 137 141 unsigned int count; ··· 157 151 struct cprng_test_suite cprng; 158 152 struct drbg_test_suite drbg; 159 153 struct akcipher_test_suite akcipher; 154 + struct sig_test_suite sig; 160 155 struct kpp_test_suite kpp; 161 156 } suite; 162 157 }; ··· 4342 4335 desc->suite.akcipher.count); 4343 4336 4344 4337 crypto_free_akcipher(tfm); 4338 + return err; 4339 + } 4340 + 4341 + static int test_sig_one(struct crypto_sig *tfm, const struct sig_testvec *vecs) 4342 + { 4343 + u8 *ptr, *key __free(kfree); 4344 + int err, sig_size; 4345 + 4346 + key = kmalloc(vecs->key_len + 2 * sizeof(u32) + vecs->param_len, 4347 + GFP_KERNEL); 4348 + if (!key) 4349 + return -ENOMEM; 4350 + 4351 + /* ecrdsa expects additional parameters appended to the key */ 4352 + memcpy(key, vecs->key, vecs->key_len); 4353 + ptr = key + vecs->key_len; 4354 + ptr = test_pack_u32(ptr, vecs->algo); 4355 + ptr = test_pack_u32(ptr, vecs->param_len); 4356 + memcpy(ptr, vecs->params, vecs->param_len); 4357 + 4358 + if (vecs->public_key_vec) 4359 + err = crypto_sig_set_pubkey(tfm, key, vecs->key_len); 4360 + else 4361 + err = crypto_sig_set_privkey(tfm, key, vecs->key_len); 4362 + if (err) 4363 + return err; 4364 + 4365 + /* 4366 + * Run asymmetric signature verification first 4367 + * (which does not require a private key) 4368 + */ 4369 + err = crypto_sig_verify(tfm, vecs->c, vecs->c_size, 4370 + vecs->m, vecs->m_size); 4371 + if (err) { 4372 + pr_err("alg: sig: verify test failed: err %d\n", err); 4373 + return err; 4374 + } 4375 + 4376 + /* 4377 + * Don't invoke sign test (which requires a private key) 4378 + * for vectors with only a public key. 4379 + */ 4380 + if (vecs->public_key_vec) 4381 + return 0; 4382 + 4383 + sig_size = crypto_sig_maxsize(tfm); 4384 + if (sig_size < vecs->c_size) { 4385 + pr_err("alg: sig: invalid maxsize %u\n", sig_size); 4386 + return -EINVAL; 4387 + } 4388 + 4389 + u8 *sig __free(kfree) = kzalloc(sig_size, GFP_KERNEL); 4390 + if (!sig) 4391 + return -ENOMEM; 4392 + 4393 + /* Run asymmetric signature generation */ 4394 + err = crypto_sig_sign(tfm, vecs->m, vecs->m_size, sig, sig_size); 4395 + if (err) { 4396 + pr_err("alg: sig: sign test failed: err %d\n", err); 4397 + return err; 4398 + } 4399 + 4400 + /* Verify that generated signature equals cooked signature */ 4401 + if (memcmp(sig, vecs->c, vecs->c_size) || 4402 + memchr_inv(sig + vecs->c_size, 0, sig_size - vecs->c_size)) { 4403 + pr_err("alg: sig: sign test failed: invalid output\n"); 4404 + hexdump(sig, sig_size); 4405 + return -EINVAL; 4406 + } 4407 + 4408 + return 0; 4409 + } 4410 + 4411 + static int test_sig(struct crypto_sig *tfm, const char *alg, 4412 + const struct sig_testvec *vecs, unsigned int tcount) 4413 + { 4414 + const char *algo = crypto_tfm_alg_driver_name(crypto_sig_tfm(tfm)); 4415 + int ret, i; 4416 + 4417 + for (i = 0; i < tcount; i++) { 4418 + ret = test_sig_one(tfm, vecs++); 4419 + if (ret) { 4420 + pr_err("alg: sig: test %d failed for %s: err %d\n", 4421 + i + 1, algo, ret); 4422 + return ret; 4423 + } 4424 + } 4425 + return 0; 4426 + } 4427 + 4428 + __maybe_unused 4429 + static int alg_test_sig(const struct alg_test_desc *desc, const char *driver, 4430 + u32 type, u32 mask) 4431 + { 4432 + struct crypto_sig *tfm; 4433 + int err = 0; 4434 + 4435 + tfm = crypto_alloc_sig(driver, type, mask); 4436 + if (IS_ERR(tfm)) { 4437 + pr_err("alg: sig: Failed to load tfm for %s: %ld\n", 4438 + driver, PTR_ERR(tfm)); 4439 + return PTR_ERR(tfm); 4440 + } 4441 + if (desc->suite.sig.vecs) 4442 + err = test_sig(tfm, desc->alg, desc->suite.sig.vecs, 4443 + desc->suite.sig.count); 4444 + 4445 + crypto_free_sig(tfm); 4345 4446 return err; 4346 4447 } 4347 4448
+13
crypto/testmgr.h
··· 162 162 enum OID algo; 163 163 }; 164 164 165 + struct sig_testvec { 166 + const unsigned char *key; 167 + const unsigned char *params; 168 + const unsigned char *m; 169 + const unsigned char *c; 170 + unsigned int key_len; 171 + unsigned int param_len; 172 + unsigned int m_size; 173 + unsigned int c_size; 174 + bool public_key_vec; 175 + enum OID algo; 176 + }; 177 + 165 178 struct kpp_testvec { 166 179 const unsigned char *secret; 167 180 const unsigned char *b_secret;
+80
include/crypto/internal/sig.h
··· 10 10 #include <crypto/algapi.h> 11 11 #include <crypto/sig.h> 12 12 13 + struct sig_instance { 14 + void (*free)(struct sig_instance *inst); 15 + union { 16 + struct { 17 + char head[offsetof(struct sig_alg, base)]; 18 + struct crypto_instance base; 19 + }; 20 + struct sig_alg alg; 21 + }; 22 + }; 23 + 24 + struct crypto_sig_spawn { 25 + struct crypto_spawn base; 26 + }; 27 + 13 28 static inline void *crypto_sig_ctx(struct crypto_sig *tfm) 14 29 { 15 30 return crypto_tfm_ctx(&tfm->base); 31 + } 32 + 33 + /** 34 + * crypto_register_sig() -- Register public key signature algorithm 35 + * 36 + * Function registers an implementation of a public key signature algorithm 37 + * 38 + * @alg: algorithm definition 39 + * 40 + * Return: zero on success; error code in case of error 41 + */ 42 + int crypto_register_sig(struct sig_alg *alg); 43 + 44 + /** 45 + * crypto_unregister_sig() -- Unregister public key signature algorithm 46 + * 47 + * Function unregisters an implementation of a public key signature algorithm 48 + * 49 + * @alg: algorithm definition 50 + */ 51 + void crypto_unregister_sig(struct sig_alg *alg); 52 + 53 + int sig_register_instance(struct crypto_template *tmpl, 54 + struct sig_instance *inst); 55 + 56 + static inline struct sig_instance *sig_instance(struct crypto_instance *inst) 57 + { 58 + return container_of(&inst->alg, struct sig_instance, alg.base); 59 + } 60 + 61 + static inline struct sig_instance *sig_alg_instance(struct crypto_sig *tfm) 62 + { 63 + return sig_instance(crypto_tfm_alg_instance(&tfm->base)); 64 + } 65 + 66 + static inline struct crypto_instance *sig_crypto_instance(struct sig_instance 67 + *inst) 68 + { 69 + return container_of(&inst->alg.base, struct crypto_instance, alg); 70 + } 71 + 72 + static inline void *sig_instance_ctx(struct sig_instance *inst) 73 + { 74 + return crypto_instance_ctx(sig_crypto_instance(inst)); 75 + } 76 + 77 + int crypto_grab_sig(struct crypto_sig_spawn *spawn, 78 + struct crypto_instance *inst, 79 + const char *name, u32 type, u32 mask); 80 + 81 + static inline struct crypto_sig *crypto_spawn_sig(struct crypto_sig_spawn 82 + *spawn) 83 + { 84 + return crypto_spawn_tfm2(&spawn->base); 85 + } 86 + 87 + static inline void crypto_drop_sig(struct crypto_sig_spawn *spawn) 88 + { 89 + crypto_drop_spawn(&spawn->base); 90 + } 91 + 92 + static inline struct sig_alg *crypto_spawn_sig_alg(struct crypto_sig_spawn 93 + *spawn) 94 + { 95 + return container_of(spawn->base.alg, struct sig_alg, base); 16 96 } 17 97 #endif
+61
include/crypto/sig.h
··· 20 20 }; 21 21 22 22 /** 23 + * struct sig_alg - generic public key signature algorithm 24 + * 25 + * @sign: Function performs a sign operation as defined by public key 26 + * algorithm. Optional. 27 + * @verify: Function performs a complete verify operation as defined by 28 + * public key algorithm, returning verification status. Optional. 29 + * @set_pub_key: Function invokes the algorithm specific set public key 30 + * function, which knows how to decode and interpret 31 + * the BER encoded public key and parameters. Mandatory. 32 + * @set_priv_key: Function invokes the algorithm specific set private key 33 + * function, which knows how to decode and interpret 34 + * the BER encoded private key and parameters. Optional. 35 + * @max_size: Function returns key size. Mandatory. 36 + * @init: Initialize the cryptographic transformation object. 37 + * This function is used to initialize the cryptographic 38 + * transformation object. This function is called only once at 39 + * the instantiation time, right after the transformation context 40 + * was allocated. In case the cryptographic hardware has some 41 + * special requirements which need to be handled by software, this 42 + * function shall check for the precise requirement of the 43 + * transformation and put any software fallbacks in place. 44 + * @exit: Deinitialize the cryptographic transformation object. This is a 45 + * counterpart to @init, used to remove various changes set in 46 + * @init. 47 + * 48 + * @base: Common crypto API algorithm data structure 49 + */ 50 + struct sig_alg { 51 + int (*sign)(struct crypto_sig *tfm, 52 + const void *src, unsigned int slen, 53 + void *dst, unsigned int dlen); 54 + int (*verify)(struct crypto_sig *tfm, 55 + const void *src, unsigned int slen, 56 + const void *digest, unsigned int dlen); 57 + int (*set_pub_key)(struct crypto_sig *tfm, 58 + const void *key, unsigned int keylen); 59 + int (*set_priv_key)(struct crypto_sig *tfm, 60 + const void *key, unsigned int keylen); 61 + unsigned int (*max_size)(struct crypto_sig *tfm); 62 + int (*init)(struct crypto_sig *tfm); 63 + void (*exit)(struct crypto_sig *tfm); 64 + 65 + struct crypto_alg base; 66 + }; 67 + 68 + /** 23 69 * DOC: Generic Public Key Signature API 24 70 * 25 71 * The Public Key Signature API is used with the algorithms of type ··· 91 45 static inline struct crypto_tfm *crypto_sig_tfm(struct crypto_sig *tfm) 92 46 { 93 47 return &tfm->base; 48 + } 49 + 50 + static inline struct crypto_sig *__crypto_sig_tfm(struct crypto_tfm *tfm) 51 + { 52 + return container_of(tfm, struct crypto_sig, base); 53 + } 54 + 55 + static inline struct sig_alg *__crypto_sig_alg(struct crypto_alg *alg) 56 + { 57 + return container_of(alg, struct sig_alg, base); 58 + } 59 + 60 + static inline struct sig_alg *crypto_sig_alg(struct crypto_sig *tfm) 61 + { 62 + return __crypto_sig_alg(crypto_sig_tfm(tfm)->__crt_alg); 94 63 } 95 64 96 65 /**
+5
include/uapi/linux/cryptouser.h
··· 64 64 CRYPTOCFGA_STAT_AKCIPHER, /* No longer supported, do not use. */ 65 65 CRYPTOCFGA_STAT_KPP, /* No longer supported, do not use. */ 66 66 CRYPTOCFGA_STAT_ACOMP, /* No longer supported, do not use. */ 67 + CRYPTOCFGA_REPORT_SIG, /* struct crypto_report_sig */ 67 68 __CRYPTOCFGA_MAX 68 69 69 70 #define CRYPTOCFGA_MAX (__CRYPTOCFGA_MAX - 1) ··· 205 204 }; 206 205 207 206 struct crypto_report_acomp { 207 + char type[CRYPTO_MAX_NAME]; 208 + }; 209 + 210 + struct crypto_report_sig { 208 211 char type[CRYPTO_MAX_NAME]; 209 212 }; 210 213