Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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(&paramlen,
^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");