From nobody Fri Dec 19 08:03:55 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 65BBDC00140 for ; Wed, 24 Aug 2022 09:51:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236461AbiHXJvC (ORCPT ); Wed, 24 Aug 2022 05:51:02 -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> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" 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) +=3D ycc.o -ycc-objs :=3D ycc_drv.o ycc_isr.o ycc_cdev.o ycc_ring.o ycc_ske.o ycc_aead= .o ycc_pke.o +ycc-objs :=3D 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/sm= 2signature_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 =3D 0, + ACT_sm2_get_signature_s =3D 1, + NR__sm2signature_actions =3D 2 +}; + +static const asn1_action_t sm2signature_action_table[NR__sm2signature_acti= ons] =3D { + [0] =3D sm2_get_signature_r, + [1] =3D sm2_get_signature_s, +}; + +static const unsigned char sm2signature_machine[] =3D { + // Sm2Signature + [0] =3D ASN1_OP_MATCH, + [1] =3D _tag(UNIV, CONS, SEQ), + [2] =3D ASN1_OP_MATCH_ACT, // sig_r + [3] =3D _tag(UNIV, PRIM, INT), + [4] =3D _action(ACT_sm2_get_signature_r), + [5] =3D ASN1_OP_MATCH_ACT, // sig_s + [6] =3D _tag(UNIV, PRIM, INT), + [7] =3D _action(ACT_sm2_get_signature_s), + [8] =3D ASN1_OP_END_SEQ, + [9] =3D ASN1_OP_COMPLETE, +}; + +const struct asn1_decoder sm2signature_decoder =3D { + .machine =3D sm2signature_machine, + .machlen =3D sizeof(sm2signature_machine), + .actions =3D sm2signature_action_table, +}; diff --git a/drivers/crypto/ycc/sm2signature_asn1.h b/drivers/crypto/ycc/sm= 2signature_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 */ =20 + YCC_CMD_SM2_VERIFY =3D 0x47, + YCC_CMD_RSA_ENC =3D 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" =20 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); } =20 +#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 =3D (struct ycc_pke_req *)ptr; + struct ycc_pke_ctx *ctx =3D sm2_req->ctx; + struct akcipher_request *req =3D sm2_req->req; + struct device *dev =3D 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 =3D=3D 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 =3D context; + + if (!value || !vlen) + return -EINVAL; + + sig->sig_r =3D 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 =3D context; + + if (!value || !vlen) + return -EINVAL; + + sig->sig_s =3D 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 =3D crypto_akcipher_reqtfm(req); + struct ycc_pke_req *sm2_req =3D akcipher_request_ctx(req); + struct ycc_pke_ctx *ctx =3D akcipher_tfm_ctx(tfm); + struct ycc_sm2_verify_cmd *sm2_verify_cmd; + struct ycc_dev *ydev =3D ctx->ring->ydev; + struct ycc_ring *ring =3D ctx->ring; + struct device *dev =3D YCC_DEV(ctx); + struct sm2_signature_ctx sig; + struct ycc_flags *aflags; + u8 buffer[80] =3D {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 =3D crypto_akcipher_verify(req); + akcipher_request_set_tfm(req, tfm); + return ret; + } + + if (req->src_len > 72 || req->src_len < 70 || req->dst_len !=3D 32) + return -EINVAL; + + sm2_req->ctx =3D ctx; + sm2_req->req =3D req; + + sg_copy_buffer(req->src, sg_nents(req->src), buffer, req->src_len, 0, 1); + sig.sig_r =3D NULL; + sig.sig_s =3D NULL; + ret =3D asn1_ber_decoder(&sm2signature_decoder, &sig, buffer, req->src_le= n); + if (ret) + return -EINVAL; + + ret =3D mpi_print(GCRYMPI_FMT_USG, buffer, MPI_NBYTES(sig.sig_r), + (size_t *)NULL, sig.sig_r); + if (ret) + return -EINVAL; + + ret =3D 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 =3D -ENOMEM; + /* Alloc dma for src, as verify has no output */ + sm2_req->src_vaddr =3D 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 =3D NULL; + + aflags =3D kzalloc(sizeof(struct ycc_flags), GFP_ATOMIC); + if (!aflags) + goto free_src; + + aflags->ptr =3D (void *)sm2_req; + aflags->ycc_done_callback =3D ycc_sm2_done_callback; + + memset(&sm2_req->desc, 0, sizeof(sm2_req->desc)); + sm2_req->desc.private_ptr =3D (u64)(void *)aflags; + + sm2_verify_cmd =3D &sm2_req->desc.cmd.sm2_verify_cmd; + sm2_verify_cmd->cmd_id =3D YCC_CMD_SM2_VERIFY; + sm2_verify_cmd->sptr =3D sm2_req->src_paddr; + sm2_verify_cmd->keyptr =3D ctx->pub_key_paddr; + + ret =3D 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 =3D akcipher_tfm_ctx(tfm); + struct device *dev =3D YCC_DEV(ctx); + int ret; + + ret =3D 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 =3D 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 !=3D 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 =3D akcipher_tfm_ctx(tfm); + struct ycc_ring *ring; + + ctx->soft_tfm =3D 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 =3D ycc_crypto_get_ring(); + if (!ring) { + crypto_free_akcipher(ctx->soft_tfm); + return -ENODEV; + } + + ctx->ring =3D ring; + return 0; +} + +static void ycc_sm2_exit(struct crypto_akcipher *tfm) +{ + struct ycc_pke_ctx *ctx =3D akcipher_tfm_ctx(tfm); + struct device *dev =3D 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 =3D { .base =3D { .cra_name =3D "rsa", @@ -685,12 +903,42 @@ static void ycc_rsa_exit(struct crypto_akcipher *tfm) .exit =3D ycc_rsa_exit, }; =20 +static struct akcipher_alg ycc_sm2 =3D { + .base =3D { + .cra_name =3D "sm2", + .cra_driver_name =3D "ycc-sm2", + .cra_priority =3D 1000, + .cra_module =3D THIS_MODULE, + .cra_ctxsize =3D sizeof(struct ycc_pke_ctx), + }, + .verify =3D ycc_sm2_verify, + .set_pub_key =3D ycc_sm2_setpubkey, + .max_size =3D ycc_sm2_max_size, + .init =3D ycc_sm2_init, + .exit =3D ycc_sm2_exit, +}; + int ycc_pke_register(void) { - return crypto_register_akcipher(&ycc_rsa); + int ret; + + ret =3D crypto_register_akcipher(&ycc_rsa); + if (ret) { + pr_err("Failed to register rsa\n"); + return ret; + } + + ret =3D crypto_register_akcipher(&ycc_sm2); + if (ret) { + crypto_unregister_akcipher(&ycc_rsa); + pr_err("Failed to register sm2\n"); + } + + return ret; } =20 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; =20 +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]; }; =20 --=20 1.8.3.1