cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sm2.c (9945B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * SM2 asymmetric public-key algorithm
      4 * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and
      5 * described at https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02
      6 *
      7 * Copyright (c) 2020, Alibaba Group.
      8 * Authors: Tianjia Zhang <tianjia.zhang@linux.alibaba.com>
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/mpi.h>
     13#include <crypto/internal/akcipher.h>
     14#include <crypto/akcipher.h>
     15#include <crypto/hash.h>
     16#include <crypto/sm3.h>
     17#include <crypto/rng.h>
     18#include <crypto/sm2.h>
     19#include "sm2signature.asn1.h"
     20
     21#define MPI_NBYTES(m)   ((mpi_get_nbits(m) + 7) / 8)
     22
     23struct ecc_domain_parms {
     24	const char *desc;           /* Description of the curve.  */
     25	unsigned int nbits;         /* Number of bits.  */
     26	unsigned int fips:1; /* True if this is a FIPS140-2 approved curve */
     27
     28	/* The model describing this curve.  This is mainly used to select
     29	 * the group equation.
     30	 */
     31	enum gcry_mpi_ec_models model;
     32
     33	/* The actual ECC dialect used.  This is used for curve specific
     34	 * optimizations and to select encodings etc.
     35	 */
     36	enum ecc_dialects dialect;
     37
     38	const char *p;              /* The prime defining the field.  */
     39	const char *a, *b;          /* The coefficients.  For Twisted Edwards
     40				     * Curves b is used for d.  For Montgomery
     41				     * Curves (a,b) has ((A-2)/4,B^-1).
     42				     */
     43	const char *n;              /* The order of the base point.  */
     44	const char *g_x, *g_y;      /* Base point.  */
     45	unsigned int h;             /* Cofactor.  */
     46};
     47
     48static const struct ecc_domain_parms sm2_ecp = {
     49	.desc = "sm2p256v1",
     50	.nbits = 256,
     51	.fips = 0,
     52	.model = MPI_EC_WEIERSTRASS,
     53	.dialect = ECC_DIALECT_STANDARD,
     54	.p   = "0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",
     55	.a   = "0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",
     56	.b   = "0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",
     57	.n   = "0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",
     58	.g_x = "0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",
     59	.g_y = "0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",
     60	.h = 1
     61};
     62
     63static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec)
     64{
     65	const struct ecc_domain_parms *ecp = &sm2_ecp;
     66	MPI p, a, b;
     67	MPI x, y;
     68	int rc = -EINVAL;
     69
     70	p = mpi_scanval(ecp->p);
     71	a = mpi_scanval(ecp->a);
     72	b = mpi_scanval(ecp->b);
     73	if (!p || !a || !b)
     74		goto free_p;
     75
     76	x = mpi_scanval(ecp->g_x);
     77	y = mpi_scanval(ecp->g_y);
     78	if (!x || !y)
     79		goto free;
     80
     81	rc = -ENOMEM;
     82
     83	ec->Q = mpi_point_new(0);
     84	if (!ec->Q)
     85		goto free;
     86
     87	/* mpi_ec_setup_elliptic_curve */
     88	ec->G = mpi_point_new(0);
     89	if (!ec->G) {
     90		mpi_point_release(ec->Q);
     91		goto free;
     92	}
     93
     94	mpi_set(ec->G->x, x);
     95	mpi_set(ec->G->y, y);
     96	mpi_set_ui(ec->G->z, 1);
     97
     98	rc = -EINVAL;
     99	ec->n = mpi_scanval(ecp->n);
    100	if (!ec->n) {
    101		mpi_point_release(ec->Q);
    102		mpi_point_release(ec->G);
    103		goto free;
    104	}
    105
    106	ec->h = ecp->h;
    107	ec->name = ecp->desc;
    108	mpi_ec_init(ec, ecp->model, ecp->dialect, 0, p, a, b);
    109
    110	rc = 0;
    111
    112free:
    113	mpi_free(x);
    114	mpi_free(y);
    115free_p:
    116	mpi_free(p);
    117	mpi_free(a);
    118	mpi_free(b);
    119
    120	return rc;
    121}
    122
    123static void sm2_ec_ctx_deinit(struct mpi_ec_ctx *ec)
    124{
    125	mpi_ec_deinit(ec);
    126
    127	memset(ec, 0, sizeof(*ec));
    128}
    129
    130/* RESULT must have been initialized and is set on success to the
    131 * point given by VALUE.
    132 */
    133static int sm2_ecc_os2ec(MPI_POINT result, MPI value)
    134{
    135	int rc;
    136	size_t n;
    137	unsigned char *buf;
    138	MPI x, y;
    139
    140	n = MPI_NBYTES(value);
    141	buf = kmalloc(n, GFP_KERNEL);
    142	if (!buf)
    143		return -ENOMEM;
    144
    145	rc = mpi_print(GCRYMPI_FMT_USG, buf, n, &n, value);
    146	if (rc)
    147		goto err_freebuf;
    148
    149	rc = -EINVAL;
    150	if (n < 1 || ((n - 1) % 2))
    151		goto err_freebuf;
    152	/* No support for point compression */
    153	if (*buf != 0x4)
    154		goto err_freebuf;
    155
    156	rc = -ENOMEM;
    157	n = (n - 1) / 2;
    158	x = mpi_read_raw_data(buf + 1, n);
    159	if (!x)
    160		goto err_freebuf;
    161	y = mpi_read_raw_data(buf + 1 + n, n);
    162	if (!y)
    163		goto err_freex;
    164
    165	mpi_normalize(x);
    166	mpi_normalize(y);
    167	mpi_set(result->x, x);
    168	mpi_set(result->y, y);
    169	mpi_set_ui(result->z, 1);
    170
    171	rc = 0;
    172
    173	mpi_free(y);
    174err_freex:
    175	mpi_free(x);
    176err_freebuf:
    177	kfree(buf);
    178	return rc;
    179}
    180
    181struct sm2_signature_ctx {
    182	MPI sig_r;
    183	MPI sig_s;
    184};
    185
    186int sm2_get_signature_r(void *context, size_t hdrlen, unsigned char tag,
    187				const void *value, size_t vlen)
    188{
    189	struct sm2_signature_ctx *sig = context;
    190
    191	if (!value || !vlen)
    192		return -EINVAL;
    193
    194	sig->sig_r = mpi_read_raw_data(value, vlen);
    195	if (!sig->sig_r)
    196		return -ENOMEM;
    197
    198	return 0;
    199}
    200
    201int sm2_get_signature_s(void *context, size_t hdrlen, unsigned char tag,
    202				const void *value, size_t vlen)
    203{
    204	struct sm2_signature_ctx *sig = context;
    205
    206	if (!value || !vlen)
    207		return -EINVAL;
    208
    209	sig->sig_s = mpi_read_raw_data(value, vlen);
    210	if (!sig->sig_s)
    211		return -ENOMEM;
    212
    213	return 0;
    214}
    215
    216static int sm2_z_digest_update(struct sm3_state *sctx,
    217			MPI m, unsigned int pbytes)
    218{
    219	static const unsigned char zero[32];
    220	unsigned char *in;
    221	unsigned int inlen;
    222
    223	in = mpi_get_buffer(m, &inlen, NULL);
    224	if (!in)
    225		return -EINVAL;
    226
    227	if (inlen < pbytes) {
    228		/* padding with zero */
    229		sm3_update(sctx, zero, pbytes - inlen);
    230		sm3_update(sctx, in, inlen);
    231	} else if (inlen > pbytes) {
    232		/* skip the starting zero */
    233		sm3_update(sctx, in + inlen - pbytes, pbytes);
    234	} else {
    235		sm3_update(sctx, in, inlen);
    236	}
    237
    238	kfree(in);
    239	return 0;
    240}
    241
    242static int sm2_z_digest_update_point(struct sm3_state *sctx,
    243		MPI_POINT point, struct mpi_ec_ctx *ec, unsigned int pbytes)
    244{
    245	MPI x, y;
    246	int ret = -EINVAL;
    247
    248	x = mpi_new(0);
    249	y = mpi_new(0);
    250
    251	if (!mpi_ec_get_affine(x, y, point, ec) &&
    252	    !sm2_z_digest_update(sctx, x, pbytes) &&
    253	    !sm2_z_digest_update(sctx, y, pbytes))
    254		ret = 0;
    255
    256	mpi_free(x);
    257	mpi_free(y);
    258	return ret;
    259}
    260
    261int sm2_compute_z_digest(struct crypto_akcipher *tfm,
    262			const unsigned char *id, size_t id_len,
    263			unsigned char dgst[SM3_DIGEST_SIZE])
    264{
    265	struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
    266	uint16_t bits_len;
    267	unsigned char entl[2];
    268	struct sm3_state sctx;
    269	unsigned int pbytes;
    270
    271	if (id_len > (USHRT_MAX / 8) || !ec->Q)
    272		return -EINVAL;
    273
    274	bits_len = (uint16_t)(id_len * 8);
    275	entl[0] = bits_len >> 8;
    276	entl[1] = bits_len & 0xff;
    277
    278	pbytes = MPI_NBYTES(ec->p);
    279
    280	/* ZA = H256(ENTLA | IDA | a | b | xG | yG | xA | yA) */
    281	sm3_init(&sctx);
    282	sm3_update(&sctx, entl, 2);
    283	sm3_update(&sctx, id, id_len);
    284
    285	if (sm2_z_digest_update(&sctx, ec->a, pbytes) ||
    286	    sm2_z_digest_update(&sctx, ec->b, pbytes) ||
    287	    sm2_z_digest_update_point(&sctx, ec->G, ec, pbytes) ||
    288	    sm2_z_digest_update_point(&sctx, ec->Q, ec, pbytes))
    289		return -EINVAL;
    290
    291	sm3_final(&sctx, dgst);
    292	return 0;
    293}
    294EXPORT_SYMBOL(sm2_compute_z_digest);
    295
    296static int _sm2_verify(struct mpi_ec_ctx *ec, MPI hash, MPI sig_r, MPI sig_s)
    297{
    298	int rc = -EINVAL;
    299	struct gcry_mpi_point sG, tP;
    300	MPI t = NULL;
    301	MPI x1 = NULL, y1 = NULL;
    302
    303	mpi_point_init(&sG);
    304	mpi_point_init(&tP);
    305	x1 = mpi_new(0);
    306	y1 = mpi_new(0);
    307	t = mpi_new(0);
    308
    309	/* r, s in [1, n-1] */
    310	if (mpi_cmp_ui(sig_r, 1) < 0 || mpi_cmp(sig_r, ec->n) > 0 ||
    311		mpi_cmp_ui(sig_s, 1) < 0 || mpi_cmp(sig_s, ec->n) > 0) {
    312		goto leave;
    313	}
    314
    315	/* t = (r + s) % n, t == 0 */
    316	mpi_addm(t, sig_r, sig_s, ec->n);
    317	if (mpi_cmp_ui(t, 0) == 0)
    318		goto leave;
    319
    320	/* sG + tP = (x1, y1) */
    321	rc = -EBADMSG;
    322	mpi_ec_mul_point(&sG, sig_s, ec->G, ec);
    323	mpi_ec_mul_point(&tP, t, ec->Q, ec);
    324	mpi_ec_add_points(&sG, &sG, &tP, ec);
    325	if (mpi_ec_get_affine(x1, y1, &sG, ec))
    326		goto leave;
    327
    328	/* R = (e + x1) % n */
    329	mpi_addm(t, hash, x1, ec->n);
    330
    331	/* check R == r */
    332	rc = -EKEYREJECTED;
    333	if (mpi_cmp(t, sig_r))
    334		goto leave;
    335
    336	rc = 0;
    337
    338leave:
    339	mpi_point_free_parts(&sG);
    340	mpi_point_free_parts(&tP);
    341	mpi_free(x1);
    342	mpi_free(y1);
    343	mpi_free(t);
    344
    345	return rc;
    346}
    347
    348static int sm2_verify(struct akcipher_request *req)
    349{
    350	struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
    351	struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
    352	unsigned char *buffer;
    353	struct sm2_signature_ctx sig;
    354	MPI hash;
    355	int ret;
    356
    357	if (unlikely(!ec->Q))
    358		return -EINVAL;
    359
    360	buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL);
    361	if (!buffer)
    362		return -ENOMEM;
    363
    364	sg_pcopy_to_buffer(req->src,
    365		sg_nents_for_len(req->src, req->src_len + req->dst_len),
    366		buffer, req->src_len + req->dst_len, 0);
    367
    368	sig.sig_r = NULL;
    369	sig.sig_s = NULL;
    370	ret = asn1_ber_decoder(&sm2signature_decoder, &sig,
    371				buffer, req->src_len);
    372	if (ret)
    373		goto error;
    374
    375	ret = -ENOMEM;
    376	hash = mpi_read_raw_data(buffer + req->src_len, req->dst_len);
    377	if (!hash)
    378		goto error;
    379
    380	ret = _sm2_verify(ec, hash, sig.sig_r, sig.sig_s);
    381
    382	mpi_free(hash);
    383error:
    384	mpi_free(sig.sig_r);
    385	mpi_free(sig.sig_s);
    386	kfree(buffer);
    387	return ret;
    388}
    389
    390static int sm2_set_pub_key(struct crypto_akcipher *tfm,
    391			const void *key, unsigned int keylen)
    392{
    393	struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
    394	MPI a;
    395	int rc;
    396
    397	/* include the uncompressed flag '0x04' */
    398	a = mpi_read_raw_data(key, keylen);
    399	if (!a)
    400		return -ENOMEM;
    401
    402	mpi_normalize(a);
    403	rc = sm2_ecc_os2ec(ec->Q, a);
    404	mpi_free(a);
    405
    406	return rc;
    407}
    408
    409static unsigned int sm2_max_size(struct crypto_akcipher *tfm)
    410{
    411	/* Unlimited max size */
    412	return PAGE_SIZE;
    413}
    414
    415static int sm2_init_tfm(struct crypto_akcipher *tfm)
    416{
    417	struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
    418
    419	return sm2_ec_ctx_init(ec);
    420}
    421
    422static void sm2_exit_tfm(struct crypto_akcipher *tfm)
    423{
    424	struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);
    425
    426	sm2_ec_ctx_deinit(ec);
    427}
    428
    429static struct akcipher_alg sm2 = {
    430	.verify = sm2_verify,
    431	.set_pub_key = sm2_set_pub_key,
    432	.max_size = sm2_max_size,
    433	.init = sm2_init_tfm,
    434	.exit = sm2_exit_tfm,
    435	.base = {
    436		.cra_name = "sm2",
    437		.cra_driver_name = "sm2-generic",
    438		.cra_priority = 100,
    439		.cra_module = THIS_MODULE,
    440		.cra_ctxsize = sizeof(struct mpi_ec_ctx),
    441	},
    442};
    443
    444static int sm2_init(void)
    445{
    446	return crypto_register_akcipher(&sm2);
    447}
    448
    449static void sm2_exit(void)
    450{
    451	crypto_unregister_akcipher(&sm2);
    452}
    453
    454subsys_initcall(sm2_init);
    455module_exit(sm2_exit);
    456
    457MODULE_LICENSE("GPL");
    458MODULE_AUTHOR("Tianjia Zhang <tianjia.zhang@linux.alibaba.com>");
    459MODULE_DESCRIPTION("SM2 generic algorithm");
    460MODULE_ALIAS_CRYPTO("sm2-generic");