^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Elliptic Curve (Russian) Digital Signature Algorithm for Cryptographic API
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2019 Vitaly Chikunov <vt@altlinux.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * References:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * GOST 34.10-2018, GOST R 34.10-2012, RFC 7091, ISO/IEC 14888-3:2018.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Historical references:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * GOST R 34.10-2001, RFC 4357, ISO/IEC 14888-3:2006/Amd 1:2010.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * This program is free software; you can redistribute it and/or modify it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * under the terms of the GNU General Public License as published by the Free
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * Software Foundation; either version 2 of the License, or (at your option)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/crypto.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <crypto/streebog.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <crypto/internal/akcipher.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <crypto/akcipher.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/oid_registry.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/scatterlist.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "ecrdsa_params.asn1.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "ecrdsa_pub_key.asn1.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "ecc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "ecrdsa_defs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define ECRDSA_MAX_SIG_SIZE (2 * 512 / 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define ECRDSA_MAX_DIGITS (512 / 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct ecrdsa_ctx {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum OID algo_oid; /* overall public key oid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) enum OID curve_oid; /* parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) enum OID digest_oid; /* parameter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) const struct ecc_curve *curve; /* curve from oid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned int digest_len; /* parameter (bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) const char *digest; /* digest name from oid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned int key_len; /* @key length (bytes) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) const char *key; /* raw public key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct ecc_point pub_key;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u64 _pubp[2][ECRDSA_MAX_DIGITS]; /* point storage for @pub_key */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static const struct ecc_curve *get_curve_by_oid(enum OID oid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) switch (oid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case OID_gostCPSignA:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) case OID_gostTC26Sign256B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return &gost_cp256a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case OID_gostCPSignB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) case OID_gostTC26Sign256C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return &gost_cp256b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) case OID_gostCPSignC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case OID_gostTC26Sign256D:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return &gost_cp256c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) case OID_gostTC26Sign512A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return &gost_tc512a;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case OID_gostTC26Sign512B:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return &gost_tc512b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) /* The following two aren't implemented: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) case OID_gostTC26Sign256A:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case OID_gostTC26Sign512C:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) static int ecrdsa_verify(struct akcipher_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned char sig[ECRDSA_MAX_SIG_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned char digest[STREEBOG512_DIGEST_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) unsigned int ndigits = req->dst_len / sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u64 r[ECRDSA_MAX_DIGITS]; /* witness (r) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) u64 _r[ECRDSA_MAX_DIGITS]; /* -r */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) u64 s[ECRDSA_MAX_DIGITS]; /* second part of sig (s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) u64 e[ECRDSA_MAX_DIGITS]; /* h \mod q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) u64 *v = e; /* e^{-1} \mod q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) u64 z1[ECRDSA_MAX_DIGITS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u64 *z2 = _r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct ecc_point cc = ECC_POINT_INIT(s, e, ndigits); /* reuse s, e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * Digest value, digest algorithm, and curve (modulus) should have the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * same length (256 or 512 bits), public key and signature should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * twice bigger.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (!ctx->curve ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) !ctx->digest ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) !req->src ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) !ctx->pub_key.x ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) req->dst_len != ctx->digest_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) req->dst_len != ctx->curve->g.ndigits * sizeof(u64) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) ctx->pub_key.ndigits != ctx->curve->g.ndigits ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) req->dst_len * 2 != req->src_len ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) WARN_ON(req->src_len > sizeof(sig)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) WARN_ON(req->dst_len > sizeof(digest)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -EBADMSG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, req->src_len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) sig, req->src_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) sg_pcopy_to_buffer(req->src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) sg_nents_for_len(req->src,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) req->src_len + req->dst_len),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) digest, req->dst_len, req->src_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) vli_from_be64(s, sig, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) vli_from_be64(r, sig + ndigits * sizeof(u64), ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Step 1: verify that 0 < r < q, 0 < s < q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (vli_is_zero(r, ndigits) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) vli_cmp(r, ctx->curve->n, ndigits) == 1 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) vli_is_zero(s, ndigits) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) vli_cmp(s, ctx->curve->n, ndigits) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* Step 2: calculate hash (h) of the message (passed as input) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Step 3: calculate e = h \mod q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) vli_from_le64(e, digest, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (vli_cmp(e, ctx->curve->n, ndigits) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) vli_sub(e, e, ctx->curve->n, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (vli_is_zero(e, ndigits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) e[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) /* Step 4: calculate v = e^{-1} \mod q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) vli_mod_inv(v, e, ctx->curve->n, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* Step 5: calculate z_1 = sv \mod q, z_2 = -rv \mod q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) vli_mod_mult_slow(z1, s, v, ctx->curve->n, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) vli_sub(_r, ctx->curve->n, r, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) vli_mod_mult_slow(z2, _r, v, ctx->curve->n, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) /* Step 6: calculate point C = z_1P + z_2Q, and R = x_c \mod q */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) ecc_point_mult_shamir(&cc, z1, &ctx->curve->g, z2, &ctx->pub_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ctx->curve);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (vli_cmp(cc.x, ctx->curve->n, ndigits) == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) vli_sub(cc.x, cc.x, ctx->curve->n, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* Step 7: if R == r signature is valid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!vli_cmp(cc.x, r, ndigits))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) int ecrdsa_param_curve(void *context, size_t hdrlen, unsigned char tag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) const void *value, size_t vlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) struct ecrdsa_ctx *ctx = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ctx->curve_oid = look_up_OID(value, vlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (!ctx->curve_oid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) ctx->curve = get_curve_by_oid(ctx->curve_oid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* Optional. If present should match expected digest algo OID. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int ecrdsa_param_digest(void *context, size_t hdrlen, unsigned char tag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) const void *value, size_t vlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct ecrdsa_ctx *ctx = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) int digest_oid = look_up_OID(value, vlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (digest_oid != ctx->digest_oid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) int ecrdsa_parse_pub_key(void *context, size_t hdrlen, unsigned char tag,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) const void *value, size_t vlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) struct ecrdsa_ctx *ctx = context;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ctx->key = value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ctx->key_len = vlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static u8 *ecrdsa_unpack_u32(u32 *dst, void *src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) memcpy(dst, src, sizeof(u32));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return src + sizeof(u32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* Parse BER encoded subjectPublicKey. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int ecrdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned int keylen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) unsigned int ndigits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) u32 algo, paramlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) u8 *params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) err = asn1_ber_decoder(&ecrdsa_pub_key_decoder, ctx, key, keylen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /* Key parameters is in the key after keylen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) params = ecrdsa_unpack_u32(¶mlen,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ecrdsa_unpack_u32(&algo, (u8 *)key + keylen));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (algo == OID_gost2012PKey256) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) ctx->digest = "streebog256";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ctx->digest_oid = OID_gost2012Digest256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) ctx->digest_len = 256 / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) } else if (algo == OID_gost2012PKey512) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) ctx->digest = "streebog512";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ctx->digest_oid = OID_gost2012Digest512;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ctx->digest_len = 512 / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -ENOPKG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ctx->algo_oid = algo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* Parse SubjectPublicKeyInfo.AlgorithmIdentifier.parameters. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) err = asn1_ber_decoder(&ecrdsa_params_decoder, ctx, params, paramlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * Sizes of algo (set in digest_len) and curve should match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) * each other.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) if (!ctx->curve ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) ctx->curve->g.ndigits * sizeof(u64) != ctx->digest_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return -ENOPKG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * Key is two 256- or 512-bit coordinates which should match
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * curve size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) if ((ctx->key_len != (2 * 256 / 8) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ctx->key_len != (2 * 512 / 8)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) ctx->key_len != ctx->curve->g.ndigits * sizeof(u64) * 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return -ENOPKG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) ndigits = ctx->key_len / sizeof(u64) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) ctx->pub_key = ECC_POINT_INIT(ctx->_pubp[0], ctx->_pubp[1], ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) vli_from_le64(ctx->pub_key.x, ctx->key, ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) vli_from_le64(ctx->pub_key.y, ctx->key + ndigits * sizeof(u64),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) ndigits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (ecc_is_pubkey_valid_partial(ctx->curve, &ctx->pub_key))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return -EKEYREJECTED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static unsigned int ecrdsa_max_size(struct crypto_akcipher *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Verify doesn't need any output, so it's just informational
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) * for keyctl to determine the key bit size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return ctx->pub_key.ndigits * sizeof(u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) static void ecrdsa_exit_tfm(struct crypto_akcipher *tfm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) static struct akcipher_alg ecrdsa_alg = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) .verify = ecrdsa_verify,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) .set_pub_key = ecrdsa_set_pub_key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) .max_size = ecrdsa_max_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) .exit = ecrdsa_exit_tfm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .base = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .cra_name = "ecrdsa",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .cra_driver_name = "ecrdsa-generic",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .cra_priority = 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .cra_module = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .cra_ctxsize = sizeof(struct ecrdsa_ctx),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) static int __init ecrdsa_mod_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return crypto_register_akcipher(&ecrdsa_alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static void __exit ecrdsa_mod_fini(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) crypto_unregister_akcipher(&ecrdsa_alg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) module_init(ecrdsa_mod_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) module_exit(ecrdsa_mod_fini);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) MODULE_AUTHOR("Vitaly Chikunov <vt@altlinux.org>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) MODULE_DESCRIPTION("EC-RDSA generic algorithm");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) MODULE_ALIAS_CRYPTO("ecrdsa-generic");