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