0001
0002
0003
0004
0005
0006
0007
0008
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;
0025 unsigned int nbits;
0026 unsigned int fips:1;
0027
0028
0029
0030
0031 enum gcry_mpi_ec_models model;
0032
0033
0034
0035
0036 enum ecc_dialects dialect;
0037
0038 const char *p;
0039 const char *a, *b;
0040
0041
0042
0043 const char *n;
0044 const char *g_x, *g_y;
0045 unsigned int h;
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
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
0131
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
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
0229 sm3_update(sctx, zero, pbytes - inlen);
0230 sm3_update(sctx, in, inlen);
0231 } else if (inlen > pbytes) {
0232
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
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
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
0316 mpi_addm(t, sig_r, sig_s, ec->n);
0317 if (mpi_cmp_ui(t, 0) == 0)
0318 goto leave;
0319
0320
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
0329 mpi_addm(t, hash, x1, ec->n);
0330
0331
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
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
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");