Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * SM2 asymmetric public-key algorithm
0004  * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and
0005  * described at https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
0006  *
0007  * Copyright (c) 2020, Alibaba Group.
0008  * Authors: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
0009  */
0010 
0011 #include <linux/module.h>
0012 #include <linux/mpi.h>
0013 #include <crypto/internal/akcipher.h>
0014 #include <crypto/akcipher.h>
0015 #include <crypto/hash.h>
0016 #include <crypto/sm3.h>
0017 #include <crypto/rng.h>
0018 #include <crypto/sm2.h>
0019 #include "sm2signature.asn1.h"
0020 
0021 #define MPI_NBYTES(m)   ((mpi_get_nbits(m) + 7) / 8)
0022 
0023 struct ecc_domain_parms {
0024     const char *desc;           /* Description of the curve.  */
0025     unsigned int nbits;         /* Number of bits.  */
0026     unsigned int fips:1; /* True if this is a FIPS140-2 approved curve */
0027 
0028     /* The model describing this curve.  This is mainly used to select
0029      * the group equation.
0030      */
0031     enum gcry_mpi_ec_models model;
0032 
0033     /* The actual ECC dialect used.  This is used for curve specific
0034      * optimizations and to select encodings etc.
0035      */
0036     enum ecc_dialects dialect;
0037 
0038     const char *p;              /* The prime defining the field.  */
0039     const char *a, *b;          /* The coefficients.  For Twisted Edwards
0040                      * Curves b is used for d.  For Montgomery
0041                      * Curves (a,b) has ((A-2)/4,B^-1).
0042                      */
0043     const char *n;              /* The order of the base point.  */
0044     const char *g_x, *g_y;      /* Base point.  */
0045     unsigned int h;             /* Cofactor.  */
0046 };
0047 
0048 static const struct ecc_domain_parms sm2_ecp = {
0049     .desc = "sm2p256v1",
0050     .nbits = 256,
0051     .fips = 0,
0052     .model = MPI_EC_WEIERSTRASS,
0053     .dialect = ECC_DIALECT_STANDARD,
0054     .p   = "0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",
0055     .a   = "0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",
0056     .b   = "0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",
0057     .n   = "0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",
0058     .g_x = "0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
0059     .g_y = "0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
0060     .h = 1
0061 };
0062 
0063 static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec)
0064 {
0065     const struct ecc_domain_parms *ecp = &sm2_ecp;
0066     MPI p, a, b;
0067     MPI x, y;
0068     int rc = -EINVAL;
0069 
0070     p = mpi_scanval(ecp->p);
0071     a = mpi_scanval(ecp->a);
0072     b = mpi_scanval(ecp->b);
0073     if (!p || !a || !b)
0074         goto free_p;
0075 
0076     x = mpi_scanval(ecp->g_x);
0077     y = mpi_scanval(ecp->g_y);
0078     if (!x || !y)
0079         goto free;
0080 
0081     rc = -ENOMEM;
0082 
0083     ec->Q = mpi_point_new(0);
0084     if (!ec->Q)
0085         goto free;
0086 
0087     /* mpi_ec_setup_elliptic_curve */
0088     ec->G = mpi_point_new(0);
0089     if (!ec->G) {
0090         mpi_point_release(ec->Q);
0091         goto free;
0092     }
0093 
0094     mpi_set(ec->G->x, x);
0095     mpi_set(ec->G->y, y);
0096     mpi_set_ui(ec->G->z, 1);
0097 
0098     rc = -EINVAL;
0099     ec->n = mpi_scanval(ecp->n);
0100     if (!ec->n) {
0101         mpi_point_release(ec->Q);
0102         mpi_point_release(ec->G);
0103         goto free;
0104     }
0105 
0106     ec->h = ecp->h;
0107     ec->name = ecp->desc;
0108     mpi_ec_init(ec, ecp->model, ecp->dialect, 0, p, a, b);
0109 
0110     rc = 0;
0111 
0112 free:
0113     mpi_free(x);
0114     mpi_free(y);
0115 free_p:
0116     mpi_free(p);
0117     mpi_free(a);
0118     mpi_free(b);
0119 
0120     return rc;
0121 }
0122 
0123 static void sm2_ec_ctx_deinit(struct mpi_ec_ctx *ec)
0124 {
0125     mpi_ec_deinit(ec);
0126 
0127     memset(ec, 0, sizeof(*ec));
0128 }
0129 
0130 /* RESULT must have been initialized and is set on success to the
0131  * point given by VALUE.
0132  */
0133 static int sm2_ecc_os2ec(MPI_POINT result, MPI value)
0134 {
0135     int rc;
0136     size_t n;
0137     unsigned char *buf;
0138     MPI x, y;
0139 
0140     n = MPI_NBYTES(value);
0141     buf = kmalloc(n, GFP_KERNEL);
0142     if (!buf)
0143         return -ENOMEM;
0144 
0145     rc = mpi_print(GCRYMPI_FMT_USG, buf, n, &n, value);
0146     if (rc)
0147         goto err_freebuf;
0148 
0149     rc = -EINVAL;
0150     if (n < 1 || ((n - 1) % 2))
0151         goto err_freebuf;
0152     /* No support for point compression */
0153     if (*buf != 0x4)
0154         goto err_freebuf;
0155 
0156     rc = -ENOMEM;
0157     n = (n - 1) / 2;
0158     x = mpi_read_raw_data(buf + 1, n);
0159     if (!x)
0160         goto err_freebuf;
0161     y = mpi_read_raw_data(buf + 1 + n, n);
0162     if (!y)
0163         goto err_freex;
0164 
0165     mpi_normalize(x);
0166     mpi_normalize(y);
0167     mpi_set(result->x, x);
0168     mpi_set(result->y, y);
0169     mpi_set_ui(result->z, 1);
0170 
0171     rc = 0;
0172 
0173     mpi_free(y);
0174 err_freex:
0175     mpi_free(x);
0176 err_freebuf:
0177     kfree(buf);
0178     return rc;
0179 }
0180 
0181 struct sm2_signature_ctx {
0182     MPI sig_r;
0183     MPI sig_s;
0184 };
0185 
0186 int sm2_get_signature_r(void *context, size_t hdrlen, unsigned char tag,
0187                 const void *value, size_t vlen)
0188 {
0189     struct sm2_signature_ctx *sig = context;
0190 
0191     if (!value || !vlen)
0192         return -EINVAL;
0193 
0194     sig->sig_r = mpi_read_raw_data(value, vlen);
0195     if (!sig->sig_r)
0196         return -ENOMEM;
0197 
0198     return 0;
0199 }
0200 
0201 int sm2_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
0202                 const void *value, size_t vlen)
0203 {
0204     struct sm2_signature_ctx *sig = context;
0205 
0206     if (!value || !vlen)
0207         return -EINVAL;
0208 
0209     sig->sig_s = mpi_read_raw_data(value, vlen);
0210     if (!sig->sig_s)
0211         return -ENOMEM;
0212 
0213     return 0;
0214 }
0215 
0216 static int sm2_z_digest_update(struct sm3_state *sctx,
0217             MPI m, unsigned int pbytes)
0218 {
0219     static const unsigned char zero[32];
0220     unsigned char *in;
0221     unsigned int inlen;
0222 
0223     in = mpi_get_buffer(m, &inlen, NULL);
0224     if (!in)
0225         return -EINVAL;
0226 
0227     if (inlen < pbytes) {
0228         /* padding with zero */
0229         sm3_update(sctx, zero, pbytes - inlen);
0230         sm3_update(sctx, in, inlen);
0231     } else if (inlen > pbytes) {
0232         /* skip the starting zero */
0233         sm3_update(sctx, in + inlen - pbytes, pbytes);
0234     } else {
0235         sm3_update(sctx, in, inlen);
0236     }
0237 
0238     kfree(in);
0239     return 0;
0240 }
0241 
0242 static int sm2_z_digest_update_point(struct sm3_state *sctx,
0243         MPI_POINT point, struct mpi_ec_ctx *ec, unsigned int pbytes)
0244 {
0245     MPI x, y;
0246     int ret = -EINVAL;
0247 
0248     x = mpi_new(0);
0249     y = mpi_new(0);
0250 
0251     if (!mpi_ec_get_affine(x, y, point, ec) &&
0252         !sm2_z_digest_update(sctx, x, pbytes) &&
0253         !sm2_z_digest_update(sctx, y, pbytes))
0254         ret = 0;
0255 
0256     mpi_free(x);
0257     mpi_free(y);
0258     return ret;
0259 }
0260 
0261 int sm2_compute_z_digest(struct crypto_akcipher *tfm,
0262             const unsigned char *id, size_t id_len,
0263             unsigned char dgst[SM3_DIGEST_SIZE])
0264 {
0265     struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
0266     uint16_t bits_len;
0267     unsigned char entl[2];
0268     struct sm3_state sctx;
0269     unsigned int pbytes;
0270 
0271     if (id_len > (USHRT_MAX / 8) || !ec->Q)
0272         return -EINVAL;
0273 
0274     bits_len = (uint16_t)(id_len * 8);
0275     entl[0] = bits_len >> 8;
0276     entl[1] = bits_len & 0xff;
0277 
0278     pbytes = MPI_NBYTES(ec->p);
0279 
0280     /* ZA = H256(ENTLA | IDA | a | b | xG | yG | xA | yA) */
0281     sm3_init(&sctx);
0282     sm3_update(&sctx, entl, 2);
0283     sm3_update(&sctx, id, id_len);
0284 
0285     if (sm2_z_digest_update(&sctx, ec->a, pbytes) ||
0286         sm2_z_digest_update(&sctx, ec->b, pbytes) ||
0287         sm2_z_digest_update_point(&sctx, ec->G, ec, pbytes) ||
0288         sm2_z_digest_update_point(&sctx, ec->Q, ec, pbytes))
0289         return -EINVAL;
0290 
0291     sm3_final(&sctx, dgst);
0292     return 0;
0293 }
0294 EXPORT_SYMBOL(sm2_compute_z_digest);
0295 
0296 static int _sm2_verify(struct mpi_ec_ctx *ec, MPI hash, MPI sig_r, MPI sig_s)
0297 {
0298     int rc = -EINVAL;
0299     struct gcry_mpi_point sG, tP;
0300     MPI t = NULL;
0301     MPI x1 = NULL, y1 = NULL;
0302 
0303     mpi_point_init(&sG);
0304     mpi_point_init(&tP);
0305     x1 = mpi_new(0);
0306     y1 = mpi_new(0);
0307     t = mpi_new(0);
0308 
0309     /* r, s in [1, n-1] */
0310     if (mpi_cmp_ui(sig_r, 1) < 0 || mpi_cmp(sig_r, ec->n) > 0 ||
0311         mpi_cmp_ui(sig_s, 1) < 0 || mpi_cmp(sig_s, ec->n) > 0) {
0312         goto leave;
0313     }
0314 
0315     /* t = (r + s) % n, t == 0 */
0316     mpi_addm(t, sig_r, sig_s, ec->n);
0317     if (mpi_cmp_ui(t, 0) == 0)
0318         goto leave;
0319 
0320     /* sG + tP = (x1, y1) */
0321     rc = -EBADMSG;
0322     mpi_ec_mul_point(&sG, sig_s, ec->G, ec);
0323     mpi_ec_mul_point(&tP, t, ec->Q, ec);
0324     mpi_ec_add_points(&sG, &sG, &tP, ec);
0325     if (mpi_ec_get_affine(x1, y1, &sG, ec))
0326         goto leave;
0327 
0328     /* R = (e + x1) % n */
0329     mpi_addm(t, hash, x1, ec->n);
0330 
0331     /* check R == r */
0332     rc = -EKEYREJECTED;
0333     if (mpi_cmp(t, sig_r))
0334         goto leave;
0335 
0336     rc = 0;
0337 
0338 leave:
0339     mpi_point_free_parts(&sG);
0340     mpi_point_free_parts(&tP);
0341     mpi_free(x1);
0342     mpi_free(y1);
0343     mpi_free(t);
0344 
0345     return rc;
0346 }
0347 
0348 static int sm2_verify(struct akcipher_request *req)
0349 {
0350     struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
0351     struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
0352     unsigned char *buffer;
0353     struct sm2_signature_ctx sig;
0354     MPI hash;
0355     int ret;
0356 
0357     if (unlikely(!ec->Q))
0358         return -EINVAL;
0359 
0360     buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL);
0361     if (!buffer)
0362         return -ENOMEM;
0363 
0364     sg_pcopy_to_buffer(req->src,
0365         sg_nents_for_len(req->src, req->src_len + req->dst_len),
0366         buffer, req->src_len + req->dst_len, 0);
0367 
0368     sig.sig_r = NULL;
0369     sig.sig_s = NULL;
0370     ret = asn1_ber_decoder(&sm2signature_decoder, &sig,
0371                 buffer, req->src_len);
0372     if (ret)
0373         goto error;
0374 
0375     ret = -ENOMEM;
0376     hash = mpi_read_raw_data(buffer + req->src_len, req->dst_len);
0377     if (!hash)
0378         goto error;
0379 
0380     ret = _sm2_verify(ec, hash, sig.sig_r, sig.sig_s);
0381 
0382     mpi_free(hash);
0383 error:
0384     mpi_free(sig.sig_r);
0385     mpi_free(sig.sig_s);
0386     kfree(buffer);
0387     return ret;
0388 }
0389 
0390 static int sm2_set_pub_key(struct crypto_akcipher *tfm,
0391             const void *key, unsigned int keylen)
0392 {
0393     struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
0394     MPI a;
0395     int rc;
0396 
0397     /* include the uncompressed flag '0x04' */
0398     a = mpi_read_raw_data(key, keylen);
0399     if (!a)
0400         return -ENOMEM;
0401 
0402     mpi_normalize(a);
0403     rc = sm2_ecc_os2ec(ec->Q, a);
0404     mpi_free(a);
0405 
0406     return rc;
0407 }
0408 
0409 static unsigned int sm2_max_size(struct crypto_akcipher *tfm)
0410 {
0411     /* Unlimited max size */
0412     return PAGE_SIZE;
0413 }
0414 
0415 static int sm2_init_tfm(struct crypto_akcipher *tfm)
0416 {
0417     struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
0418 
0419     return sm2_ec_ctx_init(ec);
0420 }
0421 
0422 static void sm2_exit_tfm(struct crypto_akcipher *tfm)
0423 {
0424     struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
0425 
0426     sm2_ec_ctx_deinit(ec);
0427 }
0428 
0429 static struct akcipher_alg sm2 = {
0430     .verify = sm2_verify,
0431     .set_pub_key = sm2_set_pub_key,
0432     .max_size = sm2_max_size,
0433     .init = sm2_init_tfm,
0434     .exit = sm2_exit_tfm,
0435     .base = {
0436         .cra_name = "sm2",
0437         .cra_driver_name = "sm2-generic",
0438         .cra_priority = 100,
0439         .cra_module = THIS_MODULE,
0440         .cra_ctxsize = sizeof(struct mpi_ec_ctx),
0441     },
0442 };
0443 
0444 static int sm2_init(void)
0445 {
0446     return crypto_register_akcipher(&sm2);
0447 }
0448 
0449 static void sm2_exit(void)
0450 {
0451     crypto_unregister_akcipher(&sm2);
0452 }
0453 
0454 subsys_initcall(sm2_init);
0455 module_exit(sm2_exit);
0456 
0457 MODULE_LICENSE("GPL");
0458 MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
0459 MODULE_DESCRIPTION("SM2 generic algorithm");
0460 MODULE_ALIAS_CRYPTO("sm2-generic");