Received: by 2002:a05:6358:45e:b0:b5:b6eb:e1f9 with SMTP id 30csp391286rwe; Wed, 24 Aug 2022 02:51:37 -0700 (PDT) X-Google-Smtp-Source: AA6agR6kGl7znl2+kJ+uOT6gLqwk/wFwjcF2t5I9QcnL5PlZLjenlF3DqYkEWTrWBESE/nHii3np X-Received: by 2002:a17:90b:3b8e:b0:1fb:830a:67a9 with SMTP id pc14-20020a17090b3b8e00b001fb830a67a9mr1820164pjb.205.1661334697164; Wed, 24 Aug 2022 02:51:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1661334697; cv=none; d=google.com; s=arc-20160816; b=j+icT0t2/iJNo32t98yfqgizX9RwojVrBW1sD0jQ4cSN1Stm+h9BMko206KR3QIblK 2tUkPJmpLZwhegunr3/HURYlIaIPOQx+wvd9WCCT/VfQV2mvE6hhz5zVEMtNN1PejwlA WxYpTtwYy0qcN9vluSREMBSviSohWnGXCfeXxHMrxz8vz3mkImG/RGacvYavqPJmS7Xw ZuOXci1iO7IS32GTzhvDxxv/RnC/ZA3zhhKn7ZtVZcQEjHaZwN2U/S02ujLUVap6CwVK z3e9E9sQVQRHF40oU1LzuanNoYU5CK5Yr6lmY1ztXpxpT7IRpay12rFxrIQ+8haKnj0v 9TKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:references:in-reply-to:message-id:date:subject :cc:to:from; bh=uBmtIaGtj3V2nIOANYnXvkrsxU0WD4PrJO84uijLT/E=; b=qT3fYV7frkMbAvSvFymKQgsOvXGXVe7CU9udV/ey2kiSrBNBhw2slVvcV9zNsDJP/J ed04WIdJ7yi15Oct2cKUYrSXyextPejZ7loLhJySgAg+vGLYHSwtsPLF4T6Wc/11AOzm TwBsNqA5LkN0NFPofz6OqWDwYPmFdlHVUHqrCI4pI0uuV3K+saQFSF09DeMIx1LJuaKp dsIEkqWSZKA0Qw+OZ8QZ7b3xR5uHa1e9agb1IIn+MN7L3kPB7IuXeWtBgp8R8uw8mf5I VKsOQggSxRivS+Csq2FHXnYEwxDquzzX9AWDud4Dx/hhfvwAlNaUCewxaqyEe2thzTmz kajA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id d4-20020aa797a4000000b005303194bf1bsi7895936pfq.111.2022.08.24.02.51.22; Wed, 24 Aug 2022 02:51:37 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-crypto-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-crypto-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=alibaba.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S235794AbiHXJul (ORCPT + 99 others); Wed, 24 Aug 2022 05:50:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36320 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236242AbiHXJue (ORCPT ); Wed, 24 Aug 2022 05:50:34 -0400 Received: from out30-43.freemail.mail.aliyun.com (out30-43.freemail.mail.aliyun.com [115.124.30.43]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DBEF03F1CC; Wed, 24 Aug 2022 02:50:30 -0700 (PDT) X-Alimail-AntiSpam: AC=PASS;BC=-1|-1;BR=01201311R181e4;CH=green;DM=||false|;DS=||;FP=0|-1|-1|-1|0|-1|-1|-1;HT=ay29a033018045176;MF=guanjun@linux.alibaba.com;NM=1;PH=DS;RN=7;SR=0;TI=SMTPD_---0VN7.oJx_1661334628; Received: from localhost(mailfrom:guanjun@linux.alibaba.com fp:SMTPD_---0VN7.oJx_1661334628) by smtp.aliyun-inc.com; Wed, 24 Aug 2022 17:50:28 +0800 From: 'Guanjun' To: herbert@gondor.apana.org.au Cc: zelin.deng@linux.alibaba.com, guanjun@linux.alibaba.com, xuchun.shang@linux.alibaba.com, artie.ding@linux.alibaba.com, linux-crypto@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v1 8/9] crypto/ycc: Add sm2 algorithm support Date: Wed, 24 Aug 2022 17:50:20 +0800 Message-Id: <1661334621-44413-9-git-send-email-guanjun@linux.alibaba.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1661334621-44413-1-git-send-email-guanjun@linux.alibaba.com> References: <1661334621-44413-1-git-send-email-guanjun@linux.alibaba.com> X-Spam-Status: No, score=-9.9 required=5.0 tests=BAYES_00, ENV_AND_HDR_SPF_MATCH,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE,UNPARSEABLE_RELAY, USER_IN_DEF_SPF_WL autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-crypto@vger.kernel.org From: Xuchun Shang Only support verification through sm2 at present. Signed-off-by: Xuchun Shang --- drivers/crypto/ycc/Makefile | 3 +- drivers/crypto/ycc/sm2signature_asn1.c | 38 +++++ drivers/crypto/ycc/sm2signature_asn1.h | 13 ++ drivers/crypto/ycc/ycc_algs.h | 2 + drivers/crypto/ycc/ycc_pke.c | 250 ++++++++++++++++++++++++++++++++- drivers/crypto/ycc/ycc_ring.h | 8 ++ 6 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 drivers/crypto/ycc/sm2signature_asn1.c create mode 100644 drivers/crypto/ycc/sm2signature_asn1.h diff --git a/drivers/crypto/ycc/Makefile b/drivers/crypto/ycc/Makefile index 89d6d6f..4f95c7f 100644 --- a/drivers/crypto/ycc/Makefile +++ b/drivers/crypto/ycc/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-(CONFIG_CRYPTO_DEV_YCC) += ycc.o -ycc-objs := ycc_drv.o ycc_isr.o ycc_cdev.o ycc_ring.o ycc_ske.o ycc_aead.o ycc_pke.o +ycc-objs := ycc_drv.o ycc_isr.o ycc_cdev.o ycc_ring.o ycc_ske.o ycc_aead.o \ + ycc_pke.o sm2signature_asn1.o diff --git a/drivers/crypto/ycc/sm2signature_asn1.c b/drivers/crypto/ycc/sm2signature_asn1.c new file mode 100644 index 00000000..1fd15c1 --- /dev/null +++ b/drivers/crypto/ycc/sm2signature_asn1.c @@ -0,0 +1,38 @@ +/* + * Automatically generated by asn1_compiler. Do not edit + * + * ASN.1 parser for sm2signature + */ +#include +#include "sm2signature_asn1.h" + +enum sm2signature_actions { + ACT_sm2_get_signature_r = 0, + ACT_sm2_get_signature_s = 1, + NR__sm2signature_actions = 2 +}; + +static const asn1_action_t sm2signature_action_table[NR__sm2signature_actions] = { + [0] = sm2_get_signature_r, + [1] = sm2_get_signature_s, +}; + +static const unsigned char sm2signature_machine[] = { + // Sm2Signature + [0] = ASN1_OP_MATCH, + [1] = _tag(UNIV, CONS, SEQ), + [2] = ASN1_OP_MATCH_ACT, // sig_r + [3] = _tag(UNIV, PRIM, INT), + [4] = _action(ACT_sm2_get_signature_r), + [5] = ASN1_OP_MATCH_ACT, // sig_s + [6] = _tag(UNIV, PRIM, INT), + [7] = _action(ACT_sm2_get_signature_s), + [8] = ASN1_OP_END_SEQ, + [9] = ASN1_OP_COMPLETE, +}; + +const struct asn1_decoder sm2signature_decoder = { + .machine = sm2signature_machine, + .machlen = sizeof(sm2signature_machine), + .actions = sm2signature_action_table, +}; diff --git a/drivers/crypto/ycc/sm2signature_asn1.h b/drivers/crypto/ycc/sm2signature_asn1.h new file mode 100644 index 00000000..192c9e1 --- /dev/null +++ b/drivers/crypto/ycc/sm2signature_asn1.h @@ -0,0 +1,13 @@ +/* + * Automatically generated by asn1_compiler. Do not edit + * + * ASN.1 parser for sm2signature + */ +#include + +extern const struct asn1_decoder sm2signature_decoder; + +extern int sm2_get_signature_r(void *context, size_t hdrlen, + unsigned char tag, const void *value, size_t vlen); +extern int sm2_get_signature_s(void *context, size_t hdrlen, + unsigned char tag, const void *value, size_t vlen); diff --git a/drivers/crypto/ycc/ycc_algs.h b/drivers/crypto/ycc/ycc_algs.h index 6a13230a..26323a8 100644 --- a/drivers/crypto/ycc/ycc_algs.h +++ b/drivers/crypto/ycc/ycc_algs.h @@ -77,6 +77,8 @@ enum ycc_cmd_id { YCC_CMD_CCM_ENC, YCC_CMD_CCM_DEC, /* 0x28 */ + YCC_CMD_SM2_VERIFY = 0x47, + YCC_CMD_RSA_ENC = 0x83, YCC_CMD_RSA_DEC, YCC_CMD_RSA_CRT_DEC, diff --git a/drivers/crypto/ycc/ycc_pke.c b/drivers/crypto/ycc/ycc_pke.c index 559f7f7..23e84ca 100644 --- a/drivers/crypto/ycc/ycc_pke.c +++ b/drivers/crypto/ycc/ycc_pke.c @@ -8,6 +8,8 @@ #include #include #include + +#include "sm2signature_asn1.h" #include "ycc_algs.h" static int ycc_rsa_done_callback(void *ptr, u16 state) @@ -666,6 +668,222 @@ static void ycc_rsa_exit(struct crypto_akcipher *tfm) crypto_free_akcipher(ctx->soft_tfm); } +#define MPI_NBYTES(m) ((mpi_get_nbits(m) + 7) / 8) + +static int ycc_sm2_done_callback(void *ptr, u16 state) +{ + struct ycc_pke_req *sm2_req = (struct ycc_pke_req *)ptr; + struct ycc_pke_ctx *ctx = sm2_req->ctx; + struct akcipher_request *req = sm2_req->req; + struct device *dev = YCC_DEV(ctx); + + dma_free_coherent(dev, 128, sm2_req->src_vaddr, sm2_req->src_paddr); + + if (req->base.complete) + req->base.complete(&req->base, state == CMD_SUCCESS ? 0 : -EBADMSG); + 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 ycc_sm2_verify(struct akcipher_request *req) +{ + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); + struct ycc_pke_req *sm2_req = akcipher_request_ctx(req); + struct ycc_pke_ctx *ctx = akcipher_tfm_ctx(tfm); + struct ycc_sm2_verify_cmd *sm2_verify_cmd; + struct ycc_dev *ydev = ctx->ring->ydev; + struct ycc_ring *ring = ctx->ring; + struct device *dev = YCC_DEV(ctx); + struct sm2_signature_ctx sig; + struct ycc_flags *aflags; + u8 buffer[80] = {0}; + int ret; + + /* Do software fallback */ + if (!test_bit(YDEV_STATUS_READY, &ydev->status) || ctx->key_len) { + akcipher_request_set_tfm(req, ctx->soft_tfm); + ret = crypto_akcipher_verify(req); + akcipher_request_set_tfm(req, tfm); + return ret; + } + + if (req->src_len > 72 || req->src_len < 70 || req->dst_len != 32) + return -EINVAL; + + sm2_req->ctx = ctx; + sm2_req->req = req; + + sg_copy_buffer(req->src, sg_nents(req->src), buffer, req->src_len, 0, 1); + sig.sig_r = NULL; + sig.sig_s = NULL; + ret = asn1_ber_decoder(&sm2signature_decoder, &sig, buffer, req->src_len); + if (ret) + return -EINVAL; + + ret = mpi_print(GCRYMPI_FMT_USG, buffer, MPI_NBYTES(sig.sig_r), + (size_t *)NULL, sig.sig_r); + if (ret) + return -EINVAL; + + ret = mpi_print(GCRYMPI_FMT_USG, buffer + MPI_NBYTES(sig.sig_r), + MPI_NBYTES(sig.sig_s), (size_t *)NULL, sig.sig_s); + if (ret) + return -EINVAL; + + ret = -ENOMEM; + /* Alloc dma for src, as verify has no output */ + sm2_req->src_vaddr = dma_alloc_coherent(dev, 128, &sm2_req->src_paddr, + GFP_ATOMIC); + if (!sm2_req->src_vaddr) + goto out; + + sg_copy_buffer(req->src, sg_nents(req->src), sm2_req->src_vaddr, + req->dst_len, req->src_len, 1); + memcpy(sm2_req->src_vaddr + 32, buffer, 64); + + sm2_req->dst_vaddr = NULL; + + aflags = kzalloc(sizeof(struct ycc_flags), GFP_ATOMIC); + if (!aflags) + goto free_src; + + aflags->ptr = (void *)sm2_req; + aflags->ycc_done_callback = ycc_sm2_done_callback; + + memset(&sm2_req->desc, 0, sizeof(sm2_req->desc)); + sm2_req->desc.private_ptr = (u64)(void *)aflags; + + sm2_verify_cmd = &sm2_req->desc.cmd.sm2_verify_cmd; + sm2_verify_cmd->cmd_id = YCC_CMD_SM2_VERIFY; + sm2_verify_cmd->sptr = sm2_req->src_paddr; + sm2_verify_cmd->keyptr = ctx->pub_key_paddr; + + ret = ycc_enqueue(ring, (u8 *)&sm2_req->desc); + if (!ret) + return -EINPROGRESS; + + kfree(aflags); +free_src: + dma_free_coherent(dev, 128, sm2_req->src_vaddr, sm2_req->src_paddr); +out: + return ret; +} + +static unsigned int ycc_sm2_max_size(struct crypto_akcipher *tfm) +{ + return PAGE_SIZE; +} + +static int ycc_sm2_setpubkey(struct crypto_akcipher *tfm, const void *key, + unsigned int keylen) +{ + struct ycc_pke_ctx *ctx = akcipher_tfm_ctx(tfm); + struct device *dev = YCC_DEV(ctx); + int ret; + + ret = crypto_akcipher_set_pub_key(ctx->soft_tfm, key, keylen); + if (ret) + return ret; + + /* Always alloc 64 bytes for pub key */ + ctx->pub_key_vaddr = dma_alloc_coherent(dev, 64, &ctx->pub_key_paddr, + GFP_KERNEL); + if (!ctx->pub_key_vaddr) + return -ENOMEM; + + /* + * Uncompressed key 65 bytes with 0x04 flag + * Compressed key 33 bytes with 0x02 or 0x03 flag + */ + switch (keylen) { + case 65: + if (*(u8 *)key != 0x04) + return -EINVAL; + memcpy(ctx->pub_key_vaddr, key + 1, 64); + break; + case 64: + memcpy(ctx->pub_key_vaddr, key, 64); + break; + case 33: + return 0; /* TODO: use sw temporary */ + default: + return -EINVAL; + } + + return 0; +} + +static int ycc_sm2_init(struct crypto_akcipher *tfm) +{ + struct ycc_pke_ctx *ctx = akcipher_tfm_ctx(tfm); + struct ycc_ring *ring; + + ctx->soft_tfm = crypto_alloc_akcipher("sm2-generic", 0, 0); + if (IS_ERR(ctx->soft_tfm)) + return PTR_ERR(ctx->soft_tfm); + + /* Reserve enough space if soft request reqires additional space */ + akcipher_set_reqsize(tfm, sizeof(struct ycc_pke_req) + + crypto_akcipher_alg(ctx->soft_tfm)->reqsize); + + ring = ycc_crypto_get_ring(); + if (!ring) { + crypto_free_akcipher(ctx->soft_tfm); + return -ENODEV; + } + + ctx->ring = ring; + return 0; +} + +static void ycc_sm2_exit(struct crypto_akcipher *tfm) +{ + struct ycc_pke_ctx *ctx = akcipher_tfm_ctx(tfm); + struct device *dev = YCC_DEV(ctx); + + if (ctx->ring) + ycc_crypto_free_ring(ctx->ring); + + if (ctx->pub_key_vaddr) + dma_free_coherent(dev, 64, ctx->pub_key_vaddr, ctx->pub_key_paddr); + + crypto_free_akcipher(ctx->soft_tfm); +} + static struct akcipher_alg ycc_rsa = { .base = { .cra_name = "rsa", @@ -685,12 +903,42 @@ static void ycc_rsa_exit(struct crypto_akcipher *tfm) .exit = ycc_rsa_exit, }; +static struct akcipher_alg ycc_sm2 = { + .base = { + .cra_name = "sm2", + .cra_driver_name = "ycc-sm2", + .cra_priority = 1000, + .cra_module = THIS_MODULE, + .cra_ctxsize = sizeof(struct ycc_pke_ctx), + }, + .verify = ycc_sm2_verify, + .set_pub_key = ycc_sm2_setpubkey, + .max_size = ycc_sm2_max_size, + .init = ycc_sm2_init, + .exit = ycc_sm2_exit, +}; + int ycc_pke_register(void) { - return crypto_register_akcipher(&ycc_rsa); + int ret; + + ret = crypto_register_akcipher(&ycc_rsa); + if (ret) { + pr_err("Failed to register rsa\n"); + return ret; + } + + ret = crypto_register_akcipher(&ycc_sm2); + if (ret) { + crypto_unregister_akcipher(&ycc_rsa); + pr_err("Failed to register sm2\n"); + } + + return ret; } void ycc_pke_unregister(void) { crypto_unregister_akcipher(&ycc_rsa); + crypto_unregister_akcipher(&ycc_sm2); } diff --git a/drivers/crypto/ycc/ycc_ring.h b/drivers/crypto/ycc/ycc_ring.h index c47fc18..6dafdc7 100644 --- a/drivers/crypto/ycc/ycc_ring.h +++ b/drivers/crypto/ycc/ycc_ring.h @@ -121,11 +121,19 @@ struct ycc_rsa_dec_cmd { u64 dptr:48; } __packed; +struct ycc_sm2_verify_cmd { + u8 cmd_id; + u64 sptr:48; + u16 key_id; + u64 keyptr:48; +} __packed; + union ycc_real_cmd { struct ycc_skcipher_cmd ske_cmd; struct ycc_aead_cmd aead_cmd; struct ycc_rsa_enc_cmd rsa_enc_cmd; struct ycc_rsa_dec_cmd rsa_dec_cmd; + struct ycc_sm2_verify_cmd sm2_verify_cmd; u8 padding[32]; }; -- 1.8.3.1