From 1dbb920e342cab987186ad8ed6eac9c1cf710db7 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Thu, 30 Jul 2020 22:39:13 +1000 Subject: crypto: algapi - Move crypto_yield into internal.h This patch moves crypto_yield into internal.h as it's only used by internal code such as skcipher. It also adds a missing inclusion of sched.h which is required for cond_resched. The header files in internal.h have been cleaned up to remove some ancient junk and add some more specific inclusions. Signed-off-by: Herbert Xu --- crypto/internal.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'crypto') diff --git a/crypto/internal.h b/crypto/internal.h index 1b92a5a61852..976ec9dfc76d 100644 --- a/crypto/internal.h +++ b/crypto/internal.h @@ -10,16 +10,14 @@ #include #include -#include -#include -#include -#include #include #include -#include #include +#include +#include #include -#include +#include +#include struct crypto_instance; struct crypto_template; @@ -140,5 +138,11 @@ static inline void crypto_notify(unsigned long val, void *v) blocking_notifier_call_chain(&crypto_chain, val, v); } +static inline void crypto_yield(u32 flags) +{ + if (flags & CRYPTO_TFM_REQ_MAY_SLEEP) + cond_resched(); +} + #endif /* _CRYPTO_INTERNAL_H */ -- cgit v1.2.3 From 0c3dc787a62aef3ca7aedf3797ec42fff9b0a913 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 19 Aug 2020 21:58:20 +1000 Subject: crypto: algapi - Remove skbuff.h inclusion The header file algapi.h includes skbuff.h unnecessarily since all we need is a forward declaration for struct sk_buff. This patch removes that inclusion. Unfortunately skbuff.h pulls in a lot of things and drivers over the years have come to rely on it so this patch adds a lot of missing inclusions that result from this. Signed-off-by: Herbert Xu --- crypto/crypto_engine.c | 1 + crypto/ecrdsa.c | 1 + crypto/jitterentropy-kcapi.c | 2 +- crypto/rsa-pkcs1pad.c | 1 + crypto/testmgr.c | 1 + 5 files changed, 5 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c index 198a8eb1cd56..d2ec3ff9bc1e 100644 --- a/crypto/crypto_engine.c +++ b/crypto/crypto_engine.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include "internal.h" diff --git a/crypto/ecrdsa.c b/crypto/ecrdsa.c index 887ec21aee49..6a3fd09057d0 100644 --- a/crypto/ecrdsa.c +++ b/crypto/ecrdsa.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "ecrdsa_params.asn1.h" #include "ecrdsa_pub_key.asn1.h" #include "ecc.h" diff --git a/crypto/jitterentropy-kcapi.c b/crypto/jitterentropy-kcapi.c index eb7d1dd506bf..e8a4165a1874 100644 --- a/crypto/jitterentropy-kcapi.c +++ b/crypto/jitterentropy-kcapi.c @@ -37,11 +37,11 @@ * DAMAGE. */ +#include #include #include #include #include -#include #include #include "jitterentropy.h" diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c index ddd3d10ffc15..8ac3e73e8ea6 100644 --- a/crypto/rsa-pkcs1pad.c +++ b/crypto/rsa-pkcs1pad.c @@ -14,6 +14,7 @@ #include #include #include +#include /* * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 23c27fc96394..66ee3bbc9872 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 4eb57bcd4c6230cde9dda61f1d43c38f58670d94 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Jul 2020 19:39:19 -0700 Subject: crypto: algif_aead - delete duplicated word Drop the doubled word "is". Signed-off-by: Randy Dunlap Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/algif_aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 21efa786f09c..54f2fb2c6535 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -120,7 +120,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* * Make sure sufficient data is present -- note, the same check is - * is also present in sendmsg/sendpage. The checks in sendpage/sendmsg + * also present in sendmsg/sendpage. The checks in sendpage/sendmsg * shall provide an information to the data sender that something is * wrong, but they are irrelevant to maintain the kernel integrity. * We need this check here too in case user space decides to not honor -- cgit v1.2.3 From 743b91507703f1ac9754f9de7a55504c13cac89a Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Jul 2020 19:39:21 -0700 Subject: crypto: crc32c_generic - delete and fix duplicated words Drop the doubled word "the". Change "at at" to "at a". Signed-off-by: Randy Dunlap Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/crc32c_generic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c index 7fa9b0788685..768614738541 100644 --- a/crypto/crc32c_generic.c +++ b/crypto/crc32c_generic.c @@ -15,7 +15,7 @@ * pages = {}, * month = {June}, *} - * Used by the iSCSI driver, possibly others, and derived from the + * Used by the iSCSI driver, possibly others, and derived from * the iscsi-crc.c module of the linux-iscsi driver at * http://linux-iscsi.sourceforge.net. * @@ -50,7 +50,7 @@ struct chksum_desc_ctx { }; /* - * Steps through buffer one byte at at time, calculates reflected + * Steps through buffer one byte at a time, calculates reflected * crc using table. */ -- cgit v1.2.3 From 71952d78e959cc28287a77a5636aa2601104406d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Jul 2020 19:39:22 -0700 Subject: crypto: crct10dif_generic - fix duplicated words Change the doubled word "at" to "at a". Signed-off-by: Randy Dunlap Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/crct10dif_generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/crct10dif_generic.c b/crypto/crct10dif_generic.c index d90c0070710e..e843982073bb 100644 --- a/crypto/crct10dif_generic.c +++ b/crypto/crct10dif_generic.c @@ -35,7 +35,7 @@ struct chksum_desc_ctx { }; /* - * Steps through buffer one byte at at time, calculates reflected + * Steps through buffer one byte at a time, calculates reflected * crc using table. */ -- cgit v1.2.3 From 40a3af45d264af3079e8d894ee42611c99dca4b7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Jul 2020 19:39:23 -0700 Subject: crypto: engine - delete duplicated word Drop the doubled word "a". Signed-off-by: Randy Dunlap Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/crypto_engine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c index d2ec3ff9bc1e..cff21f4e03e3 100644 --- a/crypto/crypto_engine.c +++ b/crypto/crypto_engine.c @@ -466,7 +466,7 @@ EXPORT_SYMBOL_GPL(crypto_engine_stop); * crypto-engine queue. * @dev: the device attached with one hardware engine * @retry_support: whether hardware has support for retry mechanism - * @cbk_do_batch: pointer to a callback function to be invoked when executing a + * @cbk_do_batch: pointer to a callback function to be invoked when executing * a batch of requests. * This has the form: * callback(struct crypto_engine *engine) -- cgit v1.2.3 From 129a4dba1b1ba9bb36c46209fc6379beb8926312 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 30 Jul 2020 19:39:24 -0700 Subject: crypto: tcrypt - delete duplicated words in messages Drop the doubled word "failed" in pr_err() messages. Signed-off-by: Randy Dunlap Cc: Herbert Xu Cc: "David S. Miller" Cc: linux-crypto@vger.kernel.org Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index ba0b7702f2e9..acc758728b73 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -398,7 +398,7 @@ static void test_mb_aead_speed(const char *algo, int enc, int secs, ret = do_one_aead_op(cur->req, ret); if (ret) { - pr_err("calculating auth failed failed (%d)\n", + pr_err("calculating auth failed (%d)\n", ret); break; } @@ -648,7 +648,7 @@ static void test_aead_speed(const char *algo, int enc, unsigned int secs, crypto_aead_encrypt(req)); if (ret) { - pr_err("calculating auth failed failed (%d)\n", + pr_err("calculating auth failed (%d)\n", ret); break; } -- cgit v1.2.3 From 2a05b029c1ee045b886ebf9efef9985ca23450de Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 31 Jul 2020 17:03:27 +1000 Subject: crypto: algif_skcipher - EBUSY on aio should be an error I removed the MAY_BACKLOG flag on the aio path a while ago but the error check still incorrectly interpreted EBUSY as success. This may cause the submitter to wait for a request that will never complete. Fixes: dad419970637 ("crypto: algif_skcipher - Do not set...") Signed-off-by: Herbert Xu --- crypto/algif_skcipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 478f3b8f5bd5..ee8890ee8f33 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -123,7 +123,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, crypto_skcipher_decrypt(&areq->cra_u.skcipher_req); /* AIO operation in progress */ - if (err == -EINPROGRESS || err == -EBUSY) + if (err == -EINPROGRESS) return -EIOCBQUEUED; sock_put(sk); -- cgit v1.2.3 From cbdad1f246dd98e6c9c32a6e5212337f542aa7e0 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 31 Jul 2020 17:03:50 +1000 Subject: crypto: algif_aead - Do not set MAY_BACKLOG on the async path The async path cannot use MAY_BACKLOG because it is not meant to block, which is what MAY_BACKLOG does. On the other hand, both the sync and async paths can make use of MAY_SLEEP. Fixes: 83094e5e9e49 ("crypto: af_alg - add async support to...") Cc: Signed-off-by: Herbert Xu --- crypto/algif_aead.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 54f2fb2c6535..42493b4d8ce4 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -78,7 +78,7 @@ static int crypto_aead_copy_sgl(struct crypto_sync_skcipher *null_tfm, SYNC_SKCIPHER_REQUEST_ON_STACK(skreq, null_tfm); skcipher_request_set_sync_tfm(skreq, null_tfm); - skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_BACKLOG, + skcipher_request_set_callback(skreq, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); skcipher_request_set_crypt(skreq, src, dst, len, NULL); @@ -291,19 +291,20 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, areq->outlen = outlen; aead_request_set_callback(&areq->cra_u.aead_req, - CRYPTO_TFM_REQ_MAY_BACKLOG, + CRYPTO_TFM_REQ_MAY_SLEEP, af_alg_async_cb, areq); err = ctx->enc ? crypto_aead_encrypt(&areq->cra_u.aead_req) : crypto_aead_decrypt(&areq->cra_u.aead_req); /* AIO operation in progress */ - if (err == -EINPROGRESS || err == -EBUSY) + if (err == -EINPROGRESS) return -EIOCBQUEUED; sock_put(sk); } else { /* Synchronous operation */ aead_request_set_callback(&areq->cra_u.aead_req, + CRYPTO_TFM_REQ_MAY_SLEEP | CRYPTO_TFM_REQ_MAY_BACKLOG, crypto_req_done, &ctx->wait); err = crypto_wait_req(ctx->enc ? -- cgit v1.2.3 From ba974adb47f2063612d558ac7c3499b59e36c147 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 5 Aug 2020 15:57:08 +1000 Subject: crypto: tcrypt - Add support for hash speed testing with keys Currently if you speed test a hash that requires a key you'll get an error because tcrypt does not set a key by default. This patch allows a key to be set using the new module parameter klen. Signed-off-by: Herbert Xu --- crypto/tcrypt.c | 14 +++++++++----- crypto/tcrypt.h | 29 ----------------------------- 2 files changed, 9 insertions(+), 34 deletions(-) (limited to 'crypto') diff --git a/crypto/tcrypt.c b/crypto/tcrypt.c index acc758728b73..234b1adcfbcb 100644 --- a/crypto/tcrypt.c +++ b/crypto/tcrypt.c @@ -63,6 +63,7 @@ static u32 type; static u32 mask; static int mode; static u32 num_mb = 8; +static unsigned int klen; static char *tvmem[TVMEMSIZE]; static const char *check[] = { @@ -864,8 +865,8 @@ static void test_mb_ahash_speed(const char *algo, unsigned int secs, goto out; } - if (speed[i].klen) - crypto_ahash_setkey(tfm, tvmem[0], speed[i].klen); + if (klen) + crypto_ahash_setkey(tfm, tvmem[0], klen); for (k = 0; k < num_mb; k++) ahash_request_set_crypt(data[k].req, data[k].sg, @@ -1099,8 +1100,8 @@ static void test_ahash_speed_common(const char *algo, unsigned int secs, break; } - if (speed[i].klen) - crypto_ahash_setkey(tfm, tvmem[0], speed[i].klen); + if (klen) + crypto_ahash_setkey(tfm, tvmem[0], klen); pr_info("test%3u " "(%5u byte blocks,%5u bytes per update,%4u updates): ", @@ -2418,7 +2419,8 @@ static int do_test(const char *alg, u32 type, u32 mask, int m, u32 num_mb) if (mode > 300 && mode < 400) break; /* fall through */ case 318: - test_hash_speed("ghash-generic", sec, hash_speed_template_16); + klen = 16; + test_hash_speed("ghash", sec, generic_hash_speed_template); if (mode > 300 && mode < 400) break; /* fall through */ case 319: @@ -3076,6 +3078,8 @@ MODULE_PARM_DESC(sec, "Length in seconds of speed tests " "(defaults to zero which uses CPU cycles instead)"); module_param(num_mb, uint, 0000); MODULE_PARM_DESC(num_mb, "Number of concurrent requests to be used in mb speed tests (defaults to 8)"); +module_param(klen, uint, 0); +MODULE_PARM_DESC(klen, "Key length (defaults to 0)"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Quick & dirty crypto testing module"); diff --git a/crypto/tcrypt.h b/crypto/tcrypt.h index 7e5fea811670..9f654677172a 100644 --- a/crypto/tcrypt.h +++ b/crypto/tcrypt.h @@ -25,7 +25,6 @@ struct aead_speed_template { struct hash_speed { unsigned int blen; /* buffer length */ unsigned int plen; /* per-update length */ - unsigned int klen; /* key length */ }; /* @@ -97,34 +96,6 @@ static struct hash_speed generic_hash_speed_template[] = { { .blen = 0, .plen = 0, } }; -static struct hash_speed hash_speed_template_16[] = { - { .blen = 16, .plen = 16, .klen = 16, }, - { .blen = 64, .plen = 16, .klen = 16, }, - { .blen = 64, .plen = 64, .klen = 16, }, - { .blen = 256, .plen = 16, .klen = 16, }, - { .blen = 256, .plen = 64, .klen = 16, }, - { .blen = 256, .plen = 256, .klen = 16, }, - { .blen = 1024, .plen = 16, .klen = 16, }, - { .blen = 1024, .plen = 256, .klen = 16, }, - { .blen = 1024, .plen = 1024, .klen = 16, }, - { .blen = 2048, .plen = 16, .klen = 16, }, - { .blen = 2048, .plen = 256, .klen = 16, }, - { .blen = 2048, .plen = 1024, .klen = 16, }, - { .blen = 2048, .plen = 2048, .klen = 16, }, - { .blen = 4096, .plen = 16, .klen = 16, }, - { .blen = 4096, .plen = 256, .klen = 16, }, - { .blen = 4096, .plen = 1024, .klen = 16, }, - { .blen = 4096, .plen = 4096, .klen = 16, }, - { .blen = 8192, .plen = 16, .klen = 16, }, - { .blen = 8192, .plen = 256, .klen = 16, }, - { .blen = 8192, .plen = 1024, .klen = 16, }, - { .blen = 8192, .plen = 4096, .klen = 16, }, - { .blen = 8192, .plen = 8192, .klen = 16, }, - - /* End marker */ - { .blen = 0, .plen = 0, .klen = 0, } -}; - static struct hash_speed poly1305_speed_template[] = { { .blen = 96, .plen = 16, }, { .blen = 96, .plen = 32, }, -- cgit v1.2.3 From 8afa25aa833fbd4f3aa701cb42ebd52b1deef1d3 Mon Sep 17 00:00:00 2001 From: Ira Weiny Date: Mon, 10 Aug 2020 17:40:15 -0700 Subject: crypto: hash - Remove unused async iterators Revert "crypto: hash - Add real ahash walk interface" This reverts commit 75ecb231ff45b54afa9f4ec9137965c3c00868f4. The callers of the functions in this commit were removed in ab8085c130ed Remove these unused calls. Fixes: ab8085c130ed ("crypto: x86 - remove SHA multibuffer routines and mcryptd") Cc: Ard Biesheuvel Signed-off-by: Ira Weiny Signed-off-by: Herbert Xu --- crypto/ahash.c | 41 ++++------------------------------------- 1 file changed, 4 insertions(+), 37 deletions(-) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index d9d65d1cc669..d84ad925dfc9 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -10,7 +10,6 @@ #include #include -#include #include #include #include @@ -46,10 +45,7 @@ static int hash_walk_next(struct crypto_hash_walk *walk) unsigned int nbytes = min(walk->entrylen, ((unsigned int)(PAGE_SIZE)) - offset); - if (walk->flags & CRYPTO_ALG_ASYNC) - walk->data = kmap(walk->pg); - else - walk->data = kmap_atomic(walk->pg); + walk->data = kmap_atomic(walk->pg); walk->data += offset; if (offset & alignmask) { @@ -99,16 +95,8 @@ int crypto_hash_walk_done(struct crypto_hash_walk *walk, int err) } } - if (walk->flags & CRYPTO_ALG_ASYNC) - kunmap(walk->pg); - else { - kunmap_atomic(walk->data); - /* - * The may sleep test only makes sense for sync users. - * Async users don't need to sleep here anyway. - */ - crypto_yield(walk->flags); - } + kunmap_atomic(walk->data); + crypto_yield(walk->flags); if (err) return err; @@ -140,33 +128,12 @@ int crypto_hash_walk_first(struct ahash_request *req, walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req)); walk->sg = req->src; - walk->flags = req->base.flags & CRYPTO_TFM_REQ_MASK; + walk->flags = req->base.flags; return hash_walk_new_entry(walk); } EXPORT_SYMBOL_GPL(crypto_hash_walk_first); -int crypto_ahash_walk_first(struct ahash_request *req, - struct crypto_hash_walk *walk) -{ - walk->total = req->nbytes; - - if (!walk->total) { - walk->entrylen = 0; - return 0; - } - - walk->alignmask = crypto_ahash_alignmask(crypto_ahash_reqtfm(req)); - walk->sg = req->src; - walk->flags = req->base.flags & CRYPTO_TFM_REQ_MASK; - walk->flags |= CRYPTO_ALG_ASYNC; - - BUILD_BUG_ON(CRYPTO_TFM_REQ_MASK & CRYPTO_ALG_ASYNC); - - return hash_walk_new_entry(walk); -} -EXPORT_SYMBOL_GPL(crypto_ahash_walk_first); - static int ahash_setkey_unaligned(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen) { -- cgit v1.2.3 From e73d340db6448013ac219d105654d2b9868a8dd2 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 18 Aug 2020 18:25:34 +1000 Subject: crypto: ahash - Add init_tfm/exit_tfm This patch adds the type-safe init_tfm/exit_tfm functions to the ahash interface. This is meant to replace the unsafe cra_init and cra_exit interface. Signed-off-by: Herbert Xu --- crypto/ahash.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/ahash.c b/crypto/ahash.c index d84ad925dfc9..c2ca631a111f 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -444,6 +444,14 @@ static int ahash_def_finup(struct ahash_request *req) return ahash_def_finup_finish1(req, err); } +static void crypto_ahash_exit_tfm(struct crypto_tfm *tfm) +{ + struct crypto_ahash *hash = __crypto_ahash_cast(tfm); + struct ahash_alg *alg = crypto_ahash_alg(hash); + + alg->exit_tfm(hash); +} + static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) { struct crypto_ahash *hash = __crypto_ahash_cast(tfm); @@ -467,7 +475,10 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm) ahash_set_needkey(hash); } - return 0; + if (alg->exit_tfm) + tfm->exit = crypto_ahash_exit_tfm; + + return alg->init_tfm ? alg->init_tfm(hash) : 0; } static unsigned int crypto_ahash_extsize(struct crypto_alg *alg) -- cgit v1.2.3 From 9ace6771831017ce75a2bdf03c284b686dd39dba Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Mon, 31 Aug 2020 18:16:49 +0300 Subject: crypto: arc4 - mark ecb(arc4) skcipher as obsolete Cryptographic algorithms may have a lifespan that is significantly shorter than Linux's, and so we need to start phasing out algorithms that are known to be broken, and are no longer fit for general use. RC4 (or arc4) is a good example here: there are a few areas where its use is still somewhat acceptable, e.g., for interoperability with legacy wifi hardware that can only use WEP or TKIP data encryption, but that should not imply that, for instance, use of RC4 based EAP-TLS by the WPA supplicant for negotiating TKIP keys is equally acceptable, or that RC4 should remain available as a general purpose cryptographic transform for all in-kernel and user space clients. Now that all in-kernel users that need to retain support have moved to the arc4 library interface, and the known users of ecb(arc4) via the socket API (iwd [0] and libell [1][2]) have been updated to switch to a local implementation, we can take the next step, and mark the ecb(arc4) skcipher as obsolete, and only provide it if the socket API is enabled in the first place, as well as provide the option to disable all algorithms that have been marked as obsolete. [0] https://git.kernel.org/pub/scm/network/wireless/iwd.git/commit/?id=1db8a85a60c64523 [1] https://git.kernel.org/pub/scm/libs/ell/ell.git/commit/?id=53482ce421b727c2 [2] https://git.kernel.org/pub/scm/libs/ell/ell.git/commit/?id=7f6a137809d42f6b Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Kconfig | 10 ++++++++++ crypto/arc4.c | 11 +++++++++++ 2 files changed, 21 insertions(+) (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index 1b57419fa2e7..e85d8a059489 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1199,6 +1199,7 @@ config CRYPTO_ANUBIS config CRYPTO_ARC4 tristate "ARC4 cipher algorithm" + depends on CRYPTO_USER_API_ENABLE_OBSOLETE select CRYPTO_SKCIPHER select CRYPTO_LIB_ARC4 help @@ -1881,6 +1882,15 @@ config CRYPTO_USER_API_AEAD This option enables the user-spaces interface for AEAD cipher algorithms. +config CRYPTO_USER_API_ENABLE_OBSOLETE + bool "Enable obsolete cryptographic algorithms for userspace" + depends on CRYPTO_USER_API + default y + help + Allow obsolete cryptographic algorithms to be selected that have + already been phased out from internal use by the kernel, and are + only useful for userspace clients that still rely on them. + config CRYPTO_STATS bool "Crypto usage statistics for User-space" depends on CRYPTO_USER diff --git a/crypto/arc4.c b/crypto/arc4.c index aa79571dbd49..3254dcc34368 100644 --- a/crypto/arc4.c +++ b/crypto/arc4.c @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include static int crypto_arc4_setkey(struct crypto_skcipher *tfm, const u8 *in_key, unsigned int key_len) @@ -39,6 +41,14 @@ static int crypto_arc4_crypt(struct skcipher_request *req) return err; } +static int crypto_arc4_init(struct crypto_skcipher *tfm) +{ + pr_warn_ratelimited("\"%s\" (%ld) uses obsolete ecb(arc4) skcipher\n", + current->comm, (unsigned long)current->pid); + + return 0; +} + static struct skcipher_alg arc4_alg = { /* * For legacy reasons, this is named "ecb(arc4)", not "arc4". @@ -55,6 +65,7 @@ static struct skcipher_alg arc4_alg = { .setkey = crypto_arc4_setkey, .encrypt = crypto_arc4_crypt, .decrypt = crypto_arc4_crypt, + .init = crypto_arc4_init, }; static int __init arc4_init(void) -- cgit v1.2.3 From 5f254dd440fbad0c00632f9ac7645f07d8df9229 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 1 Sep 2020 21:49:11 +1000 Subject: crypto: cbc - Remove cbc.h Now that crypto/cbc.h is only used by the generic cbc template, we can merge it back into the CBC code. Signed-off-by: Herbert Xu --- crypto/cbc.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 133 insertions(+), 11 deletions(-) (limited to 'crypto') diff --git a/crypto/cbc.c b/crypto/cbc.c index e6f6273a7d39..0d9509dff891 100644 --- a/crypto/cbc.c +++ b/crypto/cbc.c @@ -6,7 +6,6 @@ */ #include -#include #include #include #include @@ -14,34 +13,157 @@ #include #include -static inline void crypto_cbc_encrypt_one(struct crypto_skcipher *tfm, - const u8 *src, u8 *dst) +static int crypto_cbc_encrypt_segment(struct skcipher_walk *walk, + struct crypto_skcipher *skcipher) { - crypto_cipher_encrypt_one(skcipher_cipher_simple(tfm), dst, src); + unsigned int bsize = crypto_skcipher_blocksize(skcipher); + void (*fn)(struct crypto_tfm *, u8 *, const u8 *); + unsigned int nbytes = walk->nbytes; + u8 *src = walk->src.virt.addr; + u8 *dst = walk->dst.virt.addr; + struct crypto_cipher *cipher; + struct crypto_tfm *tfm; + u8 *iv = walk->iv; + + cipher = skcipher_cipher_simple(skcipher); + tfm = crypto_cipher_tfm(cipher); + fn = crypto_cipher_alg(cipher)->cia_encrypt; + + do { + crypto_xor(iv, src, bsize); + fn(tfm, dst, iv); + memcpy(iv, dst, bsize); + + src += bsize; + dst += bsize; + } while ((nbytes -= bsize) >= bsize); + + return nbytes; +} + +static int crypto_cbc_encrypt_inplace(struct skcipher_walk *walk, + struct crypto_skcipher *skcipher) +{ + unsigned int bsize = crypto_skcipher_blocksize(skcipher); + void (*fn)(struct crypto_tfm *, u8 *, const u8 *); + unsigned int nbytes = walk->nbytes; + u8 *src = walk->src.virt.addr; + struct crypto_cipher *cipher; + struct crypto_tfm *tfm; + u8 *iv = walk->iv; + + cipher = skcipher_cipher_simple(skcipher); + tfm = crypto_cipher_tfm(cipher); + fn = crypto_cipher_alg(cipher)->cia_encrypt; + + do { + crypto_xor(src, iv, bsize); + fn(tfm, src, src); + iv = src; + + src += bsize; + } while ((nbytes -= bsize) >= bsize); + + memcpy(walk->iv, iv, bsize); + + return nbytes; } static int crypto_cbc_encrypt(struct skcipher_request *req) { - return crypto_cbc_encrypt_walk(req, crypto_cbc_encrypt_one); + struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); + struct skcipher_walk walk; + int err; + + err = skcipher_walk_virt(&walk, req, false); + + while (walk.nbytes) { + if (walk.src.virt.addr == walk.dst.virt.addr) + err = crypto_cbc_encrypt_inplace(&walk, skcipher); + else + err = crypto_cbc_encrypt_segment(&walk, skcipher); + err = skcipher_walk_done(&walk, err); + } + + return err; +} + +static int crypto_cbc_decrypt_segment(struct skcipher_walk *walk, + struct crypto_skcipher *skcipher) +{ + unsigned int bsize = crypto_skcipher_blocksize(skcipher); + void (*fn)(struct crypto_tfm *, u8 *, const u8 *); + unsigned int nbytes = walk->nbytes; + u8 *src = walk->src.virt.addr; + u8 *dst = walk->dst.virt.addr; + struct crypto_cipher *cipher; + struct crypto_tfm *tfm; + u8 *iv = walk->iv; + + cipher = skcipher_cipher_simple(skcipher); + tfm = crypto_cipher_tfm(cipher); + fn = crypto_cipher_alg(cipher)->cia_decrypt; + + do { + fn(tfm, dst, src); + crypto_xor(dst, iv, bsize); + iv = src; + + src += bsize; + dst += bsize; + } while ((nbytes -= bsize) >= bsize); + + memcpy(walk->iv, iv, bsize); + + return nbytes; } -static inline void crypto_cbc_decrypt_one(struct crypto_skcipher *tfm, - const u8 *src, u8 *dst) +static int crypto_cbc_decrypt_inplace(struct skcipher_walk *walk, + struct crypto_skcipher *skcipher) { - crypto_cipher_decrypt_one(skcipher_cipher_simple(tfm), dst, src); + unsigned int bsize = crypto_skcipher_blocksize(skcipher); + void (*fn)(struct crypto_tfm *, u8 *, const u8 *); + unsigned int nbytes = walk->nbytes; + u8 *src = walk->src.virt.addr; + u8 last_iv[MAX_CIPHER_BLOCKSIZE]; + struct crypto_cipher *cipher; + struct crypto_tfm *tfm; + + cipher = skcipher_cipher_simple(skcipher); + tfm = crypto_cipher_tfm(cipher); + fn = crypto_cipher_alg(cipher)->cia_decrypt; + + /* Start of the last block. */ + src += nbytes - (nbytes & (bsize - 1)) - bsize; + memcpy(last_iv, src, bsize); + + for (;;) { + fn(tfm, src, src); + if ((nbytes -= bsize) < bsize) + break; + crypto_xor(src, src - bsize, bsize); + src -= bsize; + } + + crypto_xor(src, walk->iv, bsize); + memcpy(walk->iv, last_iv, bsize); + + return nbytes; } static int crypto_cbc_decrypt(struct skcipher_request *req) { - struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); struct skcipher_walk walk; int err; err = skcipher_walk_virt(&walk, req, false); while (walk.nbytes) { - err = crypto_cbc_decrypt_blocks(&walk, tfm, - crypto_cbc_decrypt_one); + if (walk.src.virt.addr == walk.dst.virt.addr) + err = crypto_cbc_decrypt_inplace(&walk, skcipher); + else + err = crypto_cbc_decrypt_segment(&walk, skcipher); err = skcipher_walk_done(&walk, err); } -- cgit v1.2.3 From 1674aea5f080c9f61424354f6870a548770eb07e Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 11 Sep 2020 17:11:03 +0300 Subject: crypto: Kconfig - mark unused ciphers as obsolete We have a few interesting pieces in our cipher museum, which are never used internally, and were only ever provided as generic C implementations. Unfortunately, we cannot simply remove this code, as we cannot be sure that it is not being used via the AF_ALG socket API, however unlikely. So let's mark the Anubis, Khazad, SEED and TEA algorithms as obsolete, which means they can only be enabled in the build if the socket API is enabled in the first place. Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index e85d8a059489..fac10143d23f 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1185,6 +1185,7 @@ config CRYPTO_AES_PPC_SPE config CRYPTO_ANUBIS tristate "Anubis cipher algorithm" + depends on CRYPTO_USER_API_ENABLE_OBSOLETE select CRYPTO_ALGAPI help Anubis cipher algorithm. @@ -1424,6 +1425,7 @@ config CRYPTO_FCRYPT config CRYPTO_KHAZAD tristate "Khazad cipher algorithm" + depends on CRYPTO_USER_API_ENABLE_OBSOLETE select CRYPTO_ALGAPI help Khazad cipher algorithm. @@ -1487,6 +1489,7 @@ config CRYPTO_CHACHA_MIPS config CRYPTO_SEED tristate "SEED cipher algorithm" + depends on CRYPTO_USER_API_ENABLE_OBSOLETE select CRYPTO_ALGAPI help SEED cipher algorithm (RFC4269). @@ -1613,6 +1616,7 @@ config CRYPTO_SM4 config CRYPTO_TEA tristate "TEA, XTEA and XETA cipher algorithms" + depends on CRYPTO_USER_API_ENABLE_OBSOLETE select CRYPTO_ALGAPI help TEA cipher algorithm. -- cgit v1.2.3 From fde2f57c2fece745a75a1978ef593411ddcf4f76 Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Thu, 17 Sep 2020 18:59:36 +0000 Subject: crypto: proc - Removing some useless only space lines Some line got only spaces, remove them Signed-off-by: Corentin Labbe Signed-off-by: Herbert Xu --- crypto/proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crypto') diff --git a/crypto/proc.c b/crypto/proc.c index 08d8c2bc7e62..12fccb9c5205 100644 --- a/crypto/proc.c +++ b/crypto/proc.c @@ -36,7 +36,7 @@ static void c_stop(struct seq_file *m, void *p) static int c_show(struct seq_file *m, void *p) { struct crypto_alg *alg = list_entry(p, struct crypto_alg, cra_list); - + seq_printf(m, "name : %s\n", alg->cra_name); seq_printf(m, "driver : %s\n", alg->cra_driver_name); seq_printf(m, "module : %s\n", module_name(alg->cra_module)); @@ -59,7 +59,7 @@ static int c_show(struct seq_file *m, void *p) alg->cra_type->show(m, alg); goto out; } - + switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) { case CRYPTO_ALG_TYPE_CIPHER: seq_printf(m, "type : cipher\n"); -- cgit v1.2.3 From 77ebdabe8de7c02f43c6de3357f79ff96f9f0579 Mon Sep 17 00:00:00 2001 From: Elena Petrova Date: Fri, 18 Sep 2020 16:42:16 +0100 Subject: crypto: af_alg - add extra parameters for DRBG interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend the user-space RNG interface: 1. Add entropy input via ALG_SET_DRBG_ENTROPY setsockopt option; 2. Add additional data input via sendmsg syscall. This allows DRBG to be tested with test vectors, for example for the purpose of CAVP testing, which otherwise isn't possible. To prevent erroneous use of entropy input, it is hidden under CRYPTO_USER_API_RNG_CAVP config option and requires CAP_SYS_ADMIN to succeed. Signed-off-by: Elena Petrova Acked-by: Stephan Müller Reviewed-by: Eric Biggers Signed-off-by: Herbert Xu --- crypto/Kconfig | 9 +++ crypto/af_alg.c | 14 ++++- crypto/algif_rng.c | 175 +++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 186 insertions(+), 12 deletions(-) (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index fac10143d23f..88f98caaf30d 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -1875,6 +1875,15 @@ config CRYPTO_USER_API_RNG This option enables the user-spaces interface for random number generator algorithms. +config CRYPTO_USER_API_RNG_CAVP + bool "Enable CAVP testing of DRBG" + depends on CRYPTO_USER_API_RNG && CRYPTO_DRBG + help + This option enables extra API for CAVP testing via the user-space + interface: resetting of DRBG entropy, and providing Additional Data. + This should only be enabled for CAVP testing. You should say + no unless you know what this is. + config CRYPTO_USER_API_AEAD tristate "User-space interface for AEAD cipher algorithms" depends on NET diff --git a/crypto/af_alg.c b/crypto/af_alg.c index a6f581ab200c..8535cb03b484 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -253,6 +253,14 @@ static int alg_setsockopt(struct socket *sock, int level, int optname, if (!type->setauthsize) goto unlock; err = type->setauthsize(ask->private, optlen); + break; + case ALG_SET_DRBG_ENTROPY: + if (sock->state == SS_CONNECTED) + goto unlock; + if (!type->setentropy) + goto unlock; + + err = type->setentropy(ask->private, optval, optlen); } unlock: @@ -285,6 +293,11 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern) security_sock_graft(sk2, newsock); security_sk_clone(sk, sk2); + /* + * newsock->ops assigned here to allow type->accept call to override + * them when required. + */ + newsock->ops = type->ops; err = type->accept(ask->private, sk2); nokey = err == -ENOKEY; @@ -303,7 +316,6 @@ int af_alg_accept(struct sock *sk, struct socket *newsock, bool kern) alg_sk(sk2)->parent = sk; alg_sk(sk2)->type = type; - newsock->ops = type->ops; newsock->state = SS_CONNECTED; if (nokey) diff --git a/crypto/algif_rng.c b/crypto/algif_rng.c index 6300e0566dc5..407408c43730 100644 --- a/crypto/algif_rng.c +++ b/crypto/algif_rng.c @@ -38,6 +38,7 @@ * DAMAGE. */ +#include #include #include #include @@ -53,15 +54,26 @@ struct rng_ctx { #define MAXSIZE 128 unsigned int len; struct crypto_rng *drng; + u8 *addtl; + size_t addtl_len; }; -static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, - int flags) +struct rng_parent_ctx { + struct crypto_rng *drng; + u8 *entropy; +}; + +static void rng_reset_addtl(struct rng_ctx *ctx) { - struct sock *sk = sock->sk; - struct alg_sock *ask = alg_sk(sk); - struct rng_ctx *ctx = ask->private; - int err; + kfree_sensitive(ctx->addtl); + ctx->addtl = NULL; + ctx->addtl_len = 0; +} + +static int _rng_recvmsg(struct crypto_rng *drng, struct msghdr *msg, size_t len, + u8 *addtl, size_t addtl_len) +{ + int err = 0; int genlen = 0; u8 result[MAXSIZE]; @@ -82,7 +94,7 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, * seeding as they automatically seed. The X9.31 DRNG will return * an error if it was not seeded properly. */ - genlen = crypto_rng_get_bytes(ctx->drng, result, len); + genlen = crypto_rng_generate(drng, addtl, addtl_len, result, len); if (genlen < 0) return genlen; @@ -92,6 +104,63 @@ static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, return err ? err : len; } +static int rng_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct rng_ctx *ctx = ask->private; + + return _rng_recvmsg(ctx->drng, msg, len, NULL, 0); +} + +static int rng_test_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags) +{ + struct sock *sk = sock->sk; + struct alg_sock *ask = alg_sk(sk); + struct rng_ctx *ctx = ask->private; + int ret; + + lock_sock(sock->sk); + ret = _rng_recvmsg(ctx->drng, msg, len, ctx->addtl, ctx->addtl_len); + rng_reset_addtl(ctx); + release_sock(sock->sk); + + return ret; +} + +static int rng_test_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) +{ + int err; + struct alg_sock *ask = alg_sk(sock->sk); + struct rng_ctx *ctx = ask->private; + + lock_sock(sock->sk); + if (len > MAXSIZE) { + err = -EMSGSIZE; + goto unlock; + } + + rng_reset_addtl(ctx); + ctx->addtl = kmalloc(len, GFP_KERNEL); + if (!ctx->addtl) { + err = -ENOMEM; + goto unlock; + } + + err = memcpy_from_msg(ctx->addtl, msg, len); + if (err) { + rng_reset_addtl(ctx); + goto unlock; + } + ctx->addtl_len = len; + +unlock: + release_sock(sock->sk); + return err ? err : len; +} + static struct proto_ops algif_rng_ops = { .family = PF_ALG, @@ -111,14 +180,53 @@ static struct proto_ops algif_rng_ops = { .recvmsg = rng_recvmsg, }; +static struct proto_ops __maybe_unused algif_rng_test_ops = { + .family = PF_ALG, + + .connect = sock_no_connect, + .socketpair = sock_no_socketpair, + .getname = sock_no_getname, + .ioctl = sock_no_ioctl, + .listen = sock_no_listen, + .shutdown = sock_no_shutdown, + .mmap = sock_no_mmap, + .bind = sock_no_bind, + .accept = sock_no_accept, + .sendpage = sock_no_sendpage, + + .release = af_alg_release, + .recvmsg = rng_test_recvmsg, + .sendmsg = rng_test_sendmsg, +}; + static void *rng_bind(const char *name, u32 type, u32 mask) { - return crypto_alloc_rng(name, type, mask); + struct rng_parent_ctx *pctx; + struct crypto_rng *rng; + + pctx = kzalloc(sizeof(*pctx), GFP_KERNEL); + if (!pctx) + return ERR_PTR(-ENOMEM); + + rng = crypto_alloc_rng(name, type, mask); + if (IS_ERR(rng)) { + kfree(pctx); + return ERR_CAST(rng); + } + + pctx->drng = rng; + return pctx; } static void rng_release(void *private) { - crypto_free_rng(private); + struct rng_parent_ctx *pctx = private; + + if (unlikely(!pctx)) + return; + crypto_free_rng(pctx->drng); + kfree_sensitive(pctx->entropy); + kfree_sensitive(pctx); } static void rng_sock_destruct(struct sock *sk) @@ -126,6 +234,7 @@ static void rng_sock_destruct(struct sock *sk) struct alg_sock *ask = alg_sk(sk); struct rng_ctx *ctx = ask->private; + rng_reset_addtl(ctx); sock_kfree_s(sk, ctx, ctx->len); af_alg_release_parent(sk); } @@ -133,6 +242,7 @@ static void rng_sock_destruct(struct sock *sk) static int rng_accept_parent(void *private, struct sock *sk) { struct rng_ctx *ctx; + struct rng_parent_ctx *pctx = private; struct alg_sock *ask = alg_sk(sk); unsigned int len = sizeof(*ctx); @@ -141,6 +251,8 @@ static int rng_accept_parent(void *private, struct sock *sk) return -ENOMEM; ctx->len = len; + ctx->addtl = NULL; + ctx->addtl_len = 0; /* * No seeding done at that point -- if multiple accepts are @@ -148,20 +260,58 @@ static int rng_accept_parent(void *private, struct sock *sk) * state of the RNG. */ - ctx->drng = private; + ctx->drng = pctx->drng; ask->private = ctx; sk->sk_destruct = rng_sock_destruct; + /* + * Non NULL pctx->entropy means that CAVP test has been initiated on + * this socket, replace proto_ops algif_rng_ops with algif_rng_test_ops. + */ + if (IS_ENABLED(CONFIG_CRYPTO_USER_API_RNG_CAVP) && pctx->entropy) + sk->sk_socket->ops = &algif_rng_test_ops; + return 0; } static int rng_setkey(void *private, const u8 *seed, unsigned int seedlen) { + struct rng_parent_ctx *pctx = private; /* * Check whether seedlen is of sufficient size is done in RNG * implementations. */ - return crypto_rng_reset(private, seed, seedlen); + return crypto_rng_reset(pctx->drng, seed, seedlen); +} + +static int __maybe_unused rng_setentropy(void *private, sockptr_t entropy, + unsigned int len) +{ + struct rng_parent_ctx *pctx = private; + u8 *kentropy = NULL; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (pctx->entropy) + return -EINVAL; + + if (len > MAXSIZE) + return -EMSGSIZE; + + if (len) { + kentropy = memdup_sockptr(entropy, len); + if (IS_ERR(kentropy)) + return PTR_ERR(kentropy); + } + + crypto_rng_alg(pctx->drng)->set_ent(pctx->drng, kentropy, len); + /* + * Since rng doesn't perform any memory management for the entropy + * buffer, save kentropy pointer to pctx now to free it after use. + */ + pctx->entropy = kentropy; + return 0; } static const struct af_alg_type algif_type_rng = { @@ -169,6 +319,9 @@ static const struct af_alg_type algif_type_rng = { .release = rng_release, .accept = rng_accept_parent, .setkey = rng_setkey, +#ifdef CONFIG_CRYPTO_USER_API_RNG_CAVP + .setentropy = rng_setentropy, +#endif .ops = &algif_rng_ops, .name = "rng", .owner = THIS_MODULE -- cgit v1.2.3 From f49282870fb039e3c2e5c3341bd27875282609d7 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:20:54 +0800 Subject: crypto: sm3 - export crypto_sm3_final function Both crypto_sm3_update and crypto_sm3_finup have been exported, exporting crypto_sm3_final, to avoid having to use crypto_sm3_finup(desc, NULL, 0, dgst) to calculate the hash in some cases. Signed-off-by: Tianjia Zhang Tested-by: Xufeng Zhang Signed-off-by: Herbert Xu --- crypto/sm3_generic.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/sm3_generic.c b/crypto/sm3_generic.c index 3468975215ca..193c4584bd00 100644 --- a/crypto/sm3_generic.c +++ b/crypto/sm3_generic.c @@ -149,17 +149,18 @@ int crypto_sm3_update(struct shash_desc *desc, const u8 *data, } EXPORT_SYMBOL(crypto_sm3_update); -static int sm3_final(struct shash_desc *desc, u8 *out) +int crypto_sm3_final(struct shash_desc *desc, u8 *out) { sm3_base_do_finalize(desc, sm3_generic_block_fn); return sm3_base_finish(desc, out); } +EXPORT_SYMBOL(crypto_sm3_final); int crypto_sm3_finup(struct shash_desc *desc, const u8 *data, unsigned int len, u8 *hash) { sm3_base_do_update(desc, data, len, sm3_generic_block_fn); - return sm3_final(desc, hash); + return crypto_sm3_final(desc, hash); } EXPORT_SYMBOL(crypto_sm3_finup); @@ -167,7 +168,7 @@ static struct shash_alg sm3_alg = { .digestsize = SM3_DIGEST_SIZE, .init = sm3_base_init, .update = crypto_sm3_update, - .final = sm3_final, + .final = crypto_sm3_final, .finup = crypto_sm3_finup, .descsize = sizeof(struct sm3_state), .base = { -- cgit v1.2.3 From ea7ecb66440b37c035e899c60ceaf7a03d364930 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:20:57 +0800 Subject: crypto: sm2 - introduce OSCCA SM2 asymmetric cipher algorithm This new module implement the SM2 public key algorithm. It was published by State Encryption Management Bureau, China. List of specifications for SM2 elliptic curve public key cryptography: * GM/T 0003.1-2012 * GM/T 0003.2-2012 * GM/T 0003.3-2012 * GM/T 0003.4-2012 * GM/T 0003.5-2012 IETF: https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 oscca: http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml scctc: http://www.gmbz.org.cn/main/bzlb.html Signed-off-by: Tianjia Zhang Tested-by: Xufeng Zhang Signed-off-by: Herbert Xu --- crypto/Kconfig | 17 ++ crypto/Makefile | 8 + crypto/sm2.c | 481 +++++++++++++++++++++++++++++++++++++++++++++++ crypto/sm2signature.asn1 | 4 + 4 files changed, 510 insertions(+) create mode 100644 crypto/sm2.c create mode 100644 crypto/sm2signature.asn1 (limited to 'crypto') diff --git a/crypto/Kconfig b/crypto/Kconfig index 88f98caaf30d..094ef56ab7b4 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -260,6 +260,23 @@ config CRYPTO_ECRDSA standard algorithms (called GOST algorithms). Only signature verification is implemented. +config CRYPTO_SM2 + tristate "SM2 algorithm" + select CRYPTO_SM3 + select CRYPTO_AKCIPHER + select CRYPTO_MANAGER + select MPILIB + select ASN1 + help + Generic implementation of the SM2 public key algorithm. It was + published by State Encryption Management Bureau, China. + as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012. + + References: + https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 + http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml + http://www.gmbz.org.cn/main/bzlb.html + config CRYPTO_CURVE25519 tristate "Curve25519 algorithm" select CRYPTO_KPP diff --git a/crypto/Makefile b/crypto/Makefile index 4ca12b6044f7..b279483fba50 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -42,6 +42,14 @@ rsa_generic-y += rsa_helper.o rsa_generic-y += rsa-pkcs1pad.o obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o +$(obj)/sm2signature.asn1.o: $(obj)/sm2signature.asn1.c $(obj)/sm2signature.asn1.h +$(obj)/sm2.o: $(obj)/sm2signature.asn1.h + +sm2_generic-y += sm2signature.asn1.o +sm2_generic-y += sm2.o + +obj-$(CONFIG_CRYPTO_SM2) += sm2_generic.o + crypto_acompress-y := acompress.o crypto_acompress-y += scompress.o obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o diff --git a/crypto/sm2.c b/crypto/sm2.c new file mode 100644 index 000000000000..767e160333f6 --- /dev/null +++ b/crypto/sm2.c @@ -0,0 +1,481 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * SM2 asymmetric public-key algorithm + * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and + * described at https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 + * + * Copyright (c) 2020, Alibaba Group. + * Authors: Tianjia Zhang + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "sm2signature.asn1.h" + +#define MPI_NBYTES(m) ((mpi_get_nbits(m) + 7) / 8) + +struct ecc_domain_parms { + const char *desc; /* Description of the curve. */ + unsigned int nbits; /* Number of bits. */ + unsigned int fips:1; /* True if this is a FIPS140-2 approved curve */ + + /* The model describing this curve. This is mainly used to select + * the group equation. + */ + enum gcry_mpi_ec_models model; + + /* The actual ECC dialect used. This is used for curve specific + * optimizations and to select encodings etc. + */ + enum ecc_dialects dialect; + + const char *p; /* The prime defining the field. */ + const char *a, *b; /* The coefficients. For Twisted Edwards + * Curves b is used for d. For Montgomery + * Curves (a,b) has ((A-2)/4,B^-1). + */ + const char *n; /* The order of the base point. */ + const char *g_x, *g_y; /* Base point. */ + unsigned int h; /* Cofactor. */ +}; + +static const struct ecc_domain_parms sm2_ecp = { + .desc = "sm2p256v1", + .nbits = 256, + .fips = 0, + .model = MPI_EC_WEIERSTRASS, + .dialect = ECC_DIALECT_STANDARD, + .p = "0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff", + .a = "0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc", + .b = "0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93", + .n = "0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123", + .g_x = "0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7", + .g_y = "0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0", + .h = 1 +}; + +static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec) +{ + const struct ecc_domain_parms *ecp = &sm2_ecp; + MPI p, a, b; + MPI x, y; + int rc = -EINVAL; + + p = mpi_scanval(ecp->p); + a = mpi_scanval(ecp->a); + b = mpi_scanval(ecp->b); + if (!p || !a || !b) + goto free_p; + + x = mpi_scanval(ecp->g_x); + y = mpi_scanval(ecp->g_y); + if (!x || !y) + goto free; + + rc = -ENOMEM; + /* mpi_ec_setup_elliptic_curve */ + ec->G = mpi_point_new(0); + if (!ec->G) + goto free; + + mpi_set(ec->G->x, x); + mpi_set(ec->G->y, y); + mpi_set_ui(ec->G->z, 1); + + rc = -EINVAL; + ec->n = mpi_scanval(ecp->n); + if (!ec->n) { + mpi_point_release(ec->G); + goto free; + } + + ec->h = ecp->h; + ec->name = ecp->desc; + mpi_ec_init(ec, ecp->model, ecp->dialect, 0, p, a, b); + + rc = 0; + +free: + mpi_free(x); + mpi_free(y); +free_p: + mpi_free(p); + mpi_free(a); + mpi_free(b); + + return rc; +} + +static void sm2_ec_ctx_deinit(struct mpi_ec_ctx *ec) +{ + mpi_ec_deinit(ec); + + memset(ec, 0, sizeof(*ec)); +} + +static int sm2_ec_ctx_reset(struct mpi_ec_ctx *ec) +{ + sm2_ec_ctx_deinit(ec); + return sm2_ec_ctx_init(ec); +} + +/* RESULT must have been initialized and is set on success to the + * point given by VALUE. + */ +static int sm2_ecc_os2ec(MPI_POINT result, MPI value) +{ + int rc; + size_t n; + const unsigned char *buf; + unsigned char *buf_memory; + MPI x, y; + + n = (mpi_get_nbits(value)+7)/8; + buf_memory = kmalloc(n, GFP_KERNEL); + rc = mpi_print(GCRYMPI_FMT_USG, buf_memory, n, &n, value); + if (rc) { + kfree(buf_memory); + return rc; + } + buf = buf_memory; + + if (n < 1) { + kfree(buf_memory); + return -EINVAL; + } + if (*buf != 4) { + kfree(buf_memory); + return -EINVAL; /* No support for point compression. */ + } + if (((n-1)%2)) { + kfree(buf_memory); + return -EINVAL; + } + n = (n-1)/2; + x = mpi_read_raw_data(buf + 1, n); + if (!x) { + kfree(buf_memory); + return -ENOMEM; + } + y = mpi_read_raw_data(buf + 1 + n, n); + kfree(buf_memory); + if (!y) { + mpi_free(x); + return -ENOMEM; + } + + mpi_normalize(x); + mpi_normalize(y); + + mpi_set(result->x, x); + mpi_set(result->y, y); + mpi_set_ui(result->z, 1); + + mpi_free(x); + mpi_free(y); + + return 0; +} + +struct sm2_signature_ctx { + MPI sig_r; + MPI sig_s; +}; + +int sm2_get_signature_r(void *context, size_t hdrlen, unsigned char tag, + const void *value, size_t vlen) +{ + struct sm2_signature_ctx *sig = context; + + if (!value || !vlen) + return -EINVAL; + + sig->sig_r = mpi_read_raw_data(value, vlen); + if (!sig->sig_r) + return -ENOMEM; + + return 0; +} + +int sm2_get_signature_s(void *context, size_t hdrlen, unsigned char tag, + const void *value, size_t vlen) +{ + struct sm2_signature_ctx *sig = context; + + if (!value || !vlen) + return -EINVAL; + + sig->sig_s = mpi_read_raw_data(value, vlen); + if (!sig->sig_s) + return -ENOMEM; + + return 0; +} + +static int sm2_z_digest_update(struct shash_desc *desc, + MPI m, unsigned int pbytes) +{ + static const unsigned char zero[32]; + unsigned char *in; + unsigned int inlen; + + in = mpi_get_buffer(m, &inlen, NULL); + if (!in) + return -EINVAL; + + if (inlen < pbytes) { + /* padding with zero */ + crypto_sm3_update(desc, zero, pbytes - inlen); + crypto_sm3_update(desc, in, inlen); + } else if (inlen > pbytes) { + /* skip the starting zero */ + crypto_sm3_update(desc, in + inlen - pbytes, pbytes); + } else { + crypto_sm3_update(desc, in, inlen); + } + + kfree(in); + return 0; +} + +static int sm2_z_digest_update_point(struct shash_desc *desc, + MPI_POINT point, struct mpi_ec_ctx *ec, unsigned int pbytes) +{ + MPI x, y; + int ret = -EINVAL; + + x = mpi_new(0); + y = mpi_new(0); + + if (!mpi_ec_get_affine(x, y, point, ec) && + !sm2_z_digest_update(desc, x, pbytes) && + !sm2_z_digest_update(desc, y, pbytes)) + ret = 0; + + mpi_free(x); + mpi_free(y); + return ret; +} + +int sm2_compute_z_digest(struct crypto_akcipher *tfm, + const unsigned char *id, size_t id_len, + unsigned char dgst[SM3_DIGEST_SIZE]) +{ + struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); + uint16_t bits_len; + unsigned char entl[2]; + SHASH_DESC_ON_STACK(desc, NULL); + unsigned int pbytes; + + if (id_len > (USHRT_MAX / 8) || !ec->Q) + return -EINVAL; + + bits_len = (uint16_t)(id_len * 8); + entl[0] = bits_len >> 8; + entl[1] = bits_len & 0xff; + + pbytes = MPI_NBYTES(ec->p); + + /* ZA = H256(ENTLA | IDA | a | b | xG | yG | xA | yA) */ + sm3_base_init(desc); + crypto_sm3_update(desc, entl, 2); + crypto_sm3_update(desc, id, id_len); + + if (sm2_z_digest_update(desc, ec->a, pbytes) || + sm2_z_digest_update(desc, ec->b, pbytes) || + sm2_z_digest_update_point(desc, ec->G, ec, pbytes) || + sm2_z_digest_update_point(desc, ec->Q, ec, pbytes)) + return -EINVAL; + + crypto_sm3_final(desc, dgst); + return 0; +} +EXPORT_SYMBOL(sm2_compute_z_digest); + +static int _sm2_verify(struct mpi_ec_ctx *ec, MPI hash, MPI sig_r, MPI sig_s) +{ + int rc = -EINVAL; + struct gcry_mpi_point sG, tP; + MPI t = NULL; + MPI x1 = NULL, y1 = NULL; + + mpi_point_init(&sG); + mpi_point_init(&tP); + x1 = mpi_new(0); + y1 = mpi_new(0); + t = mpi_new(0); + + /* r, s in [1, n-1] */ + if (mpi_cmp_ui(sig_r, 1) < 0 || mpi_cmp(sig_r, ec->n) > 0 || + mpi_cmp_ui(sig_s, 1) < 0 || mpi_cmp(sig_s, ec->n) > 0) { + goto leave; + } + + /* t = (r + s) % n, t == 0 */ + mpi_addm(t, sig_r, sig_s, ec->n); + if (mpi_cmp_ui(t, 0) == 0) + goto leave; + + /* sG + tP = (x1, y1) */ + rc = -EBADMSG; + mpi_ec_mul_point(&sG, sig_s, ec->G, ec); + mpi_ec_mul_point(&tP, t, ec->Q, ec); + mpi_ec_add_points(&sG, &sG, &tP, ec); + if (mpi_ec_get_affine(x1, y1, &sG, ec)) + goto leave; + + /* R = (e + x1) % n */ + mpi_addm(t, hash, x1, ec->n); + + /* check R == r */ + rc = -EKEYREJECTED; + if (mpi_cmp(t, sig_r)) + goto leave; + + rc = 0; + +leave: + mpi_point_free_parts(&sG); + mpi_point_free_parts(&tP); + mpi_free(x1); + mpi_free(y1); + mpi_free(t); + + return rc; +} + +static int sm2_verify(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); + unsigned char *buffer; + struct sm2_signature_ctx sig; + MPI hash; + int ret; + + if (unlikely(!ec->Q)) + return -EINVAL; + + buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + sg_pcopy_to_buffer(req->src, + sg_nents_for_len(req->src, req->src_len + req->dst_len), + buffer, req->src_len + req->dst_len, 0); + + sig.sig_r = NULL; + sig.sig_s = NULL; + ret = asn1_ber_decoder(&sm2signature_decoder, &sig, + buffer, req->src_len); + if (ret) + goto error; + + ret = -ENOMEM; + hash = mpi_read_raw_data(buffer + req->src_len, req->dst_len); + if (!hash) + goto error; + + ret = _sm2_verify(ec, hash, sig.sig_r, sig.sig_s); + + mpi_free(hash); +error: + mpi_free(sig.sig_r); + mpi_free(sig.sig_s); + kfree(buffer); + return ret; +} + +static int sm2_set_pub_key(struct crypto_akcipher *tfm, + const void *key, unsigned int keylen) +{ + struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); + MPI a; + int rc; + + rc = sm2_ec_ctx_reset(ec); + if (rc) + return rc; + + ec->Q = mpi_point_new(0); + if (!ec->Q) + return -ENOMEM; + + /* include the uncompressed flag '0x04' */ + rc = -ENOMEM; + a = mpi_read_raw_data(key, keylen); + if (!a) + goto error; + + mpi_normalize(a); + rc = sm2_ecc_os2ec(ec->Q, a); + mpi_free(a); + if (rc) + goto error; + + return 0; + +error: + mpi_point_release(ec->Q); + ec->Q = NULL; + return rc; +} + +static unsigned int sm2_max_size(struct crypto_akcipher *tfm) +{ + /* Unlimited max size */ + return PAGE_SIZE; +} + +static int sm2_init_tfm(struct crypto_akcipher *tfm) +{ + struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); + + return sm2_ec_ctx_init(ec); +} + +static void sm2_exit_tfm(struct crypto_akcipher *tfm) +{ + struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm); + + sm2_ec_ctx_deinit(ec); +} + +static struct akcipher_alg sm2 = { + .verify = sm2_verify, + .set_pub_key = sm2_set_pub_key, + .max_size = sm2_max_size, + .init = sm2_init_tfm, + .exit = sm2_exit_tfm, + .base = { + .cra_name = "sm2", + .cra_driver_name = "sm2-generic", + .cra_priority = 100, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct mpi_ec_ctx), + }, +}; + +static int sm2_init(void) +{ + return crypto_register_akcipher(&sm2); +} + +static void sm2_exit(void) +{ + crypto_unregister_akcipher(&sm2); +} + +subsys_initcall(sm2_init); +module_exit(sm2_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Tianjia Zhang "); +MODULE_DESCRIPTION("SM2 generic algorithm"); +MODULE_ALIAS_CRYPTO("sm2-generic"); diff --git a/crypto/sm2signature.asn1 b/crypto/sm2signature.asn1 new file mode 100644 index 000000000000..ab8c0b754d21 --- /dev/null +++ b/crypto/sm2signature.asn1 @@ -0,0 +1,4 @@ +Sm2Signature ::= SEQUENCE { + sig_r INTEGER ({ sm2_get_signature_r }), + sig_s INTEGER ({ sm2_get_signature_s }) +} -- cgit v1.2.3 From a1f62c217d9c371187dd14d2e1370923aae58994 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:20:58 +0800 Subject: crypto: testmgr - support test with different ciphertext per encryption Some asymmetric algorithms will get different ciphertext after each encryption, such as SM2, and let testmgr support the testing of such algorithms. In struct akcipher_testvec, set c and c_size to be empty, skip the comparison of the ciphertext, and compare the decrypted plaintext with m to achieve the test purpose. Signed-off-by: Tianjia Zhang Tested-by: Xufeng Zhang Signed-off-by: Herbert Xu --- crypto/testmgr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 66ee3bbc9872..d084de4c60f2 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -4026,7 +4026,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, pr_err("alg: akcipher: %s test failed. err %d\n", op, err); goto free_all; } - if (!vecs->siggen_sigver_test) { + if (!vecs->siggen_sigver_test && c) { if (req->dst_len != c_size) { pr_err("alg: akcipher: %s test failed. Invalid output len\n", op); @@ -4057,6 +4057,11 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, goto free_all; } + if (!vecs->siggen_sigver_test && !c) { + c = outbuf_enc; + c_size = req->dst_len; + } + op = vecs->siggen_sigver_test ? "sign" : "decrypt"; if (WARN_ON(c_size > PAGE_SIZE)) goto free_all; -- cgit v1.2.3 From 2b40386774831c9617325ca8940fb3c270cbb086 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:20:59 +0800 Subject: crypto: testmgr - Fix potential memory leak in test_akcipher_one() When the 'key' allocation fails, the 'req' will not be released, which will cause memory leakage on this path. This patch adds a 'free_req' tag used to solve this problem, and two new err values are added to reflect the real reason of the error. Signed-off-by: Tianjia Zhang Signed-off-by: Herbert Xu --- crypto/testmgr.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index d084de4c60f2..21f2878e4e54 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -3955,7 +3955,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, key = kmalloc(vecs->key_len + sizeof(u32) * 2 + vecs->param_len, GFP_KERNEL); if (!key) - goto free_xbuf; + goto free_req; memcpy(key, vecs->key, vecs->key_len); ptr = key + vecs->key_len; ptr = test_pack_u32(ptr, vecs->algo); @@ -3967,7 +3967,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, else err = crypto_akcipher_set_priv_key(tfm, key, vecs->key_len); if (err) - goto free_req; + goto free_key; /* * First run test which do not require a private key, such as @@ -3977,7 +3977,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, out_len_max = crypto_akcipher_maxsize(tfm); outbuf_enc = kzalloc(out_len_max, GFP_KERNEL); if (!outbuf_enc) - goto free_req; + goto free_key; if (!vecs->siggen_sigver_test) { m = vecs->m; @@ -3996,6 +3996,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, op = "verify"; } + err = -E2BIG; if (WARN_ON(m_size > PAGE_SIZE)) goto free_all; memcpy(xbuf[0], m, m_size); @@ -4062,6 +4063,7 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, c_size = req->dst_len; } + err = -E2BIG; op = vecs->siggen_sigver_test ? "sign" : "decrypt"; if (WARN_ON(c_size > PAGE_SIZE)) goto free_all; @@ -4098,9 +4100,10 @@ static int test_akcipher_one(struct crypto_akcipher *tfm, free_all: kfree(outbuf_dec); kfree(outbuf_enc); +free_key: + kfree(key); free_req: akcipher_request_free(req); - kfree(key); free_xbuf: testmgr_free_buf(xbuf); return err; -- cgit v1.2.3 From 8b805b97fc1aa0de89e582b206ce2efd0df05895 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:21:00 +0800 Subject: crypto: sm2 - add SM2 test vectors to testmgr Add testmgr test vectors for SM2 algorithm. These vectors come from `openssl pkeyutl -sign` and libgcrypt. Signed-off-by: Tianjia Zhang Tested-by: Xufeng Zhang Signed-off-by: Herbert Xu --- crypto/testmgr.c | 6 ++++++ crypto/testmgr.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) (limited to 'crypto') diff --git a/crypto/testmgr.c b/crypto/testmgr.c index 21f2878e4e54..a64a639eddfa 100644 --- a/crypto/testmgr.c +++ b/crypto/testmgr.c @@ -5385,6 +5385,12 @@ static const struct alg_test_desc alg_test_descs[] = { .suite = { .hash = __VECS(sha512_tv_template) } + }, { + .alg = "sm2", + .test = alg_test_akcipher, + .suite = { + .akcipher = __VECS(sm2_tv_template) + } }, { .alg = "sm3", .test = alg_test_hash, diff --git a/crypto/testmgr.h b/crypto/testmgr.h index b9a2d73d9f8d..8c83811c0e35 100644 --- a/crypto/testmgr.h +++ b/crypto/testmgr.h @@ -3792,6 +3792,65 @@ static const struct hash_testvec hmac_streebog512_tv_template[] = { }, }; +/* + * SM2 test vectors. + */ +static const struct akcipher_testvec sm2_tv_template[] = { + { /* Generated from openssl */ + .key = + "\x04" + "\x8e\xa0\x33\x69\x91\x7e\x3d\xec\xad\x8e\xf0\x45\x5e\x13\x3e\x68" + "\x5b\x8c\xab\x5c\xc6\xc8\x50\xdf\x91\x00\xe0\x24\x73\x4d\x31\xf2" + "\x2e\xc0\xd5\x6b\xee\xda\x98\x93\xec\xd8\x36\xaa\xb9\xcf\x63\x82" + "\xef\xa7\x1a\x03\xed\x16\xba\x74\xb8\x8b\xf9\xe5\x70\x39\xa4\x70", + .key_len = 65, + .param_len = 0, + .c = + "\x30\x45" + "\x02\x20" + "\x70\xab\xb6\x7d\xd6\x54\x80\x64\x42\x7e\x2d\x05\x08\x36\xc9\x96" + "\x25\xc2\xbb\xff\x08\xe5\x43\x15\x5e\xf3\x06\xd9\x2b\x2f\x0a\x9f" + "\x02\x21" + "\x00" + "\xbf\x21\x5f\x7e\x5d\x3f\x1a\x4d\x8f\x84\xc2\xe9\xa6\x4c\xa4\x18" + "\xb2\xb8\x46\xf4\x32\x96\xfa\x57\xc6\x29\xd4\x89\xae\xcc\xda\xdb", + .c_size = 71, + .algo = OID_SM2_with_SM3, + .m = + "\x47\xa7\xbf\xd3\xda\xc4\x79\xee\xda\x8b\x4f\xe8\x40\x94\xd4\x32" + "\x8f\xf1\xcd\x68\x4d\xbd\x9b\x1d\xe0\xd8\x9a\x5d\xad\x85\x47\x5c", + .m_size = 32, + .public_key_vec = true, + .siggen_sigver_test = true, + }, + { /* From libgcrypt */ + .key = + "\x04" + "\x87\x59\x38\x9a\x34\xaa\xad\x07\xec\xf4\xe0\xc8\xc2\x65\x0a\x44" + "\x59\xc8\xd9\x26\xee\x23\x78\x32\x4e\x02\x61\xc5\x25\x38\xcb\x47" + "\x75\x28\x10\x6b\x1e\x0b\x7c\x8d\xd5\xff\x29\xa9\xc8\x6a\x89\x06" + "\x56\x56\xeb\x33\x15\x4b\xc0\x55\x60\x91\xef\x8a\xc9\xd1\x7d\x78", + .key_len = 65, + .param_len = 0, + .c = + "\x30\x44" + "\x02\x20" + "\xd9\xec\xef\xe8\x5f\xee\x3c\x59\x57\x8e\x5b\xab\xb3\x02\xe1\x42" + "\x4b\x67\x2c\x0b\x26\xb6\x51\x2c\x3e\xfc\xc6\x49\xec\xfe\x89\xe5" + "\x02\x20" + "\x43\x45\xd0\xa5\xff\xe5\x13\x27\x26\xd0\xec\x37\xad\x24\x1e\x9a" + "\x71\x9a\xa4\x89\xb0\x7e\x0f\xc4\xbb\x2d\x50\xd0\xe5\x7f\x7a\x68", + .c_size = 70, + .algo = OID_SM2_with_SM3, + .m = + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x00" + "\x12\x34\x56\x78\x9a\xbc\xde\xf0\x12\x34\x56\x78\x9a\xbc\xde\xf0", + .m_size = 32, + .public_key_vec = true, + .siggen_sigver_test = true, + }, +}; + /* Example vectors below taken from * http://www.oscca.gov.cn/UpFile/20101222141857786.pdf * -- cgit v1.2.3 From 254f84f559039b6d6f6e1035fd7645b42671ab48 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:21:01 +0800 Subject: X.509: support OSCCA certificate parse The digital certificate format based on SM2 crypto algorithm as specified in GM/T 0015-2012. It was published by State Encryption Management Bureau, China. This patch adds the OID object identifier defined by OSCCA. The x509 certificate supports SM2-with-SM3 type certificate parsing. It uses the standard elliptic curve public key, and the sm2 algorithm signs the hash generated by sm3. Signed-off-by: Tianjia Zhang Tested-by: Xufeng Zhang Reviewed-by: Vitaly Chikunov Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/x509_cert_parser.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index 26ec20ef4899..52c9b455fc7d 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -234,6 +234,10 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, case OID_gost2012Signature512: ctx->cert->sig->hash_algo = "streebog512"; goto ecrdsa; + + case OID_SM2_with_SM3: + ctx->cert->sig->hash_algo = "sm3"; + goto sm2; } rsa_pkcs1: @@ -246,6 +250,11 @@ ecrdsa: ctx->cert->sig->encoding = "raw"; ctx->algo_oid = ctx->last_oid; return 0; +sm2: + ctx->cert->sig->pkey_algo = "sm2"; + ctx->cert->sig->encoding = "raw"; + ctx->algo_oid = ctx->last_oid; + return 0; } /* @@ -266,7 +275,8 @@ int x509_note_signature(void *context, size_t hdrlen, } if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 || - strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0) { + strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 || + strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0) { /* Discard the BIT STRING metadata */ if (vlen < 1 || *(const u8 *)value != 0) return -EBADMSG; @@ -451,13 +461,20 @@ int x509_extract_key_data(void *context, size_t hdrlen, struct x509_parse_context *ctx = context; ctx->key_algo = ctx->last_oid; - if (ctx->last_oid == OID_rsaEncryption) + switch (ctx->last_oid) { + case OID_rsaEncryption: ctx->cert->pub->pkey_algo = "rsa"; - else if (ctx->last_oid == OID_gost2012PKey256 || - ctx->last_oid == OID_gost2012PKey512) + break; + case OID_gost2012PKey256: + case OID_gost2012PKey512: ctx->cert->pub->pkey_algo = "ecrdsa"; - else + break; + case OID_id_ecPublicKey: + ctx->cert->pub->pkey_algo = "sm2"; + break; + default: return -ENOPKG; + } /* Discard the BIT STRING metadata */ if (vlen < 1 || *(const u8 *)value != 0) -- cgit v1.2.3 From 215525639631ade1d67e879fe2c3d7195daa9f59 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 21 Sep 2020 00:21:02 +0800 Subject: X.509: support OSCCA SM2-with-SM3 certificate verification The digital certificate format based on SM2 crypto algorithm as specified in GM/T 0015-2012. It was published by State Encryption Management Bureau, China. The method of generating Other User Information is defined as ZA=H256(ENTLA || IDA || a || b || xG || yG || xA || yA), it also specified in https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02. The x509 certificate supports SM2-with-SM3 type certificate verification. Because certificate verification requires ZA in addition to tbs data, ZA also depends on elliptic curve parameters and public key data, so you need to access tbs in sig and calculate ZA. Finally calculate the digest of the signature and complete the verification work. The calculation process of ZA is declared in specifications GM/T 0009-2012 and GM/T 0003.2-2012. Signed-off-by: Tianjia Zhang Tested-by: Xufeng Zhang Reviewed-by: Gilad Ben-Yossef Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/Makefile | 1 + crypto/asymmetric_keys/public_key.c | 6 ++++ crypto/asymmetric_keys/public_key_sm2.c | 61 ++++++++++++++++++++++++++++++++ crypto/asymmetric_keys/x509_public_key.c | 3 ++ 4 files changed, 71 insertions(+) create mode 100644 crypto/asymmetric_keys/public_key_sm2.c (limited to 'crypto') diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 28b91adba2ae..1a99ea5acb6b 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -11,6 +11,7 @@ asymmetric_keys-y := \ signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o +obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key_sm2.o obj-$(CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE) += asym_tpm.o # diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index d8410ffd7f12..1d0492098bbd 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -299,6 +299,12 @@ int public_key_verify_signature(const struct public_key *pkey, if (ret) goto error_free_key; + if (strcmp(sig->pkey_algo, "sm2") == 0 && sig->data_size) { + ret = cert_sig_digest_update(sig, tfm); + if (ret) + goto error_free_key; + } + sg_init_table(src_sg, 2); sg_set_buf(&src_sg[0], sig->s, sig->s_size); sg_set_buf(&src_sg[1], sig->digest, sig->digest_size); diff --git a/crypto/asymmetric_keys/public_key_sm2.c b/crypto/asymmetric_keys/public_key_sm2.c new file mode 100644 index 000000000000..7325cf21dbb4 --- /dev/null +++ b/crypto/asymmetric_keys/public_key_sm2.c @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * asymmetric public-key algorithm for SM2-with-SM3 certificate + * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and + * described at https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 + * + * Copyright (c) 2020, Alibaba Group. + * Authors: Tianjia Zhang + */ + +#include +#include +#include + +#if IS_REACHABLE(CONFIG_CRYPTO_SM2) + +int cert_sig_digest_update(const struct public_key_signature *sig, + struct crypto_akcipher *tfm_pkey) +{ + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t desc_size; + unsigned char dgst[SM3_DIGEST_SIZE]; + int ret; + + BUG_ON(!sig->data); + + ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID, + SM2_DEFAULT_USERID_LEN, dgst); + if (ret) + return ret; + + tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) + goto error_free_tfm; + + desc->tfm = tfm; + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error_free_desc; + + ret = crypto_shash_update(desc, dgst, SM3_DIGEST_SIZE); + if (ret < 0) + goto error_free_desc; + + ret = crypto_shash_finup(desc, sig->data, sig->data_size, sig->digest); + +error_free_desc: + kfree(desc); +error_free_tfm: + crypto_free_shash(tfm); + return ret; +} + +#endif /* ! IS_REACHABLE(CONFIG_CRYPTO_SM2) */ diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index d964cc82b69c..ae450eb8be14 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -30,6 +30,9 @@ int x509_get_sig_params(struct x509_certificate *cert) pr_devel("==>%s()\n", __func__); + sig->data = cert->tbs; + sig->data_size = cert->tbs_size; + if (!cert->pub->pkey_algo) cert->unsupported_key = true; -- cgit v1.2.3 From 524ccdbdfb52608e9b98fcd64f4337add7009f41 Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 26 Sep 2020 12:26:50 +0200 Subject: crypto: xor - defer load time benchmark to a later time Currently, the XOR module performs its boot time benchmark at core initcall time when it is built-in, to ensure that the RAID code can make use of it when it is built-in as well. Let's defer this to a later stage during the boot, to avoid impacting the overall boot time of the system. Instead, just pick an arbitrary implementation from the list, and use that as the preliminary default. Reviewed-by: Douglas Anderson Signed-off-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/xor.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/xor.c b/crypto/xor.c index ea7349e6ed23..b42c38343733 100644 --- a/crypto/xor.c +++ b/crypto/xor.c @@ -54,6 +54,28 @@ EXPORT_SYMBOL(xor_blocks); /* Set of all registered templates. */ static struct xor_block_template *__initdata template_list; +#ifndef MODULE +static void __init do_xor_register(struct xor_block_template *tmpl) +{ + tmpl->next = template_list; + template_list = tmpl; +} + +static int __init register_xor_blocks(void) +{ + active_template = XOR_SELECT_TEMPLATE(NULL); + + if (!active_template) { +#define xor_speed do_xor_register + // register all the templates and pick the first as the default + XOR_TRY_TEMPLATES; +#undef xor_speed + active_template = template_list; + } + return 0; +} +#endif + #define BENCH_SIZE (PAGE_SIZE) static void __init @@ -129,6 +151,7 @@ calibrate_xor_blocks(void) #define xor_speed(templ) do_xor_speed((templ), b1, b2) printk(KERN_INFO "xor: measuring software checksum speed\n"); + template_list = NULL; XOR_TRY_TEMPLATES; fastest = template_list; for (f = fastest; f; f = f->next) @@ -150,6 +173,10 @@ static __exit void xor_exit(void) { } MODULE_LICENSE("GPL"); +#ifndef MODULE /* when built-in xor.o must initialize before drivers/md/md.o */ -core_initcall(calibrate_xor_blocks); +core_initcall(register_xor_blocks); +#endif + +module_init(calibrate_xor_blocks); module_exit(xor_exit); -- cgit v1.2.3 From c055e3eae0f133d98e9c66ad136eefd811701b3a Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Sat, 26 Sep 2020 12:26:51 +0200 Subject: crypto: xor - use ktime for template benchmarking Currently, we use the jiffies counter as a time source, by staring at it until a HZ period elapses, and then staring at it again and perform as many XOR operations as we can at the same time until another HZ period elapses, so that we can calculate the throughput. This takes longer than necessary, and depends on HZ, which is undesirable, since HZ is system dependent. Let's use the ktime interface instead, and use it to time a fixed number of XOR operations, which can be done much faster, and makes the time spent depend on the performance level of the system itself, which is much more reasonable. To ensure that we have the resolution we need even on systems with 32 kHz time sources, while not spending too much time in the benchmark on a slow CPU, let's switch to 3 attempts of 800 repetitions each: that way, we will only misidentify algorithms that perform within 10% of each other as the fastest if they are faster than 10 GB/s to begin with, which is not expected to occur on systems with such coarse clocks. On ThunderX2, I get the following results: Before: [72625.956765] xor: measuring software checksum speed [72625.993104] 8regs : 10169.000 MB/sec [72626.033099] 32regs : 12050.000 MB/sec [72626.073095] arm64_neon: 11100.000 MB/sec [72626.073097] xor: using function: 32regs (12050.000 MB/sec) After: [72599.650216] xor: measuring software checksum speed [72599.651188] 8regs : 10491 MB/sec [72599.652006] 32regs : 12345 MB/sec [72599.652871] arm64_neon : 11402 MB/sec [72599.652873] xor: using function: 32regs (12345 MB/sec) Link: https://lore.kernel.org/linux-crypto/20200923182230.22715-3-ardb@kernel.org/ Signed-off-by: Ard Biesheuvel Reviewed-by: Douglas Anderson Signed-off-by: Herbert Xu --- crypto/xor.c | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'crypto') diff --git a/crypto/xor.c b/crypto/xor.c index b42c38343733..a0badbc03577 100644 --- a/crypto/xor.c +++ b/crypto/xor.c @@ -76,49 +76,43 @@ static int __init register_xor_blocks(void) } #endif -#define BENCH_SIZE (PAGE_SIZE) +#define BENCH_SIZE 4096 +#define REPS 800U static void __init do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) { int speed; - unsigned long now, j; - int i, count, max; + int i, j, count; + ktime_t min, start, diff; tmpl->next = template_list; template_list = tmpl; preempt_disable(); - /* - * Count the number of XORs done during a whole jiffy, and use - * this to calculate the speed of checksumming. We use a 2-page - * allocation to have guaranteed color L1-cache layout. - */ - max = 0; - for (i = 0; i < 5; i++) { - j = jiffies; - count = 0; - while ((now = jiffies) == j) - cpu_relax(); - while (time_before(jiffies, now + 1)) { + min = (ktime_t)S64_MAX; + for (i = 0; i < 3; i++) { + start = ktime_get(); + for (j = 0; j < REPS; j++) { mb(); /* prevent loop optimzation */ tmpl->do_2(BENCH_SIZE, b1, b2); mb(); count++; mb(); } - if (count > max) - max = count; + diff = ktime_sub(ktime_get(), start); + if (diff < min) + min = diff; } preempt_enable(); - speed = max * (HZ * BENCH_SIZE / 1024); + // bytes/ns == GB/s, multiply by 1000 to get MB/s [not MiB/s] + speed = (1000 * REPS * BENCH_SIZE) / (unsigned int)ktime_to_ns(min); tmpl->speed = speed; - printk(KERN_INFO " %-10s: %5d.%03d MB/sec\n", tmpl->name, - speed / 1000, speed % 1000); + pr_info(" %-16s: %5d MB/sec\n", tmpl->name, speed); } static int __init @@ -158,8 +152,8 @@ calibrate_xor_blocks(void) if (f->speed > fastest->speed) fastest = f; - printk(KERN_INFO "xor: using function: %s (%d.%03d MB/sec)\n", - fastest->name, fastest->speed / 1000, fastest->speed % 1000); + pr_info("xor: using function: %s (%d MB/sec)\n", + fastest->name, fastest->speed); #undef xor_speed -- cgit v1.2.3 From 4f28945da0c502c794eb4e4d535d3ba65d3c9769 Mon Sep 17 00:00:00 2001 From: Tianjia Zhang Date: Mon, 5 Oct 2020 22:46:28 +0800 Subject: X.509: fix error return value on the failed path When memory allocation fails, an appropriate return value should be set. Fixes: 215525639631 ("X.509: support OSCCA SM2-with-SM3 certificate verification") Signed-off-by: Tianjia Zhang Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/public_key_sm2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'crypto') diff --git a/crypto/asymmetric_keys/public_key_sm2.c b/crypto/asymmetric_keys/public_key_sm2.c index 7325cf21dbb4..66b614e1eccd 100644 --- a/crypto/asymmetric_keys/public_key_sm2.c +++ b/crypto/asymmetric_keys/public_key_sm2.c @@ -36,8 +36,10 @@ int cert_sig_digest_update(const struct public_key_signature *sig, desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); desc = kzalloc(desc_size, GFP_KERNEL); - if (!desc) + if (!desc) { + ret = -ENOMEM; goto error_free_tfm; + } desc->tfm = tfm; -- cgit v1.2.3 From 10b0f78a73237181260fc3661577d59b475f8a20 Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 6 Oct 2020 12:58:48 -0700 Subject: crypto: xor - Remove unused variable count in do_xor_speed Clang warns: crypto/xor.c:101:4: warning: variable 'count' is uninitialized when used here [-Wuninitialized] count++; ^~~~~ crypto/xor.c:86:17: note: initialize the variable 'count' to silence this warning int i, j, count; ^ = 0 1 warning generated. After the refactoring to use ktime that happened in this function, count is only assigned, never read. Just remove the variable to get rid of the warning. Fixes: c055e3eae0f1 ("crypto: xor - use ktime for template benchmarking") Link: https://github.com/ClangBuiltLinux/linux/issues/1171 Signed-off-by: Nathan Chancellor Reviewed-by: Douglas Anderson Acked-by: Ard Biesheuvel Signed-off-by: Herbert Xu --- crypto/xor.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'crypto') diff --git a/crypto/xor.c b/crypto/xor.c index a0badbc03577..eacbf4f93990 100644 --- a/crypto/xor.c +++ b/crypto/xor.c @@ -83,7 +83,7 @@ static void __init do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) { int speed; - int i, j, count; + int i, j; ktime_t min, start, diff; tmpl->next = template_list; @@ -98,8 +98,6 @@ do_xor_speed(struct xor_block_template *tmpl, void *b1, void *b2) mb(); /* prevent loop optimzation */ tmpl->do_2(BENCH_SIZE, b1, b2); mb(); - count++; - mb(); } diff = ktime_sub(ktime_get(), start); if (diff < min) -- cgit v1.2.3 From 3093e7c16e12d729c325adb3c53dde7308cefbd8 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 7 Oct 2020 17:05:45 +1100 Subject: X.509: Fix modular build of public_key_sm2 The sm2 code was split out of public_key.c in a way that breaks modular builds. This patch moves the code back into the same file as the original motivation was to minimise ifdefs and that has nothing to do with splitting the code out. Fixes: 215525639631 ("X.509: support OSCCA SM2-with-SM3...") Reported-by: kernel test robot Signed-off-by: Herbert Xu --- crypto/asymmetric_keys/Makefile | 1 - crypto/asymmetric_keys/public_key.c | 57 +++++++++++++++++++++++++++++ crypto/asymmetric_keys/public_key_sm2.c | 63 --------------------------------- 3 files changed, 57 insertions(+), 64 deletions(-) delete mode 100644 crypto/asymmetric_keys/public_key_sm2.c (limited to 'crypto') diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index 1a99ea5acb6b..28b91adba2ae 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -11,7 +11,6 @@ asymmetric_keys-y := \ signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key_sm2.o obj-$(CONFIG_ASYMMETRIC_TPM_KEY_SUBTYPE) += asym_tpm.o # diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 1d0492098bbd..8892908ad58c 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include MODULE_DESCRIPTION("In-software asymmetric public-key subtype"); MODULE_AUTHOR("Red Hat, Inc."); @@ -246,6 +248,61 @@ error_free_tfm: return ret; } +#if IS_REACHABLE(CONFIG_CRYPTO_SM2) +static int cert_sig_digest_update(const struct public_key_signature *sig, + struct crypto_akcipher *tfm_pkey) +{ + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t desc_size; + unsigned char dgst[SM3_DIGEST_SIZE]; + int ret; + + BUG_ON(!sig->data); + + ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID, + SM2_DEFAULT_USERID_LEN, dgst); + if (ret) + return ret; + + tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) { + ret = -ENOMEM; + goto error_free_tfm; + } + + desc->tfm = tfm; + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error_free_desc; + + ret = crypto_shash_update(desc, dgst, SM3_DIGEST_SIZE); + if (ret < 0) + goto error_free_desc; + + ret = crypto_shash_finup(desc, sig->data, sig->data_size, sig->digest); + +error_free_desc: + kfree(desc); +error_free_tfm: + crypto_free_shash(tfm); + return ret; +} +#else +static inline int cert_sig_digest_update( + const struct public_key_signature *sig, + struct crypto_akcipher *tfm_pkey) +{ + return -ENOTSUPP; +} +#endif /* ! IS_REACHABLE(CONFIG_CRYPTO_SM2) */ + /* * Verify a signature using a public key. */ diff --git a/crypto/asymmetric_keys/public_key_sm2.c b/crypto/asymmetric_keys/public_key_sm2.c deleted file mode 100644 index 66b614e1eccd..000000000000 --- a/crypto/asymmetric_keys/public_key_sm2.c +++ /dev/null @@ -1,63 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * asymmetric public-key algorithm for SM2-with-SM3 certificate - * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and - * described at https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02 - * - * Copyright (c) 2020, Alibaba Group. - * Authors: Tianjia Zhang - */ - -#include -#include -#include - -#if IS_REACHABLE(CONFIG_CRYPTO_SM2) - -int cert_sig_digest_update(const struct public_key_signature *sig, - struct crypto_akcipher *tfm_pkey) -{ - struct crypto_shash *tfm; - struct shash_desc *desc; - size_t desc_size; - unsigned char dgst[SM3_DIGEST_SIZE]; - int ret; - - BUG_ON(!sig->data); - - ret = sm2_compute_z_digest(tfm_pkey, SM2_DEFAULT_USERID, - SM2_DEFAULT_USERID_LEN, dgst); - if (ret) - return ret; - - tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); - if (IS_ERR(tfm)) - return PTR_ERR(tfm); - - desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); - desc = kzalloc(desc_size, GFP_KERNEL); - if (!desc) { - ret = -ENOMEM; - goto error_free_tfm; - } - - desc->tfm = tfm; - - ret = crypto_shash_init(desc); - if (ret < 0) - goto error_free_desc; - - ret = crypto_shash_update(desc, dgst, SM3_DIGEST_SIZE); - if (ret < 0) - goto error_free_desc; - - ret = crypto_shash_finup(desc, sig->data, sig->data_size, sig->digest); - -error_free_desc: - kfree(desc); -error_free_tfm: - crypto_free_shash(tfm); - return ret; -} - -#endif /* ! IS_REACHABLE(CONFIG_CRYPTO_SM2) */ -- cgit v1.2.3