Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: ecdsa - Add support for ECDSA signature verification

Add support for parsing the parameters of a NIST P256 or NIST P192 key.
Enable signature verification using these keys. The new module is
enabled with CONFIG_ECDSA:
Elliptic Curve Digital Signature Algorithm (NIST P192, P256 etc.)
is A NIST cryptographic standard algorithm. Only signature verification
is implemented.

Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: linux-crypto@vger.kernel.org
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Stefan Berger and committed by
Herbert Xu
4e660291 7547738d

+671 -11
+10
crypto/Kconfig
··· 242 242 help 243 243 Generic implementation of the ECDH algorithm 244 244 245 + config CRYPTO_ECDSA 246 + tristate "ECDSA (NIST P192, P256 etc.) algorithm" 247 + select CRYPTO_ECC 248 + select CRYPTO_AKCIPHER 249 + select ASN1 250 + help 251 + Elliptic Curve Digital Signature Algorithm (NIST P192, P256 etc.) 252 + is A NIST cryptographic standard algorithm. Only signature verification 253 + is implemented. 254 + 245 255 config CRYPTO_ECRDSA 246 256 tristate "EC-RDSA (GOST 34.10) algorithm" 247 257 select CRYPTO_ECC
+6
crypto/Makefile
··· 50 50 51 51 obj-$(CONFIG_CRYPTO_SM2) += sm2_generic.o 52 52 53 + $(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h 54 + $(obj)/ecdsa.o: $(obj)/ecdsasignature.asn1.h 55 + ecdsa_generic-y += ecdsa.o 56 + ecdsa_generic-y += ecdsasignature.asn1.o 57 + obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o 58 + 53 59 crypto_acompress-y := acompress.o 54 60 crypto_acompress-y += scompress.o 55 61 obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o
+2 -11
crypto/ecc.c
··· 42 42 u64 m_high; 43 43 } uint128_t; 44 44 45 - static inline const struct ecc_curve *ecc_get_curve(unsigned int curve_id) 45 + const struct ecc_curve *ecc_get_curve(unsigned int curve_id) 46 46 { 47 47 switch (curve_id) { 48 48 /* In FIPS mode only allow P256 and higher */ ··· 54 54 return NULL; 55 55 } 56 56 } 57 + EXPORT_SYMBOL(ecc_get_curve); 57 58 58 59 static u64 *ecc_alloc_digits_space(unsigned int ndigits) 59 60 { ··· 1281 1280 apply_z(rx, ry, z, curve->p, ndigits); 1282 1281 } 1283 1282 EXPORT_SYMBOL(ecc_point_mult_shamir); 1284 - 1285 - static inline void ecc_swap_digits(const u64 *in, u64 *out, 1286 - unsigned int ndigits) 1287 - { 1288 - const __be64 *src = (__force __be64 *)in; 1289 - int i; 1290 - 1291 - for (i = 0; i < ndigits; i++) 1292 - out[i] = be64_to_cpu(src[ndigits - 1 - i]); 1293 - } 1294 1283 1295 1284 static int __ecc_is_key_valid(const struct ecc_curve *curve, 1296 1285 const u64 *private_key, unsigned int ndigits)
+25
crypto/ecc.h
··· 33 33 34 34 #define ECC_DIGITS_TO_BYTES_SHIFT 3 35 35 36 + #define ECC_MAX_BYTES (ECC_MAX_DIGITS << ECC_DIGITS_TO_BYTES_SHIFT) 37 + 36 38 /** 37 39 * struct ecc_point - elliptic curve point in affine coordinates 38 40 * ··· 71 69 u64 *a; 72 70 u64 *b; 73 71 }; 72 + 73 + /** 74 + * ecc_swap_digits() - Copy ndigits from big endian array to native array 75 + * @in: Input array 76 + * @out: Output array 77 + * @ndigits: Number of digits to copy 78 + */ 79 + static inline void ecc_swap_digits(const u64 *in, u64 *out, unsigned int ndigits) 80 + { 81 + const __be64 *src = (__force __be64 *)in; 82 + int i; 83 + 84 + for (i = 0; i < ndigits; i++) 85 + out[i] = be64_to_cpu(src[ndigits - 1 - i]); 86 + } 87 + 88 + /** 89 + * ecc_get_curve() - Get a curve given its curve_id 90 + * @curve_id: Id of the curve 91 + * 92 + * Returns pointer to the curve data, NULL if curve is not available 93 + */ 94 + const struct ecc_curve *ecc_get_curve(unsigned int curve_id); 74 95 75 96 /** 76 97 * ecc_is_key_valid() - Validate a given ECDH private key
+345
crypto/ecdsa.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (c) 2021 IBM Corporation 4 + */ 5 + 6 + #include <linux/module.h> 7 + #include <crypto/internal/akcipher.h> 8 + #include <crypto/akcipher.h> 9 + #include <crypto/ecdh.h> 10 + #include <linux/asn1_decoder.h> 11 + #include <linux/scatterlist.h> 12 + 13 + #include "ecc.h" 14 + #include "ecdsasignature.asn1.h" 15 + 16 + struct ecc_ctx { 17 + unsigned int curve_id; 18 + const struct ecc_curve *curve; 19 + 20 + bool pub_key_set; 21 + u64 x[ECC_MAX_DIGITS]; /* pub key x and y coordinates */ 22 + u64 y[ECC_MAX_DIGITS]; 23 + struct ecc_point pub_key; 24 + }; 25 + 26 + struct ecdsa_signature_ctx { 27 + const struct ecc_curve *curve; 28 + u64 r[ECC_MAX_DIGITS]; 29 + u64 s[ECC_MAX_DIGITS]; 30 + }; 31 + 32 + /* 33 + * Get the r and s components of a signature from the X509 certificate. 34 + */ 35 + static int ecdsa_get_signature_rs(u64 *dest, size_t hdrlen, unsigned char tag, 36 + const void *value, size_t vlen, unsigned int ndigits) 37 + { 38 + size_t keylen = ndigits * sizeof(u64); 39 + ssize_t diff = vlen - keylen; 40 + const char *d = value; 41 + u8 rs[ECC_MAX_BYTES]; 42 + 43 + if (!value || !vlen) 44 + return -EINVAL; 45 + 46 + /* diff = 0: 'value' has exacly the right size 47 + * diff > 0: 'value' has too many bytes; one leading zero is allowed that 48 + * makes the value a positive integer; error on more 49 + * diff < 0: 'value' is missing leading zeros, which we add 50 + */ 51 + if (diff > 0) { 52 + /* skip over leading zeros that make 'value' a positive int */ 53 + if (*d == 0) { 54 + vlen -= 1; 55 + diff--; 56 + d++; 57 + } 58 + if (diff) 59 + return -EINVAL; 60 + } 61 + if (-diff >= keylen) 62 + return -EINVAL; 63 + 64 + if (diff) { 65 + /* leading zeros not given in 'value' */ 66 + memset(rs, 0, -diff); 67 + } 68 + 69 + memcpy(&rs[-diff], d, vlen); 70 + 71 + ecc_swap_digits((u64 *)rs, dest, ndigits); 72 + 73 + return 0; 74 + } 75 + 76 + int ecdsa_get_signature_r(void *context, size_t hdrlen, unsigned char tag, 77 + const void *value, size_t vlen) 78 + { 79 + struct ecdsa_signature_ctx *sig = context; 80 + 81 + return ecdsa_get_signature_rs(sig->r, hdrlen, tag, value, vlen, 82 + sig->curve->g.ndigits); 83 + } 84 + 85 + int ecdsa_get_signature_s(void *context, size_t hdrlen, unsigned char tag, 86 + const void *value, size_t vlen) 87 + { 88 + struct ecdsa_signature_ctx *sig = context; 89 + 90 + return ecdsa_get_signature_rs(sig->s, hdrlen, tag, value, vlen, 91 + sig->curve->g.ndigits); 92 + } 93 + 94 + static int _ecdsa_verify(struct ecc_ctx *ctx, const u64 *hash, const u64 *r, const u64 *s) 95 + { 96 + const struct ecc_curve *curve = ctx->curve; 97 + unsigned int ndigits = curve->g.ndigits; 98 + u64 s1[ECC_MAX_DIGITS]; 99 + u64 u1[ECC_MAX_DIGITS]; 100 + u64 u2[ECC_MAX_DIGITS]; 101 + u64 x1[ECC_MAX_DIGITS]; 102 + u64 y1[ECC_MAX_DIGITS]; 103 + struct ecc_point res = ECC_POINT_INIT(x1, y1, ndigits); 104 + 105 + /* 0 < r < n and 0 < s < n */ 106 + if (vli_is_zero(r, ndigits) || vli_cmp(r, curve->n, ndigits) >= 0 || 107 + vli_is_zero(s, ndigits) || vli_cmp(s, curve->n, ndigits) >= 0) 108 + return -EBADMSG; 109 + 110 + /* hash is given */ 111 + pr_devel("hash : %016llx %016llx ... %016llx\n", 112 + hash[ndigits - 1], hash[ndigits - 2], hash[0]); 113 + 114 + /* s1 = (s^-1) mod n */ 115 + vli_mod_inv(s1, s, curve->n, ndigits); 116 + /* u1 = (hash * s1) mod n */ 117 + vli_mod_mult_slow(u1, hash, s1, curve->n, ndigits); 118 + /* u2 = (r * s1) mod n */ 119 + vli_mod_mult_slow(u2, r, s1, curve->n, ndigits); 120 + /* res = u1*G + u2 * pub_key */ 121 + ecc_point_mult_shamir(&res, u1, &curve->g, u2, &ctx->pub_key, curve); 122 + 123 + /* res.x = res.x mod n (if res.x > order) */ 124 + if (unlikely(vli_cmp(res.x, curve->n, ndigits) == 1)) 125 + /* faster alternative for NIST p256 & p192 */ 126 + vli_sub(res.x, res.x, curve->n, ndigits); 127 + 128 + if (!vli_cmp(res.x, r, ndigits)) 129 + return 0; 130 + 131 + return -EKEYREJECTED; 132 + } 133 + 134 + /* 135 + * Verify an ECDSA signature. 136 + */ 137 + static int ecdsa_verify(struct akcipher_request *req) 138 + { 139 + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 140 + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); 141 + size_t keylen = ctx->curve->g.ndigits * sizeof(u64); 142 + struct ecdsa_signature_ctx sig_ctx = { 143 + .curve = ctx->curve, 144 + }; 145 + u8 rawhash[ECC_MAX_BYTES]; 146 + u64 hash[ECC_MAX_DIGITS]; 147 + unsigned char *buffer; 148 + ssize_t diff; 149 + int ret; 150 + 151 + if (unlikely(!ctx->pub_key_set)) 152 + return -EINVAL; 153 + 154 + buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL); 155 + if (!buffer) 156 + return -ENOMEM; 157 + 158 + sg_pcopy_to_buffer(req->src, 159 + sg_nents_for_len(req->src, req->src_len + req->dst_len), 160 + buffer, req->src_len + req->dst_len, 0); 161 + 162 + ret = asn1_ber_decoder(&ecdsasignature_decoder, &sig_ctx, 163 + buffer, req->src_len); 164 + if (ret < 0) 165 + goto error; 166 + 167 + /* if the hash is shorter then we will add leading zeros to fit to ndigits */ 168 + diff = keylen - req->dst_len; 169 + if (diff >= 0) { 170 + if (diff) 171 + memset(rawhash, 0, diff); 172 + memcpy(&rawhash[diff], buffer + req->src_len, req->dst_len); 173 + } else if (diff < 0) { 174 + /* given hash is longer, we take the left-most bytes */ 175 + memcpy(&rawhash, buffer + req->src_len, keylen); 176 + } 177 + 178 + ecc_swap_digits((u64 *)rawhash, hash, ctx->curve->g.ndigits); 179 + 180 + ret = _ecdsa_verify(ctx, hash, sig_ctx.r, sig_ctx.s); 181 + 182 + error: 183 + kfree(buffer); 184 + 185 + return ret; 186 + } 187 + 188 + static int ecdsa_ecc_ctx_init(struct ecc_ctx *ctx, unsigned int curve_id) 189 + { 190 + ctx->curve_id = curve_id; 191 + ctx->curve = ecc_get_curve(curve_id); 192 + if (!ctx->curve) 193 + return -EINVAL; 194 + 195 + return 0; 196 + } 197 + 198 + 199 + static void ecdsa_ecc_ctx_deinit(struct ecc_ctx *ctx) 200 + { 201 + ctx->pub_key_set = false; 202 + } 203 + 204 + static int ecdsa_ecc_ctx_reset(struct ecc_ctx *ctx) 205 + { 206 + unsigned int curve_id = ctx->curve_id; 207 + int ret; 208 + 209 + ecdsa_ecc_ctx_deinit(ctx); 210 + ret = ecdsa_ecc_ctx_init(ctx, curve_id); 211 + if (ret == 0) 212 + ctx->pub_key = ECC_POINT_INIT(ctx->x, ctx->y, 213 + ctx->curve->g.ndigits); 214 + return ret; 215 + } 216 + 217 + /* 218 + * Set the public key given the raw uncompressed key data from an X509 219 + * certificate. The key data contain the concatenated X and Y coordinates of 220 + * the public key. 221 + */ 222 + static int ecdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, unsigned int keylen) 223 + { 224 + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); 225 + const unsigned char *d = key; 226 + const u64 *digits = (const u64 *)&d[1]; 227 + unsigned int ndigits; 228 + int ret; 229 + 230 + ret = ecdsa_ecc_ctx_reset(ctx); 231 + if (ret < 0) 232 + return ret; 233 + 234 + if (keylen < 1 || (((keylen - 1) >> 1) % sizeof(u64)) != 0) 235 + return -EINVAL; 236 + /* we only accept uncompressed format indicated by '4' */ 237 + if (d[0] != 4) 238 + return -EINVAL; 239 + 240 + keylen--; 241 + ndigits = (keylen >> 1) / sizeof(u64); 242 + if (ndigits != ctx->curve->g.ndigits) 243 + return -EINVAL; 244 + 245 + ecc_swap_digits(digits, ctx->pub_key.x, ndigits); 246 + ecc_swap_digits(&digits[ndigits], ctx->pub_key.y, ndigits); 247 + ret = ecc_is_pubkey_valid_full(ctx->curve, &ctx->pub_key); 248 + 249 + ctx->pub_key_set = ret == 0; 250 + 251 + return ret; 252 + } 253 + 254 + static void ecdsa_exit_tfm(struct crypto_akcipher *tfm) 255 + { 256 + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); 257 + 258 + ecdsa_ecc_ctx_deinit(ctx); 259 + } 260 + 261 + static unsigned int ecdsa_max_size(struct crypto_akcipher *tfm) 262 + { 263 + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); 264 + 265 + return ctx->pub_key.ndigits << ECC_DIGITS_TO_BYTES_SHIFT; 266 + } 267 + 268 + static int ecdsa_nist_p256_init_tfm(struct crypto_akcipher *tfm) 269 + { 270 + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); 271 + 272 + return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P256); 273 + } 274 + 275 + static struct akcipher_alg ecdsa_nist_p256 = { 276 + .verify = ecdsa_verify, 277 + .set_pub_key = ecdsa_set_pub_key, 278 + .max_size = ecdsa_max_size, 279 + .init = ecdsa_nist_p256_init_tfm, 280 + .exit = ecdsa_exit_tfm, 281 + .base = { 282 + .cra_name = "ecdsa-nist-p256", 283 + .cra_driver_name = "ecdsa-nist-p256-generic", 284 + .cra_priority = 100, 285 + .cra_module = THIS_MODULE, 286 + .cra_ctxsize = sizeof(struct ecc_ctx), 287 + }, 288 + }; 289 + 290 + static int ecdsa_nist_p192_init_tfm(struct crypto_akcipher *tfm) 291 + { 292 + struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm); 293 + 294 + return ecdsa_ecc_ctx_init(ctx, ECC_CURVE_NIST_P192); 295 + } 296 + 297 + static struct akcipher_alg ecdsa_nist_p192 = { 298 + .verify = ecdsa_verify, 299 + .set_pub_key = ecdsa_set_pub_key, 300 + .max_size = ecdsa_max_size, 301 + .init = ecdsa_nist_p192_init_tfm, 302 + .exit = ecdsa_exit_tfm, 303 + .base = { 304 + .cra_name = "ecdsa-nist-p192", 305 + .cra_driver_name = "ecdsa-nist-p192-generic", 306 + .cra_priority = 100, 307 + .cra_module = THIS_MODULE, 308 + .cra_ctxsize = sizeof(struct ecc_ctx), 309 + }, 310 + }; 311 + static bool ecdsa_nist_p192_registered; 312 + 313 + static int ecdsa_init(void) 314 + { 315 + int ret; 316 + 317 + /* NIST p192 may not be available in FIPS mode */ 318 + ret = crypto_register_akcipher(&ecdsa_nist_p192); 319 + ecdsa_nist_p192_registered = ret == 0; 320 + 321 + ret = crypto_register_akcipher(&ecdsa_nist_p256); 322 + if (ret) 323 + goto nist_p256_error; 324 + return 0; 325 + 326 + nist_p256_error: 327 + if (ecdsa_nist_p192_registered) 328 + crypto_unregister_akcipher(&ecdsa_nist_p192); 329 + return ret; 330 + } 331 + 332 + static void ecdsa_exit(void) 333 + { 334 + if (ecdsa_nist_p192_registered) 335 + crypto_unregister_akcipher(&ecdsa_nist_p192); 336 + crypto_unregister_akcipher(&ecdsa_nist_p256); 337 + } 338 + 339 + subsys_initcall(ecdsa_init); 340 + module_exit(ecdsa_exit); 341 + 342 + MODULE_LICENSE("GPL"); 343 + MODULE_AUTHOR("Stefan Berger <stefanb@linux.ibm.com>"); 344 + MODULE_DESCRIPTION("ECDSA generic algorithm"); 345 + MODULE_ALIAS_CRYPTO("ecdsa-generic");
+4
crypto/ecdsasignature.asn1
··· 1 + ECDSASignature ::= SEQUENCE { 2 + r INTEGER ({ ecdsa_get_signature_r }), 3 + s INTEGER ({ ecdsa_get_signature_s }) 4 + }
+12
crypto/testmgr.c
··· 4911 4911 .kpp = __VECS(ecdh_tv_template) 4912 4912 } 4913 4913 }, { 4914 + .alg = "ecdsa-nist-p192", 4915 + .test = alg_test_akcipher, 4916 + .suite = { 4917 + .akcipher = __VECS(ecdsa_nist_p192_tv_template) 4918 + } 4919 + }, { 4920 + .alg = "ecdsa-nist-p256", 4921 + .test = alg_test_akcipher, 4922 + .suite = { 4923 + .akcipher = __VECS(ecdsa_nist_p256_tv_template) 4924 + } 4925 + }, { 4914 4926 .alg = "ecrdsa", 4915 4927 .test = alg_test_akcipher, 4916 4928 .suite = {
+267
crypto/testmgr.h
··· 567 567 }; 568 568 569 569 /* 570 + * ECDSA test vectors. 571 + */ 572 + static const struct akcipher_testvec ecdsa_nist_p192_tv_template[] = { 573 + { 574 + .key = 575 + "\x04\xf7\x46\xf8\x2f\x15\xf6\x22\x8e\xd7\x57\x4f\xcc\xe7\xbb\xc1" 576 + "\xd4\x09\x73\xcf\xea\xd0\x15\x07\x3d\xa5\x8a\x8a\x95\x43\xe4\x68" 577 + "\xea\xc6\x25\xc1\xc1\x01\x25\x4c\x7e\xc3\x3c\xa6\x04\x0a\xe7\x08" 578 + "\x98", 579 + .key_len = 49, 580 + .params = 581 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 582 + "\xce\x3d\x03\x01\x01", 583 + .param_len = 21, 584 + .m = 585 + "\xcd\xb9\xd2\x1c\xb7\x6f\xcd\x44\xb3\xfd\x63\xea\xa3\x66\x7f\xae" 586 + "\x63\x85\xe7\x82", 587 + .m_size = 20, 588 + .algo = OID_id_ecdsa_with_sha1, 589 + .c = 590 + "\x30\x35\x02\x19\x00\xba\xe5\x93\x83\x6e\xb6\x3b\x63\xa0\x27\x91" 591 + "\xc6\xf6\x7f\xc3\x09\xad\x59\xad\x88\x27\xd6\x92\x6b\x02\x18\x10" 592 + "\x68\x01\x9d\xba\xce\x83\x08\xef\x95\x52\x7b\xa0\x0f\xe4\x18\x86" 593 + "\x80\x6f\xa5\x79\x77\xda\xd0", 594 + .c_size = 55, 595 + .public_key_vec = true, 596 + .siggen_sigver_test = true, 597 + }, { 598 + .key = 599 + "\x04\xb6\x4b\xb1\xd1\xac\xba\x24\x8f\x65\xb2\x60\x00\x90\xbf\xbd" 600 + "\x78\x05\x73\xe9\x79\x1d\x6f\x7c\x0b\xd2\xc3\x93\xa7\x28\xe1\x75" 601 + "\xf7\xd5\x95\x1d\x28\x10\xc0\x75\x50\x5c\x1a\x4f\x3f\x8f\xa5\xee" 602 + "\xa3", 603 + .key_len = 49, 604 + .params = 605 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 606 + "\xce\x3d\x03\x01\x01", 607 + .param_len = 21, 608 + .m = 609 + "\x8d\xd6\xb8\x3e\xe5\xff\x23\xf6\x25\xa2\x43\x42\x74\x45\xa7\x40" 610 + "\x3a\xff\x2f\xe1\xd3\xf6\x9f\xe8\x33\xcb\x12\x11", 611 + .m_size = 28, 612 + .algo = OID_id_ecdsa_with_sha224, 613 + .c = 614 + "\x30\x34\x02\x18\x5a\x8b\x82\x69\x7e\x8a\x0a\x09\x14\xf8\x11\x2b" 615 + "\x55\xdc\xae\x37\x83\x7b\x12\xe6\xb6\x5b\xcb\xd4\x02\x18\x6a\x14" 616 + "\x4f\x53\x75\xc8\x02\x48\xeb\xc3\x92\x0f\x1e\x72\xee\xc4\xa3\xe3" 617 + "\x5c\x99\xdb\x92\x5b\x36", 618 + .c_size = 54, 619 + .public_key_vec = true, 620 + .siggen_sigver_test = true, 621 + }, { 622 + .key = 623 + "\x04\xe2\x51\x24\x9b\xf7\xb6\x32\x82\x39\x66\x3d\x5b\xec\x3b\xae" 624 + "\x0c\xd5\xf2\x67\xd1\xc7\xe1\x02\xe4\xbf\x90\x62\xb8\x55\x75\x56" 625 + "\x69\x20\x5e\xcb\x4e\xca\x33\xd6\xcb\x62\x6b\x94\xa9\xa2\xe9\x58" 626 + "\x91", 627 + .key_len = 49, 628 + .params = 629 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 630 + "\xce\x3d\x03\x01\x01", 631 + .param_len = 21, 632 + .m = 633 + "\x35\xec\xa1\xa0\x9e\x14\xde\x33\x03\xb6\xf6\xbd\x0c\x2f\xb2\xfd" 634 + "\x1f\x27\x82\xa5\xd7\x70\x3f\xef\xa0\x82\x69\x8e\x73\x31\x8e\xd7", 635 + .m_size = 32, 636 + .algo = OID_id_ecdsa_with_sha256, 637 + .c = 638 + "\x30\x35\x02\x18\x3f\x72\x3f\x1f\x42\xd2\x3f\x1d\x6b\x1a\x58\x56" 639 + "\xf1\x8f\xf7\xfd\x01\x48\xfb\x5f\x72\x2a\xd4\x8f\x02\x19\x00\xb3" 640 + "\x69\x43\xfd\x48\x19\x86\xcf\x32\xdd\x41\x74\x6a\x51\xc7\xd9\x7d" 641 + "\x3a\x97\xd9\xcd\x1a\x6a\x49", 642 + .c_size = 55, 643 + .public_key_vec = true, 644 + .siggen_sigver_test = true, 645 + }, { 646 + .key = 647 + "\x04\x5a\x13\xfe\x68\x86\x4d\xf4\x17\xc7\xa4\xe5\x8c\x65\x57\xb7" 648 + "\x03\x73\x26\x57\xfb\xe5\x58\x40\xd8\xfd\x49\x05\xab\xf1\x66\x1f" 649 + "\xe2\x9d\x93\x9e\xc2\x22\x5a\x8b\x4f\xf3\x77\x22\x59\x7e\xa6\x4e" 650 + "\x8b", 651 + .key_len = 49, 652 + .params = 653 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 654 + "\xce\x3d\x03\x01\x01", 655 + .param_len = 21, 656 + .m = 657 + "\x9d\x2e\x1a\x8f\xed\x6c\x4b\x61\xae\xac\xd5\x19\x79\xce\x67\xf9" 658 + "\xa0\x34\xeb\xb0\x81\xf9\xd9\xdc\x6e\xb3\x5c\xa8\x69\xfc\x8a\x61" 659 + "\x39\x81\xfb\xfd\x5c\x30\x6b\xa8\xee\xed\x89\xaf\xa3\x05\xe4\x78", 660 + .m_size = 48, 661 + .algo = OID_id_ecdsa_with_sha384, 662 + .c = 663 + "\x30\x35\x02\x19\x00\xf0\xa3\x38\xce\x2b\xf8\x9d\x1a\xcf\x7f\x34" 664 + "\xb4\xb4\xe5\xc5\x00\xdd\x15\xbb\xd6\x8c\xa7\x03\x78\x02\x18\x64" 665 + "\xbc\x5a\x1f\x82\x96\x61\xd7\xd1\x01\x77\x44\x5d\x53\xa4\x7c\x93" 666 + "\x12\x3b\x3b\x28\xfb\x6d\xe1", 667 + .c_size = 55, 668 + .public_key_vec = true, 669 + .siggen_sigver_test = true, 670 + }, { 671 + .key = 672 + "\x04\xd5\xf2\x6e\xc3\x94\x5c\x52\xbc\xdf\x86\x6c\x14\xd1\xca\xea" 673 + "\xcc\x72\x3a\x8a\xf6\x7a\x3a\x56\x36\x3b\xca\xc6\x94\x0e\x17\x1d" 674 + "\x9e\xa0\x58\x28\xf9\x4b\xe6\xd1\xa5\x44\x91\x35\x0d\xe7\xf5\x11" 675 + "\x57", 676 + .key_len = 49, 677 + .params = 678 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 679 + "\xce\x3d\x03\x01\x01", 680 + .param_len = 21, 681 + .m = 682 + "\xd5\x4b\xe9\x36\xda\xd8\x6e\xc0\x50\x03\xbe\x00\x43\xff\xf0\x23" 683 + "\xac\xa2\x42\xe7\x37\x77\x79\x52\x8f\x3e\xc0\x16\xc1\xfc\x8c\x67" 684 + "\x16\xbc\x8a\x5d\x3b\xd3\x13\xbb\xb6\xc0\x26\x1b\xeb\x33\xcc\x70" 685 + "\x4a\xf2\x11\x37\xe8\x1b\xba\x55\xac\x69\xe1\x74\x62\x7c\x6e\xb5", 686 + .m_size = 64, 687 + .algo = OID_id_ecdsa_with_sha512, 688 + .c = 689 + "\x30\x35\x02\x19\x00\x88\x5b\x8f\x59\x43\xbf\xcf\xc6\xdd\x3f\x07" 690 + "\x87\x12\xa0\xd4\xac\x2b\x11\x2d\x1c\xb6\x06\xc9\x6c\x02\x18\x73" 691 + "\xb4\x22\x9a\x98\x73\x3c\x83\xa9\x14\x2a\x5e\xf5\xe5\xfb\x72\x28" 692 + "\x6a\xdf\x97\xfd\x82\x76\x24", 693 + .c_size = 55, 694 + .public_key_vec = true, 695 + .siggen_sigver_test = true, 696 + }, 697 + }; 698 + 699 + static const struct akcipher_testvec ecdsa_nist_p256_tv_template[] = { 700 + { 701 + .key = 702 + "\x04\xb9\x7b\xbb\xd7\x17\x64\xd2\x7e\xfc\x81\x5d\x87\x06\x83\x41" 703 + "\x22\xd6\x9a\xaa\x87\x17\xec\x4f\x63\x55\x2f\x94\xba\xdd\x83\xe9" 704 + "\x34\x4b\xf3\xe9\x91\x13\x50\xb6\xcb\xca\x62\x08\xe7\x3b\x09\xdc" 705 + "\xc3\x63\x4b\x2d\xb9\x73\x53\xe4\x45\xe6\x7c\xad\xe7\x6b\xb0\xe8" 706 + "\xaf", 707 + .key_len = 65, 708 + .params = 709 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 710 + "\xce\x3d\x03\x01\x07", 711 + .param_len = 21, 712 + .m = 713 + "\xc2\x2b\x5f\x91\x78\x34\x26\x09\x42\x8d\x6f\x51\xb2\xc5\xaf\x4c" 714 + "\x0b\xde\x6a\x42", 715 + .m_size = 20, 716 + .algo = OID_id_ecdsa_with_sha1, 717 + .c = 718 + "\x30\x46\x02\x21\x00\xf9\x25\xce\x9f\x3a\xa6\x35\x81\xcf\xd4\xe7" 719 + "\xb7\xf0\x82\x56\x41\xf7\xd4\xad\x8d\x94\x5a\x69\x89\xee\xca\x6a" 720 + "\x52\x0e\x48\x4d\xcc\x02\x21\x00\xd7\xe4\xef\x52\x66\xd3\x5b\x9d" 721 + "\x8a\xfa\x54\x93\x29\xa7\x70\x86\xf1\x03\x03\xf3\x3b\xe2\x73\xf7" 722 + "\xfb\x9d\x8b\xde\xd4\x8d\x6f\xad", 723 + .c_size = 72, 724 + .public_key_vec = true, 725 + .siggen_sigver_test = true, 726 + }, { 727 + .key = 728 + "\x04\x8b\x6d\xc0\x33\x8e\x2d\x8b\x67\xf5\xeb\xc4\x7f\xa0\xf5\xd9" 729 + "\x7b\x03\xa5\x78\x9a\xb5\xea\x14\xe4\x23\xd0\xaf\xd7\x0e\x2e\xa0" 730 + "\xc9\x8b\xdb\x95\xf8\xb3\xaf\xac\x00\x2c\x2c\x1f\x7a\xfd\x95\x88" 731 + "\x43\x13\xbf\xf3\x1c\x05\x1a\x14\x18\x09\x3f\xd6\x28\x3e\xc5\xa0" 732 + "\xd4", 733 + .key_len = 65, 734 + .params = 735 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 736 + "\xce\x3d\x03\x01\x07", 737 + .param_len = 21, 738 + .m = 739 + "\x1a\x15\xbc\xa3\xe4\xed\x3a\xb8\x23\x67\xc6\xc4\x34\xf8\x6c\x41" 740 + "\x04\x0b\xda\xc5\x77\xfa\x1c\x2d\xe6\x2c\x3b\xe0", 741 + .m_size = 28, 742 + .algo = OID_id_ecdsa_with_sha224, 743 + .c = 744 + "\x30\x44\x02\x20\x20\x43\xfa\xc0\x9f\x9d\x7b\xe7\xae\xce\x77\x59" 745 + "\x1a\xdb\x59\xd5\x34\x62\x79\xcb\x6a\x91\x67\x2e\x7d\x25\xd8\x25" 746 + "\xf5\x81\xd2\x1e\x02\x20\x5f\xf8\x74\xf8\x57\xd0\x5e\x54\x76\x20" 747 + "\x4a\x77\x22\xec\xc8\x66\xbf\x50\x05\x58\x39\x0e\x26\x92\xce\xd5" 748 + "\x2e\x8b\xde\x5a\x04\x0e", 749 + .c_size = 70, 750 + .public_key_vec = true, 751 + .siggen_sigver_test = true, 752 + }, { 753 + .key = 754 + "\x04\xf1\xea\xc4\x53\xf3\xb9\x0e\x9f\x7e\xad\xe3\xea\xd7\x0e\x0f" 755 + "\xd6\x98\x9a\xca\x92\x4d\x0a\x80\xdb\x2d\x45\xc7\xec\x4b\x97\x00" 756 + "\x2f\xe9\x42\x6c\x29\xdc\x55\x0e\x0b\x53\x12\x9b\x2b\xad\x2c\xe9" 757 + "\x80\xe6\xc5\x43\xc2\x1d\x5e\xbb\x65\x21\x50\xb6\x37\xb0\x03\x8e" 758 + "\xb8", 759 + .key_len = 65, 760 + .params = 761 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 762 + "\xce\x3d\x03\x01\x07", 763 + .param_len = 21, 764 + .m = 765 + "\x8f\x43\x43\x46\x64\x8f\x6b\x96\xdf\x89\xdd\xa9\x01\xc5\x17\x6b" 766 + "\x10\xa6\xd8\x39\x61\xdd\x3c\x1a\xc8\x8b\x59\xb2\xdc\x32\x7a\xa4", 767 + .m_size = 32, 768 + .algo = OID_id_ecdsa_with_sha256, 769 + .c = 770 + "\x30\x45\x02\x20\x08\x31\xfa\x74\x0d\x1d\x21\x5d\x09\xdc\x29\x63" 771 + "\xa8\x1a\xad\xfc\xac\x44\xc3\xe8\x24\x11\x2d\xa4\x91\xdc\x02\x67" 772 + "\xdc\x0c\xd0\x82\x02\x21\x00\xbd\xff\xce\xee\x42\xc3\x97\xff\xf9" 773 + "\xa9\x81\xac\x4a\x50\xd0\x91\x0a\x6e\x1b\xc4\xaf\xe1\x83\xc3\x4f" 774 + "\x2a\x65\x35\x23\xe3\x1d\xfa", 775 + .c_size = 71, 776 + .public_key_vec = true, 777 + .siggen_sigver_test = true, 778 + }, { 779 + .key = 780 + "\x04\xc5\xc6\xea\x60\xc9\xce\xad\x02\x8d\xf5\x3e\x24\xe3\x52\x1d" 781 + "\x28\x47\x3b\xc3\x6b\xa4\x99\x35\x99\x11\x88\x88\xc8\xf4\xee\x7e" 782 + "\x8c\x33\x8f\x41\x03\x24\x46\x2b\x1a\x82\xf9\x9f\xe1\x97\x1b\x00" 783 + "\xda\x3b\x24\x41\xf7\x66\x33\x58\x3d\x3a\x81\xad\xcf\x16\xe9\xe2" 784 + "\x7c", 785 + .key_len = 65, 786 + .params = 787 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 788 + "\xce\x3d\x03\x01\x07", 789 + .param_len = 21, 790 + .m = 791 + "\x3e\x78\x70\xfb\xcd\x66\xba\x91\xa1\x79\xff\x1e\x1c\x6b\x78\xe6" 792 + "\xc0\x81\x3a\x65\x97\x14\x84\x36\x14\x1a\x9a\xb7\xc5\xab\x84\x94" 793 + "\x5e\xbb\x1b\x34\x71\xcb\x41\xe1\xf6\xfc\x92\x7b\x34\xbb\x86\xbb", 794 + .m_size = 48, 795 + .algo = OID_id_ecdsa_with_sha384, 796 + .c = 797 + "\x30\x46\x02\x21\x00\x8e\xf3\x6f\xdc\xf8\x69\xa6\x2e\xd0\x2e\x95" 798 + "\x54\xd1\x95\x64\x93\x08\xb2\x6b\x24\x94\x48\x46\x5e\xf2\xe4\x6c" 799 + "\xc7\x94\xb1\xd5\xfe\x02\x21\x00\xeb\xa7\x80\x26\xdc\xf9\x3a\x44" 800 + "\x19\xfb\x5f\x92\xf4\xc9\x23\x37\x69\xf4\x3b\x4f\x47\xcf\x9b\x16" 801 + "\xc0\x60\x11\x92\xdc\x17\x89\x12", 802 + .c_size = 72, 803 + .public_key_vec = true, 804 + .siggen_sigver_test = true, 805 + }, { 806 + .key = 807 + "\x04\xd7\x27\x46\x49\xf6\x26\x85\x12\x40\x76\x8e\xe2\xe6\x2a\x7a" 808 + "\x83\xb1\x4e\x7a\xeb\x3b\x5c\x67\x4a\xb5\xa4\x92\x8c\x69\xff\x38" 809 + "\xee\xd9\x4e\x13\x29\x59\xad\xde\x6b\xbb\x45\x31\xee\xfd\xd1\x1b" 810 + "\x64\xd3\xb5\xfc\xaf\x9b\x4b\x88\x3b\x0e\xb7\xd6\xdf\xf1\xd5\x92" 811 + "\xbf", 812 + .key_len = 65, 813 + .params = 814 + "\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48" 815 + "\xce\x3d\x03\x01\x07", 816 + .param_len = 21, 817 + .m = 818 + "\x57\xb7\x9e\xe9\x05\x0a\x8c\x1b\xc9\x13\xe5\x4a\x24\xc7\xe2\xe9" 819 + "\x43\xc3\xd1\x76\x62\xf4\x98\x1a\x9c\x13\xb0\x20\x1b\xe5\x39\xca" 820 + "\x4f\xd9\x85\x34\x95\xa2\x31\xbc\xbb\xde\xdd\x76\xbb\x61\xe3\xcf" 821 + "\x9d\xc0\x49\x7a\xf3\x7a\xc4\x7d\xa8\x04\x4b\x8d\xb4\x4d\x5b\xd6", 822 + .m_size = 64, 823 + .algo = OID_id_ecdsa_with_sha512, 824 + .c = 825 + "\x30\x45\x02\x21\x00\xb8\x6d\x87\x81\x43\xdf\xfb\x9f\x40\xea\x44" 826 + "\x81\x00\x4e\x29\x08\xed\x8c\x73\x30\x6c\x22\xb3\x97\x76\xf6\x04" 827 + "\x99\x09\x37\x4d\xfa\x02\x20\x1e\xb9\x75\x31\xf6\x04\xa5\x4d\xf8" 828 + "\x00\xdd\xab\xd4\xc0\x2b\xe6\x5c\xad\xc3\x78\x1c\xc2\xc1\x19\x76" 829 + "\x31\x79\x4a\xe9\x81\x6a\xee", 830 + .c_size = 71, 831 + .public_key_vec = true, 832 + .siggen_sigver_test = true, 833 + }, 834 + }; 835 + 836 + /* 570 837 * EC-RDSA test vectors are generated by gost-engine. 571 838 */ 572 839 static const struct akcipher_testvec ecrdsa_tv_template[] = {