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

crypto: ecrdsa - add EC-RDSA (GOST 34.10) algorithm

Add Elliptic Curve Russian Digital Signature Algorithm (GOST R
34.10-2012, RFC 7091, ISO/IEC 14888-3) is one of the Russian (and since
2018 the CIS countries) cryptographic standard algorithms (called GOST
algorithms). Only signature verification is supported, with intent to be
used in the IMA.

Summary of the changes:

* crypto/Kconfig:
- EC-RDSA is added into Public-key cryptography section.

* crypto/Makefile:
- ecrdsa objects are added.

* crypto/asymmetric_keys/x509_cert_parser.c:
- Recognize EC-RDSA and Streebog OIDs.

* include/linux/oid_registry.h:
- EC-RDSA OIDs are added to the enum. Also, a two currently not
implemented curve OIDs are added for possible extension later (to
not change numbering and grouping).

* crypto/ecc.c:
- Kenneth MacKay copyright date is updated to 2014, because
vli_mmod_slow, ecc_point_add, ecc_point_mult_shamir are based on his
code from micro-ecc.
- Functions needed for ecrdsa are EXPORT_SYMBOL'ed.
- New functions:
vli_is_negative - helper to determine sign of vli;
vli_from_be64 - unpack big-endian array into vli (used for
a signature);
vli_from_le64 - unpack little-endian array into vli (used for
a public key);
vli_uadd, vli_usub - add/sub u64 value to/from vli (used for
increment/decrement);
mul_64_64 - optimized to use __int128 where appropriate, this speeds
up point multiplication (and as a consequence signature
verification) by the factor of 1.5-2;
vli_umult - multiply vli by a small value (speeds up point
multiplication by another factor of 1.5-2, depending on vli sizes);
vli_mmod_special - module reduction for some form of Pseudo-Mersenne
primes (used for the curves A);
vli_mmod_special2 - module reduction for another form of
Pseudo-Mersenne primes (used for the curves B);
vli_mmod_barrett - module reduction using pre-computed value (used
for the curve C);
vli_mmod_slow - more general module reduction which is much slower
(used when the modulus is subgroup order);
vli_mod_mult_slow - modular multiplication;
ecc_point_add - add two points;
ecc_point_mult_shamir - add two points multiplied by scalars in one
combined multiplication (this gives speed up by another factor 2 in
compare to two separate multiplications).
ecc_is_pubkey_valid_partial - additional samity check is added.
- Updated vli_mmod_fast with non-strict heuristic to call optimal
module reduction function depending on the prime value;
- All computations for the previously defined (two NIST) curves should
not unaffected.

* crypto/ecc.h:
- Newly exported functions are documented.

* crypto/ecrdsa_defs.h
- Five curves are defined.

* crypto/ecrdsa.c:
- Signature verification is implemented.

* crypto/ecrdsa_params.asn1, crypto/ecrdsa_pub_key.asn1:
- Templates for BER decoder for EC-RDSA parameters and public key.

Cc: linux-integrity@vger.kernel.org
Signed-off-by: Vitaly Chikunov <vt@altlinux.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Vitaly Chikunov and committed by
Herbert Xu
0d7a7864 4a2289da

+1022 -13
+11
crypto/Kconfig
··· 259 259 help 260 260 Generic implementation of the ECDH algorithm 261 261 262 + config CRYPTO_ECRDSA 263 + tristate "EC-RDSA (GOST 34.10) algorithm" 264 + select CRYPTO_ECC 265 + select CRYPTO_AKCIPHER 266 + select CRYPTO_STREEBOG 267 + help 268 + Elliptic Curve Russian Digital Signature Algorithm (GOST R 34.10-2012, 269 + RFC 7091, ISO/IEC 14888-3:2018) is one of the Russian cryptographic 270 + standard algorithms (called GOST algorithms). Only signature verification 271 + is implemented. 272 + 262 273 comment "Authenticated Encryption with Associated Data" 263 274 264 275 config CRYPTO_CCM
+8
crypto/Makefile
··· 153 153 ecdh_generic-y += ecdh_helper.o 154 154 obj-$(CONFIG_CRYPTO_ECDH) += ecdh_generic.o 155 155 156 + $(obj)/ecrdsa_params.asn1.o: $(obj)/ecrdsa_params.asn1.c $(obj)/ecrdsa_params.asn1.h 157 + $(obj)/ecrdsa_pub_key.asn1.o: $(obj)/ecrdsa_pub_key.asn1.c $(obj)/ecrdsa_pub_key.asn1.h 158 + $(obj)/ecrdsa.o: $(obj)/ecrdsa_params.asn1.h $(obj)/ecrdsa_pub_key.asn1.h 159 + ecrdsa_generic-y += ecrdsa.o 160 + ecrdsa_generic-y += ecrdsa_params.asn1.o 161 + ecrdsa_generic-y += ecrdsa_pub_key.asn1.o 162 + obj-$(CONFIG_CRYPTO_ECRDSA) += ecrdsa_generic.o 163 + 156 164 # 157 165 # generic algorithms and the async_tx api 158 166 #
+22 -4
crypto/asymmetric_keys/x509_cert_parser.c
··· 230 230 case OID_sha224WithRSAEncryption: 231 231 ctx->cert->sig->hash_algo = "sha224"; 232 232 goto rsa_pkcs1; 233 + 234 + case OID_gost2012Signature256: 235 + ctx->cert->sig->hash_algo = "streebog256"; 236 + goto ecrdsa; 237 + 238 + case OID_gost2012Signature512: 239 + ctx->cert->sig->hash_algo = "streebog512"; 240 + goto ecrdsa; 233 241 } 234 242 235 243 rsa_pkcs1: 236 244 ctx->cert->sig->pkey_algo = "rsa"; 237 245 ctx->cert->sig->encoding = "pkcs1"; 246 + ctx->algo_oid = ctx->last_oid; 247 + return 0; 248 + ecrdsa: 249 + ctx->cert->sig->pkey_algo = "ecrdsa"; 250 + ctx->cert->sig->encoding = "raw"; 238 251 ctx->algo_oid = ctx->last_oid; 239 252 return 0; 240 253 } ··· 269 256 return -EINVAL; 270 257 } 271 258 272 - if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0) { 259 + if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 || 260 + strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0) { 273 261 /* Discard the BIT STRING metadata */ 274 262 if (vlen < 1 || *(const u8 *)value != 0) 275 263 return -EBADMSG; ··· 454 440 { 455 441 struct x509_parse_context *ctx = context; 456 442 457 - if (ctx->last_oid != OID_rsaEncryption) 443 + ctx->key_algo = ctx->last_oid; 444 + if (ctx->last_oid == OID_rsaEncryption) 445 + ctx->cert->pub->pkey_algo = "rsa"; 446 + else if (ctx->last_oid == OID_gost2012PKey256 || 447 + ctx->last_oid == OID_gost2012PKey512) 448 + ctx->cert->pub->pkey_algo = "ecrdsa"; 449 + else 458 450 return -ENOPKG; 459 - 460 - ctx->cert->pub->pkey_algo = "rsa"; 461 451 462 452 /* Discard the BIT STRING metadata */ 463 453 if (vlen < 1 || *(const u8 *)value != 0)
+384 -8
crypto/ecc.c
··· 1 1 /* 2 - * Copyright (c) 2013, Kenneth MacKay 3 - * All rights reserved. 2 + * Copyright (c) 2013, 2014 Kenneth MacKay. All rights reserved. 3 + * Copyright (c) 2019 Vitaly Chikunov <vt@altlinux.org> 4 4 * 5 5 * Redistribution and use in source and binary forms, with or without 6 6 * modification, are permitted provided that the following conditions are ··· 31 31 #include <linux/fips.h> 32 32 #include <crypto/ecdh.h> 33 33 #include <crypto/rng.h> 34 + #include <asm/unaligned.h> 35 + #include <linux/ratelimit.h> 34 36 35 37 #include "ecc.h" 36 38 #include "ecc_curve_defs.h" ··· 134 132 return (vli[bit / 64] & ((u64)1 << (bit % 64))); 135 133 } 136 134 135 + static bool vli_is_negative(const u64 *vli, unsigned int ndigits) 136 + { 137 + return vli_test_bit(vli, ndigits * 64 - 1); 138 + } 139 + 137 140 /* Counts the number of 64-bit "digits" in vli. */ 138 141 static unsigned int vli_num_digits(const u64 *vli, unsigned int ndigits) 139 142 { ··· 169 162 170 163 return ((num_digits - 1) * 64 + i); 171 164 } 165 + 166 + /* Set dest from unaligned bit string src. */ 167 + void vli_from_be64(u64 *dest, const void *src, unsigned int ndigits) 168 + { 169 + int i; 170 + const u64 *from = src; 171 + 172 + for (i = 0; i < ndigits; i++) 173 + dest[i] = get_unaligned_be64(&from[ndigits - 1 - i]); 174 + } 175 + EXPORT_SYMBOL(vli_from_be64); 176 + 177 + void vli_from_le64(u64 *dest, const void *src, unsigned int ndigits) 178 + { 179 + int i; 180 + const u64 *from = src; 181 + 182 + for (i = 0; i < ndigits; i++) 183 + dest[i] = get_unaligned_le64(&from[i]); 184 + } 185 + EXPORT_SYMBOL(vli_from_le64); 172 186 173 187 /* Sets dest = src. */ 174 188 static void vli_set(u64 *dest, const u64 *src, unsigned int ndigits) ··· 270 242 return carry; 271 243 } 272 244 245 + /* Computes result = left + right, returning carry. Can modify in place. */ 246 + static u64 vli_uadd(u64 *result, const u64 *left, u64 right, 247 + unsigned int ndigits) 248 + { 249 + u64 carry = right; 250 + int i; 251 + 252 + for (i = 0; i < ndigits; i++) { 253 + u64 sum; 254 + 255 + sum = left[i] + carry; 256 + if (sum != left[i]) 257 + carry = (sum < left[i]); 258 + else 259 + carry = !!carry; 260 + 261 + result[i] = sum; 262 + } 263 + 264 + return carry; 265 + } 266 + 273 267 /* Computes result = left - right, returning borrow. Can modify in place. */ 274 268 u64 vli_sub(u64 *result, const u64 *left, const u64 *right, 275 269 unsigned int ndigits) ··· 313 263 } 314 264 EXPORT_SYMBOL(vli_sub); 315 265 266 + /* Computes result = left - right, returning borrow. Can modify in place. */ 267 + static u64 vli_usub(u64 *result, const u64 *left, u64 right, 268 + unsigned int ndigits) 269 + { 270 + u64 borrow = right; 271 + int i; 272 + 273 + for (i = 0; i < ndigits; i++) { 274 + u64 diff; 275 + 276 + diff = left[i] - borrow; 277 + if (diff != left[i]) 278 + borrow = (diff > left[i]); 279 + 280 + result[i] = diff; 281 + } 282 + 283 + return borrow; 284 + } 285 + 316 286 static uint128_t mul_64_64(u64 left, u64 right) 317 287 { 288 + uint128_t result; 289 + #if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__) 290 + unsigned __int128 m = (unsigned __int128)left * right; 291 + 292 + result.m_low = m; 293 + result.m_high = m >> 64; 294 + #else 318 295 u64 a0 = left & 0xffffffffull; 319 296 u64 a1 = left >> 32; 320 297 u64 b0 = right & 0xffffffffull; ··· 350 273 u64 m1 = a0 * b1; 351 274 u64 m2 = a1 * b0; 352 275 u64 m3 = a1 * b1; 353 - uint128_t result; 354 276 355 277 m2 += (m0 >> 32); 356 278 m2 += m1; ··· 360 284 361 285 result.m_low = (m0 & 0xffffffffull) | (m2 << 32); 362 286 result.m_high = m3 + (m2 >> 32); 363 - 287 + #endif 364 288 return result; 365 289 } 366 290 ··· 408 332 } 409 333 410 334 result[ndigits * 2 - 1] = r01.m_low; 335 + } 336 + 337 + /* Compute product = left * right, for a small right value. */ 338 + static void vli_umult(u64 *result, const u64 *left, u32 right, 339 + unsigned int ndigits) 340 + { 341 + uint128_t r01 = { 0 }; 342 + unsigned int k; 343 + 344 + for (k = 0; k < ndigits; k++) { 345 + uint128_t product; 346 + 347 + product = mul_64_64(left[k], right); 348 + r01 = add_128_128(r01, product); 349 + /* no carry */ 350 + result[k] = r01.m_low; 351 + r01.m_low = r01.m_high; 352 + r01.m_high = 0; 353 + } 354 + result[k] = r01.m_low; 355 + for (++k; k < ndigits * 2; k++) 356 + result[k] = 0; 411 357 } 412 358 413 359 static void vli_square(u64 *result, const u64 *left, unsigned int ndigits) ··· 502 404 */ 503 405 if (borrow) 504 406 vli_add(result, result, mod, ndigits); 407 + } 408 + 409 + /* 410 + * Computes result = product % mod 411 + * for special form moduli: p = 2^k-c, for small c (note the minus sign) 412 + * 413 + * References: 414 + * R. Crandall, C. Pomerance. Prime Numbers: A Computational Perspective. 415 + * 9 Fast Algorithms for Large-Integer Arithmetic. 9.2.3 Moduli of special form 416 + * Algorithm 9.2.13 (Fast mod operation for special-form moduli). 417 + */ 418 + static void vli_mmod_special(u64 *result, const u64 *product, 419 + const u64 *mod, unsigned int ndigits) 420 + { 421 + u64 c = -mod[0]; 422 + u64 t[ECC_MAX_DIGITS * 2]; 423 + u64 r[ECC_MAX_DIGITS * 2]; 424 + 425 + vli_set(r, product, ndigits * 2); 426 + while (!vli_is_zero(r + ndigits, ndigits)) { 427 + vli_umult(t, r + ndigits, c, ndigits); 428 + vli_clear(r + ndigits, ndigits); 429 + vli_add(r, r, t, ndigits * 2); 430 + } 431 + vli_set(t, mod, ndigits); 432 + vli_clear(t + ndigits, ndigits); 433 + while (vli_cmp(r, t, ndigits * 2) >= 0) 434 + vli_sub(r, r, t, ndigits * 2); 435 + vli_set(result, r, ndigits); 436 + } 437 + 438 + /* 439 + * Computes result = product % mod 440 + * for special form moduli: p = 2^{k-1}+c, for small c (note the plus sign) 441 + * where k-1 does not fit into qword boundary by -1 bit (such as 255). 442 + 443 + * References (loosely based on): 444 + * A. Menezes, P. van Oorschot, S. Vanstone. Handbook of Applied Cryptography. 445 + * 14.3.4 Reduction methods for moduli of special form. Algorithm 14.47. 446 + * URL: http://cacr.uwaterloo.ca/hac/about/chap14.pdf 447 + * 448 + * H. Cohen, G. Frey, R. Avanzi, C. Doche, T. Lange, K. Nguyen, F. Vercauteren. 449 + * Handbook of Elliptic and Hyperelliptic Curve Cryptography. 450 + * Algorithm 10.25 Fast reduction for special form moduli 451 + */ 452 + static void vli_mmod_special2(u64 *result, const u64 *product, 453 + const u64 *mod, unsigned int ndigits) 454 + { 455 + u64 c2 = mod[0] * 2; 456 + u64 q[ECC_MAX_DIGITS]; 457 + u64 r[ECC_MAX_DIGITS * 2]; 458 + u64 m[ECC_MAX_DIGITS * 2]; /* expanded mod */ 459 + int carry; /* last bit that doesn't fit into q */ 460 + int i; 461 + 462 + vli_set(m, mod, ndigits); 463 + vli_clear(m + ndigits, ndigits); 464 + 465 + vli_set(r, product, ndigits); 466 + /* q and carry are top bits */ 467 + vli_set(q, product + ndigits, ndigits); 468 + vli_clear(r + ndigits, ndigits); 469 + carry = vli_is_negative(r, ndigits); 470 + if (carry) 471 + r[ndigits - 1] &= (1ull << 63) - 1; 472 + for (i = 1; carry || !vli_is_zero(q, ndigits); i++) { 473 + u64 qc[ECC_MAX_DIGITS * 2]; 474 + 475 + vli_umult(qc, q, c2, ndigits); 476 + if (carry) 477 + vli_uadd(qc, qc, mod[0], ndigits * 2); 478 + vli_set(q, qc + ndigits, ndigits); 479 + vli_clear(qc + ndigits, ndigits); 480 + carry = vli_is_negative(qc, ndigits); 481 + if (carry) 482 + qc[ndigits - 1] &= (1ull << 63) - 1; 483 + if (i & 1) 484 + vli_sub(r, r, qc, ndigits * 2); 485 + else 486 + vli_add(r, r, qc, ndigits * 2); 487 + } 488 + while (vli_is_negative(r, ndigits * 2)) 489 + vli_add(r, r, m, ndigits * 2); 490 + while (vli_cmp(r, m, ndigits * 2) >= 0) 491 + vli_sub(r, r, m, ndigits * 2); 492 + 493 + vli_set(result, r, ndigits); 494 + } 495 + 496 + /* 497 + * Computes result = product % mod, where product is 2N words long. 498 + * Reference: Ken MacKay's micro-ecc. 499 + * Currently only designed to work for curve_p or curve_n. 500 + */ 501 + static void vli_mmod_slow(u64 *result, u64 *product, const u64 *mod, 502 + unsigned int ndigits) 503 + { 504 + u64 mod_m[2 * ECC_MAX_DIGITS]; 505 + u64 tmp[2 * ECC_MAX_DIGITS]; 506 + u64 *v[2] = { tmp, product }; 507 + u64 carry = 0; 508 + unsigned int i; 509 + /* Shift mod so its highest set bit is at the maximum position. */ 510 + int shift = (ndigits * 2 * 64) - vli_num_bits(mod, ndigits); 511 + int word_shift = shift / 64; 512 + int bit_shift = shift % 64; 513 + 514 + vli_clear(mod_m, word_shift); 515 + if (bit_shift > 0) { 516 + for (i = 0; i < ndigits; ++i) { 517 + mod_m[word_shift + i] = (mod[i] << bit_shift) | carry; 518 + carry = mod[i] >> (64 - bit_shift); 519 + } 520 + } else 521 + vli_set(mod_m + word_shift, mod, ndigits); 522 + 523 + for (i = 1; shift >= 0; --shift) { 524 + u64 borrow = 0; 525 + unsigned int j; 526 + 527 + for (j = 0; j < ndigits * 2; ++j) { 528 + u64 diff = v[i][j] - mod_m[j] - borrow; 529 + 530 + if (diff != v[i][j]) 531 + borrow = (diff > v[i][j]); 532 + v[1 - i][j] = diff; 533 + } 534 + i = !(i ^ borrow); /* Swap the index if there was no borrow */ 535 + vli_rshift1(mod_m, ndigits); 536 + mod_m[ndigits - 1] |= mod_m[ndigits] << (64 - 1); 537 + vli_rshift1(mod_m + ndigits, ndigits); 538 + } 539 + vli_set(result, v[i], ndigits); 540 + } 541 + 542 + /* Computes result = product % mod using Barrett's reduction with precomputed 543 + * value mu appended to the mod after ndigits, mu = (2^{2w} / mod) and have 544 + * length ndigits + 1, where mu * (2^w - 1) should not overflow ndigits 545 + * boundary. 546 + * 547 + * Reference: 548 + * R. Brent, P. Zimmermann. Modern Computer Arithmetic. 2010. 549 + * 2.4.1 Barrett's algorithm. Algorithm 2.5. 550 + */ 551 + static void vli_mmod_barrett(u64 *result, u64 *product, const u64 *mod, 552 + unsigned int ndigits) 553 + { 554 + u64 q[ECC_MAX_DIGITS * 2]; 555 + u64 r[ECC_MAX_DIGITS * 2]; 556 + const u64 *mu = mod + ndigits; 557 + 558 + vli_mult(q, product + ndigits, mu, ndigits); 559 + if (mu[ndigits]) 560 + vli_add(q + ndigits, q + ndigits, product + ndigits, ndigits); 561 + vli_mult(r, mod, q + ndigits, ndigits); 562 + vli_sub(r, product, r, ndigits * 2); 563 + while (!vli_is_zero(r + ndigits, ndigits) || 564 + vli_cmp(r, mod, ndigits) != -1) { 565 + u64 carry; 566 + 567 + carry = vli_sub(r, r, mod, ndigits); 568 + vli_usub(r + ndigits, r + ndigits, carry, ndigits); 569 + } 570 + vli_set(result, r, ndigits); 505 571 } 506 572 507 573 /* Computes p_result = p_product % curve_p. ··· 775 513 } 776 514 } 777 515 778 - /* Computes result = product % curve_prime 779 - * from http://www.nsa.gov/ia/_files/nist-routines.pdf 780 - */ 516 + /* Computes result = product % curve_prime for different curve_primes. 517 + * 518 + * Note that curve_primes are distinguished just by heuristic check and 519 + * not by complete conformance check. 520 + */ 781 521 static bool vli_mmod_fast(u64 *result, u64 *product, 782 522 const u64 *curve_prime, unsigned int ndigits) 783 523 { 784 524 u64 tmp[2 * ECC_MAX_DIGITS]; 525 + 526 + /* Currently, both NIST primes have -1 in lowest qword. */ 527 + if (curve_prime[0] != -1ull) { 528 + /* Try to handle Pseudo-Marsenne primes. */ 529 + if (curve_prime[ndigits - 1] == -1ull) { 530 + vli_mmod_special(result, product, curve_prime, 531 + ndigits); 532 + return true; 533 + } else if (curve_prime[ndigits - 1] == 1ull << 63 && 534 + curve_prime[ndigits - 2] == 0) { 535 + vli_mmod_special2(result, product, curve_prime, 536 + ndigits); 537 + return true; 538 + } 539 + vli_mmod_barrett(result, product, curve_prime, ndigits); 540 + return true; 541 + } 785 542 786 543 switch (ndigits) { 787 544 case 3: ··· 810 529 vli_mmod_fast_256(result, product, curve_prime, tmp); 811 530 break; 812 531 default: 813 - pr_err("unsupports digits size!\n"); 532 + pr_err_ratelimited("ecc: unsupported digits size!\n"); 814 533 return false; 815 534 } 816 535 817 536 return true; 818 537 } 538 + 539 + /* Computes result = (left * right) % mod. 540 + * Assumes that mod is big enough curve order. 541 + */ 542 + void vli_mod_mult_slow(u64 *result, const u64 *left, const u64 *right, 543 + const u64 *mod, unsigned int ndigits) 544 + { 545 + u64 product[ECC_MAX_DIGITS * 2]; 546 + 547 + vli_mult(product, left, right, ndigits); 548 + vli_mmod_slow(result, product, mod, ndigits); 549 + } 550 + EXPORT_SYMBOL(vli_mod_mult_slow); 819 551 820 552 /* Computes result = (left * right) % curve_prime. */ 821 553 static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right, ··· 1202 908 vli_set(result->y, ry[0], ndigits); 1203 909 } 1204 910 911 + /* Computes R = P + Q mod p */ 912 + static void ecc_point_add(const struct ecc_point *result, 913 + const struct ecc_point *p, const struct ecc_point *q, 914 + const struct ecc_curve *curve) 915 + { 916 + u64 z[ECC_MAX_DIGITS]; 917 + u64 px[ECC_MAX_DIGITS]; 918 + u64 py[ECC_MAX_DIGITS]; 919 + unsigned int ndigits = curve->g.ndigits; 920 + 921 + vli_set(result->x, q->x, ndigits); 922 + vli_set(result->y, q->y, ndigits); 923 + vli_mod_sub(z, result->x, p->x, curve->p, ndigits); 924 + vli_set(px, p->x, ndigits); 925 + vli_set(py, p->y, ndigits); 926 + xycz_add(px, py, result->x, result->y, curve->p, ndigits); 927 + vli_mod_inv(z, z, curve->p, ndigits); 928 + apply_z(result->x, result->y, z, curve->p, ndigits); 929 + } 930 + 931 + /* Computes R = u1P + u2Q mod p using Shamir's trick. 932 + * Based on: Kenneth MacKay's micro-ecc (2014). 933 + */ 934 + void ecc_point_mult_shamir(const struct ecc_point *result, 935 + const u64 *u1, const struct ecc_point *p, 936 + const u64 *u2, const struct ecc_point *q, 937 + const struct ecc_curve *curve) 938 + { 939 + u64 z[ECC_MAX_DIGITS]; 940 + u64 sump[2][ECC_MAX_DIGITS]; 941 + u64 *rx = result->x; 942 + u64 *ry = result->y; 943 + unsigned int ndigits = curve->g.ndigits; 944 + unsigned int num_bits; 945 + struct ecc_point sum = ECC_POINT_INIT(sump[0], sump[1], ndigits); 946 + const struct ecc_point *points[4]; 947 + const struct ecc_point *point; 948 + unsigned int idx; 949 + int i; 950 + 951 + ecc_point_add(&sum, p, q, curve); 952 + points[0] = NULL; 953 + points[1] = p; 954 + points[2] = q; 955 + points[3] = &sum; 956 + 957 + num_bits = max(vli_num_bits(u1, ndigits), 958 + vli_num_bits(u2, ndigits)); 959 + i = num_bits - 1; 960 + idx = (!!vli_test_bit(u1, i)) | ((!!vli_test_bit(u2, i)) << 1); 961 + point = points[idx]; 962 + 963 + vli_set(rx, point->x, ndigits); 964 + vli_set(ry, point->y, ndigits); 965 + vli_clear(z + 1, ndigits - 1); 966 + z[0] = 1; 967 + 968 + for (--i; i >= 0; i--) { 969 + ecc_point_double_jacobian(rx, ry, z, curve->p, ndigits); 970 + idx = (!!vli_test_bit(u1, i)) | ((!!vli_test_bit(u2, i)) << 1); 971 + point = points[idx]; 972 + if (point) { 973 + u64 tx[ECC_MAX_DIGITS]; 974 + u64 ty[ECC_MAX_DIGITS]; 975 + u64 tz[ECC_MAX_DIGITS]; 976 + 977 + vli_set(tx, point->x, ndigits); 978 + vli_set(ty, point->y, ndigits); 979 + apply_z(tx, ty, z, curve->p, ndigits); 980 + vli_mod_sub(tz, rx, tx, curve->p, ndigits); 981 + xycz_add(tx, ty, rx, ry, curve->p, ndigits); 982 + vli_mod_mult_fast(z, z, tz, curve->p, ndigits); 983 + } 984 + } 985 + vli_mod_inv(z, z, curve->p, ndigits); 986 + apply_z(rx, ry, z, curve->p, ndigits); 987 + } 988 + EXPORT_SYMBOL(ecc_point_mult_shamir); 989 + 1205 990 static inline void ecc_swap_digits(const u64 *in, u64 *out, 1206 991 unsigned int ndigits) 1207 992 { ··· 1423 1050 struct ecc_point *pk) 1424 1051 { 1425 1052 u64 yy[ECC_MAX_DIGITS], xxx[ECC_MAX_DIGITS], w[ECC_MAX_DIGITS]; 1053 + 1054 + if (WARN_ON(pk->ndigits != curve->g.ndigits)) 1055 + return -EINVAL; 1426 1056 1427 1057 /* Check 1: Verify key is not the zero point. */ 1428 1058 if (ecc_point_is_zero(pk))
+53 -1
crypto/ecc.h
··· 26 26 #ifndef _CRYPTO_ECC_H 27 27 #define _CRYPTO_ECC_H 28 28 29 + /* One digit is u64 qword. */ 29 30 #define ECC_CURVE_NIST_P192_DIGITS 3 30 31 #define ECC_CURVE_NIST_P256_DIGITS 4 31 - #define ECC_MAX_DIGITS ECC_CURVE_NIST_P256_DIGITS 32 + #define ECC_MAX_DIGITS (512 / 64) 32 33 33 34 #define ECC_DIGITS_TO_BYTES_SHIFT 3 34 35 ··· 45 44 u64 *y; 46 45 u8 ndigits; 47 46 }; 47 + 48 + #define ECC_POINT_INIT(x, y, ndigits) (struct ecc_point) { x, y, ndigits } 48 49 49 50 /** 50 51 * struct ecc_curve - definition of elliptic curve ··· 183 180 unsigned int ndigits); 184 181 185 182 /** 183 + * vli_from_be64() - Load vli from big-endian u64 array 184 + * 185 + * @dest: destination vli 186 + * @src: source array of u64 BE values 187 + * @ndigits: length of both vli and array 188 + */ 189 + void vli_from_be64(u64 *dest, const void *src, unsigned int ndigits); 190 + 191 + /** 192 + * vli_from_le64() - Load vli from little-endian u64 array 193 + * 194 + * @dest: destination vli 195 + * @src: source array of u64 LE values 196 + * @ndigits: length of both vli and array 197 + */ 198 + void vli_from_le64(u64 *dest, const void *src, unsigned int ndigits); 199 + 200 + /** 186 201 * vli_mod_inv() - Modular inversion 187 202 * 188 203 * @result: where to write vli number ··· 211 190 void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod, 212 191 unsigned int ndigits); 213 192 193 + /** 194 + * vli_mod_mult_slow() - Modular multiplication 195 + * 196 + * @result: where to write result value 197 + * @left: vli number to multiply with @right 198 + * @right: vli number to multiply with @left 199 + * @mod: modulus 200 + * @ndigits: length of all vlis 201 + * 202 + * Note: Assumes that mod is big enough curve order. 203 + */ 204 + void vli_mod_mult_slow(u64 *result, const u64 *left, const u64 *right, 205 + const u64 *mod, unsigned int ndigits); 206 + 207 + /** 208 + * ecc_point_mult_shamir() - Add two points multiplied by scalars 209 + * 210 + * @result: resulting point 211 + * @x: scalar to multiply with @p 212 + * @p: point to multiply with @x 213 + * @y: scalar to multiply with @q 214 + * @q: point to multiply with @y 215 + * @curve: curve 216 + * 217 + * Returns result = x * p + x * q over the curve. 218 + * This works faster than two multiplications and addition. 219 + */ 220 + void ecc_point_mult_shamir(const struct ecc_point *result, 221 + const u64 *x, const struct ecc_point *p, 222 + const u64 *y, const struct ecc_point *q, 223 + const struct ecc_curve *curve); 214 224 #endif
+296
crypto/ecrdsa.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Elliptic Curve (Russian) Digital Signature Algorithm for Cryptographic API 4 + * 5 + * Copyright (c) 2019 Vitaly Chikunov <vt@altlinux.org> 6 + * 7 + * References: 8 + * GOST 34.10-2018, GOST R 34.10-2012, RFC 7091, ISO/IEC 14888-3:2018. 9 + * 10 + * Historical references: 11 + * GOST R 34.10-2001, RFC 4357, ISO/IEC 14888-3:2006/Amd 1:2010. 12 + * 13 + * This program is free software; you can redistribute it and/or modify it 14 + * under the terms of the GNU General Public License as published by the Free 15 + * Software Foundation; either version 2 of the License, or (at your option) 16 + * any later version. 17 + */ 18 + 19 + #include <linux/module.h> 20 + #include <linux/crypto.h> 21 + #include <crypto/streebog.h> 22 + #include <crypto/internal/akcipher.h> 23 + #include <crypto/akcipher.h> 24 + #include <linux/oid_registry.h> 25 + #include "ecrdsa_params.asn1.h" 26 + #include "ecrdsa_pub_key.asn1.h" 27 + #include "ecc.h" 28 + #include "ecrdsa_defs.h" 29 + 30 + #define ECRDSA_MAX_SIG_SIZE (2 * 512 / 8) 31 + #define ECRDSA_MAX_DIGITS (512 / 64) 32 + 33 + struct ecrdsa_ctx { 34 + enum OID algo_oid; /* overall public key oid */ 35 + enum OID curve_oid; /* parameter */ 36 + enum OID digest_oid; /* parameter */ 37 + const struct ecc_curve *curve; /* curve from oid */ 38 + unsigned int digest_len; /* parameter (bytes) */ 39 + const char *digest; /* digest name from oid */ 40 + unsigned int key_len; /* @key length (bytes) */ 41 + const char *key; /* raw public key */ 42 + struct ecc_point pub_key; 43 + u64 _pubp[2][ECRDSA_MAX_DIGITS]; /* point storage for @pub_key */ 44 + }; 45 + 46 + static const struct ecc_curve *get_curve_by_oid(enum OID oid) 47 + { 48 + switch (oid) { 49 + case OID_gostCPSignA: 50 + case OID_gostTC26Sign256B: 51 + return &gost_cp256a; 52 + case OID_gostCPSignB: 53 + case OID_gostTC26Sign256C: 54 + return &gost_cp256b; 55 + case OID_gostCPSignC: 56 + case OID_gostTC26Sign256D: 57 + return &gost_cp256c; 58 + case OID_gostTC26Sign512A: 59 + return &gost_tc512a; 60 + case OID_gostTC26Sign512B: 61 + return &gost_tc512b; 62 + /* The following two aren't implemented: */ 63 + case OID_gostTC26Sign256A: 64 + case OID_gostTC26Sign512C: 65 + default: 66 + return NULL; 67 + } 68 + } 69 + 70 + static int ecrdsa_verify(struct akcipher_request *req) 71 + { 72 + struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); 73 + struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm); 74 + unsigned char sig[ECRDSA_MAX_SIG_SIZE]; 75 + unsigned char digest[STREEBOG512_DIGEST_SIZE]; 76 + unsigned int ndigits = req->dst_len / sizeof(u64); 77 + u64 r[ECRDSA_MAX_DIGITS]; /* witness (r) */ 78 + u64 _r[ECRDSA_MAX_DIGITS]; /* -r */ 79 + u64 s[ECRDSA_MAX_DIGITS]; /* second part of sig (s) */ 80 + u64 e[ECRDSA_MAX_DIGITS]; /* h \mod q */ 81 + u64 *v = e; /* e^{-1} \mod q */ 82 + u64 z1[ECRDSA_MAX_DIGITS]; 83 + u64 *z2 = _r; 84 + struct ecc_point cc = ECC_POINT_INIT(s, e, ndigits); /* reuse s, e */ 85 + 86 + /* 87 + * Digest value, digest algorithm, and curve (modulus) should have the 88 + * same length (256 or 512 bits), public key and signature should be 89 + * twice bigger. 90 + */ 91 + if (!ctx->curve || 92 + !ctx->digest || 93 + !req->src || 94 + !ctx->pub_key.x || 95 + req->dst_len != ctx->digest_len || 96 + req->dst_len != ctx->curve->g.ndigits * sizeof(u64) || 97 + ctx->pub_key.ndigits != ctx->curve->g.ndigits || 98 + req->dst_len * 2 != req->src_len || 99 + WARN_ON(req->src_len > sizeof(sig)) || 100 + WARN_ON(req->dst_len > sizeof(digest))) 101 + return -EBADMSG; 102 + 103 + sg_copy_to_buffer(req->src, sg_nents_for_len(req->src, req->src_len), 104 + sig, req->src_len); 105 + sg_pcopy_to_buffer(req->src, 106 + sg_nents_for_len(req->src, 107 + req->src_len + req->dst_len), 108 + digest, req->dst_len, req->src_len); 109 + 110 + vli_from_be64(s, sig, ndigits); 111 + vli_from_be64(r, sig + ndigits * sizeof(u64), ndigits); 112 + 113 + /* Step 1: verify that 0 < r < q, 0 < s < q */ 114 + if (vli_is_zero(r, ndigits) || 115 + vli_cmp(r, ctx->curve->n, ndigits) == 1 || 116 + vli_is_zero(s, ndigits) || 117 + vli_cmp(s, ctx->curve->n, ndigits) == 1) 118 + return -EKEYREJECTED; 119 + 120 + /* Step 2: calculate hash (h) of the message (passed as input) */ 121 + /* Step 3: calculate e = h \mod q */ 122 + vli_from_le64(e, digest, ndigits); 123 + if (vli_cmp(e, ctx->curve->n, ndigits) == 1) 124 + vli_sub(e, e, ctx->curve->n, ndigits); 125 + if (vli_is_zero(e, ndigits)) 126 + e[0] = 1; 127 + 128 + /* Step 4: calculate v = e^{-1} \mod q */ 129 + vli_mod_inv(v, e, ctx->curve->n, ndigits); 130 + 131 + /* Step 5: calculate z_1 = sv \mod q, z_2 = -rv \mod q */ 132 + vli_mod_mult_slow(z1, s, v, ctx->curve->n, ndigits); 133 + vli_sub(_r, ctx->curve->n, r, ndigits); 134 + vli_mod_mult_slow(z2, _r, v, ctx->curve->n, ndigits); 135 + 136 + /* Step 6: calculate point C = z_1P + z_2Q, and R = x_c \mod q */ 137 + ecc_point_mult_shamir(&cc, z1, &ctx->curve->g, z2, &ctx->pub_key, 138 + ctx->curve); 139 + if (vli_cmp(cc.x, ctx->curve->n, ndigits) == 1) 140 + vli_sub(cc.x, cc.x, ctx->curve->n, ndigits); 141 + 142 + /* Step 7: if R == r signature is valid */ 143 + if (!vli_cmp(cc.x, r, ndigits)) 144 + return 0; 145 + else 146 + return -EKEYREJECTED; 147 + } 148 + 149 + int ecrdsa_param_curve(void *context, size_t hdrlen, unsigned char tag, 150 + const void *value, size_t vlen) 151 + { 152 + struct ecrdsa_ctx *ctx = context; 153 + 154 + ctx->curve_oid = look_up_OID(value, vlen); 155 + if (!ctx->curve_oid) 156 + return -EINVAL; 157 + ctx->curve = get_curve_by_oid(ctx->curve_oid); 158 + return 0; 159 + } 160 + 161 + /* Optional. If present should match expected digest algo OID. */ 162 + int ecrdsa_param_digest(void *context, size_t hdrlen, unsigned char tag, 163 + const void *value, size_t vlen) 164 + { 165 + struct ecrdsa_ctx *ctx = context; 166 + int digest_oid = look_up_OID(value, vlen); 167 + 168 + if (digest_oid != ctx->digest_oid) 169 + return -EINVAL; 170 + return 0; 171 + } 172 + 173 + int ecrdsa_parse_pub_key(void *context, size_t hdrlen, unsigned char tag, 174 + const void *value, size_t vlen) 175 + { 176 + struct ecrdsa_ctx *ctx = context; 177 + 178 + ctx->key = value; 179 + ctx->key_len = vlen; 180 + return 0; 181 + } 182 + 183 + static u8 *ecrdsa_unpack_u32(u32 *dst, void *src) 184 + { 185 + memcpy(dst, src, sizeof(u32)); 186 + return src + sizeof(u32); 187 + } 188 + 189 + /* Parse BER encoded subjectPublicKey. */ 190 + static int ecrdsa_set_pub_key(struct crypto_akcipher *tfm, const void *key, 191 + unsigned int keylen) 192 + { 193 + struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm); 194 + unsigned int ndigits; 195 + u32 algo, paramlen; 196 + u8 *params; 197 + int err; 198 + 199 + err = asn1_ber_decoder(&ecrdsa_pub_key_decoder, ctx, key, keylen); 200 + if (err < 0) 201 + return err; 202 + 203 + /* Key parameters is in the key after keylen. */ 204 + params = ecrdsa_unpack_u32(&paramlen, 205 + ecrdsa_unpack_u32(&algo, (u8 *)key + keylen)); 206 + 207 + if (algo == OID_gost2012PKey256) { 208 + ctx->digest = "streebog256"; 209 + ctx->digest_oid = OID_gost2012Digest256; 210 + ctx->digest_len = 256 / 8; 211 + } else if (algo == OID_gost2012PKey512) { 212 + ctx->digest = "streebog512"; 213 + ctx->digest_oid = OID_gost2012Digest512; 214 + ctx->digest_len = 512 / 8; 215 + } else 216 + return -ENOPKG; 217 + ctx->algo_oid = algo; 218 + 219 + /* Parse SubjectPublicKeyInfo.AlgorithmIdentifier.parameters. */ 220 + err = asn1_ber_decoder(&ecrdsa_params_decoder, ctx, params, paramlen); 221 + if (err < 0) 222 + return err; 223 + /* 224 + * Sizes of algo (set in digest_len) and curve should match 225 + * each other. 226 + */ 227 + if (!ctx->curve || 228 + ctx->curve->g.ndigits * sizeof(u64) != ctx->digest_len) 229 + return -ENOPKG; 230 + /* 231 + * Key is two 256- or 512-bit coordinates which should match 232 + * curve size. 233 + */ 234 + if ((ctx->key_len != (2 * 256 / 8) && 235 + ctx->key_len != (2 * 512 / 8)) || 236 + ctx->key_len != ctx->curve->g.ndigits * sizeof(u64) * 2) 237 + return -ENOPKG; 238 + 239 + ndigits = ctx->key_len / sizeof(u64) / 2; 240 + ctx->pub_key = ECC_POINT_INIT(ctx->_pubp[0], ctx->_pubp[1], ndigits); 241 + vli_from_le64(ctx->pub_key.x, ctx->key, ndigits); 242 + vli_from_le64(ctx->pub_key.y, ctx->key + ndigits * sizeof(u64), 243 + ndigits); 244 + 245 + if (ecc_is_pubkey_valid_partial(ctx->curve, &ctx->pub_key)) 246 + return -EKEYREJECTED; 247 + 248 + return 0; 249 + } 250 + 251 + static unsigned int ecrdsa_max_size(struct crypto_akcipher *tfm) 252 + { 253 + struct ecrdsa_ctx *ctx = akcipher_tfm_ctx(tfm); 254 + 255 + /* 256 + * Verify doesn't need any output, so it's just informational 257 + * for keyctl to determine the key bit size. 258 + */ 259 + return ctx->pub_key.ndigits * sizeof(u64); 260 + } 261 + 262 + static void ecrdsa_exit_tfm(struct crypto_akcipher *tfm) 263 + { 264 + } 265 + 266 + static struct akcipher_alg ecrdsa_alg = { 267 + .verify = ecrdsa_verify, 268 + .set_pub_key = ecrdsa_set_pub_key, 269 + .max_size = ecrdsa_max_size, 270 + .exit = ecrdsa_exit_tfm, 271 + .base = { 272 + .cra_name = "ecrdsa", 273 + .cra_driver_name = "ecrdsa-generic", 274 + .cra_priority = 100, 275 + .cra_module = THIS_MODULE, 276 + .cra_ctxsize = sizeof(struct ecrdsa_ctx), 277 + }, 278 + }; 279 + 280 + static int __init ecrdsa_mod_init(void) 281 + { 282 + return crypto_register_akcipher(&ecrdsa_alg); 283 + } 284 + 285 + static void __exit ecrdsa_mod_fini(void) 286 + { 287 + crypto_unregister_akcipher(&ecrdsa_alg); 288 + } 289 + 290 + module_init(ecrdsa_mod_init); 291 + module_exit(ecrdsa_mod_fini); 292 + 293 + MODULE_LICENSE("GPL"); 294 + MODULE_AUTHOR("Vitaly Chikunov <vt@altlinux.org>"); 295 + MODULE_DESCRIPTION("EC-RDSA generic algorithm"); 296 + MODULE_ALIAS_CRYPTO("ecrdsa-generic");
+225
crypto/ecrdsa_defs.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Definitions of EC-RDSA Curve Parameters 4 + * 5 + * Copyright (c) 2019 Vitaly Chikunov <vt@altlinux.org> 6 + * 7 + * This program is free software; you can redistribute it and/or modify it 8 + * under the terms of the GNU General Public License as published by the Free 9 + * Software Foundation; either version 2 of the License, or (at your option) 10 + * any later version. 11 + */ 12 + 13 + #ifndef _CRYTO_ECRDSA_DEFS_H 14 + #define _CRYTO_ECRDSA_DEFS_H 15 + 16 + #include "ecc.h" 17 + 18 + #define ECRDSA_MAX_SIG_SIZE (2 * 512 / 8) 19 + #define ECRDSA_MAX_DIGITS (512 / 64) 20 + 21 + /* 22 + * EC-RDSA uses its own set of curves. 23 + * 24 + * cp256{a,b,c} curves first defined for GOST R 34.10-2001 in RFC 4357 (as 25 + * 256-bit {A,B,C}-ParamSet), but inherited for GOST R 34.10-2012 and 26 + * proposed for use in R 50.1.114-2016 and RFC 7836 as the 256-bit curves. 27 + */ 28 + /* OID_gostCPSignA 1.2.643.2.2.35.1 */ 29 + static u64 cp256a_g_x[] = { 30 + 0x0000000000000001ull, 0x0000000000000000ull, 31 + 0x0000000000000000ull, 0x0000000000000000ull, }; 32 + static u64 cp256a_g_y[] = { 33 + 0x22ACC99C9E9F1E14ull, 0x35294F2DDF23E3B1ull, 34 + 0x27DF505A453F2B76ull, 0x8D91E471E0989CDAull, }; 35 + static u64 cp256a_p[] = { /* p = 2^256 - 617 */ 36 + 0xFFFFFFFFFFFFFD97ull, 0xFFFFFFFFFFFFFFFFull, 37 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull }; 38 + static u64 cp256a_n[] = { 39 + 0x45841B09B761B893ull, 0x6C611070995AD100ull, 40 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull }; 41 + static u64 cp256a_a[] = { /* a = p - 3 */ 42 + 0xFFFFFFFFFFFFFD94ull, 0xFFFFFFFFFFFFFFFFull, 43 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull }; 44 + static u64 cp256a_b[] = { 45 + 0x00000000000000a6ull, 0x0000000000000000ull, 46 + 0x0000000000000000ull, 0x0000000000000000ull }; 47 + 48 + static struct ecc_curve gost_cp256a = { 49 + .name = "cp256a", 50 + .g = { 51 + .x = cp256a_g_x, 52 + .y = cp256a_g_y, 53 + .ndigits = 256 / 64, 54 + }, 55 + .p = cp256a_p, 56 + .n = cp256a_n, 57 + .a = cp256a_a, 58 + .b = cp256a_b 59 + }; 60 + 61 + /* OID_gostCPSignB 1.2.643.2.2.35.2 */ 62 + static u64 cp256b_g_x[] = { 63 + 0x0000000000000001ull, 0x0000000000000000ull, 64 + 0x0000000000000000ull, 0x0000000000000000ull, }; 65 + static u64 cp256b_g_y[] = { 66 + 0x744BF8D717717EFCull, 0xC545C9858D03ECFBull, 67 + 0xB83D1C3EB2C070E5ull, 0x3FA8124359F96680ull, }; 68 + static u64 cp256b_p[] = { /* p = 2^255 + 3225 */ 69 + 0x0000000000000C99ull, 0x0000000000000000ull, 70 + 0x0000000000000000ull, 0x8000000000000000ull, }; 71 + static u64 cp256b_n[] = { 72 + 0xE497161BCC8A198Full, 0x5F700CFFF1A624E5ull, 73 + 0x0000000000000001ull, 0x8000000000000000ull, }; 74 + static u64 cp256b_a[] = { /* a = p - 3 */ 75 + 0x0000000000000C96ull, 0x0000000000000000ull, 76 + 0x0000000000000000ull, 0x8000000000000000ull, }; 77 + static u64 cp256b_b[] = { 78 + 0x2F49D4CE7E1BBC8Bull, 0xE979259373FF2B18ull, 79 + 0x66A7D3C25C3DF80Aull, 0x3E1AF419A269A5F8ull, }; 80 + 81 + static struct ecc_curve gost_cp256b = { 82 + .name = "cp256b", 83 + .g = { 84 + .x = cp256b_g_x, 85 + .y = cp256b_g_y, 86 + .ndigits = 256 / 64, 87 + }, 88 + .p = cp256b_p, 89 + .n = cp256b_n, 90 + .a = cp256b_a, 91 + .b = cp256b_b 92 + }; 93 + 94 + /* OID_gostCPSignC 1.2.643.2.2.35.3 */ 95 + static u64 cp256c_g_x[] = { 96 + 0x0000000000000000ull, 0x0000000000000000ull, 97 + 0x0000000000000000ull, 0x0000000000000000ull, }; 98 + static u64 cp256c_g_y[] = { 99 + 0x366E550DFDB3BB67ull, 0x4D4DC440D4641A8Full, 100 + 0x3CBF3783CD08C0EEull, 0x41ECE55743711A8Cull, }; 101 + static u64 cp256c_p[] = { 102 + 0x7998F7B9022D759Bull, 0xCF846E86789051D3ull, 103 + 0xAB1EC85E6B41C8AAull, 0x9B9F605F5A858107ull, 104 + /* pre-computed value for Barrett's reduction */ 105 + 0xedc283cdd217b5a2ull, 0xbac48fc06398ae59ull, 106 + 0x405384d55f9f3b73ull, 0xa51f176161f1d734ull, 107 + 0x0000000000000001ull, }; 108 + static u64 cp256c_n[] = { 109 + 0xF02F3A6598980BB9ull, 0x582CA3511EDDFB74ull, 110 + 0xAB1EC85E6B41C8AAull, 0x9B9F605F5A858107ull, }; 111 + static u64 cp256c_a[] = { /* a = p - 3 */ 112 + 0x7998F7B9022D7598ull, 0xCF846E86789051D3ull, 113 + 0xAB1EC85E6B41C8AAull, 0x9B9F605F5A858107ull, }; 114 + static u64 cp256c_b[] = { 115 + 0x000000000000805aull, 0x0000000000000000ull, 116 + 0x0000000000000000ull, 0x0000000000000000ull, }; 117 + 118 + static struct ecc_curve gost_cp256c = { 119 + .name = "cp256c", 120 + .g = { 121 + .x = cp256c_g_x, 122 + .y = cp256c_g_y, 123 + .ndigits = 256 / 64, 124 + }, 125 + .p = cp256c_p, 126 + .n = cp256c_n, 127 + .a = cp256c_a, 128 + .b = cp256c_b 129 + }; 130 + 131 + /* tc512{a,b} curves first recommended in 2013 and then standardized in 132 + * R 50.1.114-2016 and RFC 7836 for use with GOST R 34.10-2012 (as TC26 133 + * 512-bit ParamSet{A,B}). 134 + */ 135 + /* OID_gostTC26Sign512A 1.2.643.7.1.2.1.2.1 */ 136 + static u64 tc512a_g_x[] = { 137 + 0x0000000000000003ull, 0x0000000000000000ull, 138 + 0x0000000000000000ull, 0x0000000000000000ull, 139 + 0x0000000000000000ull, 0x0000000000000000ull, 140 + 0x0000000000000000ull, 0x0000000000000000ull, }; 141 + static u64 tc512a_g_y[] = { 142 + 0x89A589CB5215F2A4ull, 0x8028FE5FC235F5B8ull, 143 + 0x3D75E6A50E3A41E9ull, 0xDF1626BE4FD036E9ull, 144 + 0x778064FDCBEFA921ull, 0xCE5E1C93ACF1ABC1ull, 145 + 0xA61B8816E25450E6ull, 0x7503CFE87A836AE3ull, }; 146 + static u64 tc512a_p[] = { /* p = 2^512 - 569 */ 147 + 0xFFFFFFFFFFFFFDC7ull, 0xFFFFFFFFFFFFFFFFull, 148 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 149 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 150 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, }; 151 + static u64 tc512a_n[] = { 152 + 0xCACDB1411F10B275ull, 0x9B4B38ABFAD2B85Dull, 153 + 0x6FF22B8D4E056060ull, 0x27E69532F48D8911ull, 154 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 155 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, }; 156 + static u64 tc512a_a[] = { /* a = p - 3 */ 157 + 0xFFFFFFFFFFFFFDC4ull, 0xFFFFFFFFFFFFFFFFull, 158 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 159 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, 160 + 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull, }; 161 + static u64 tc512a_b[] = { 162 + 0x503190785A71C760ull, 0x862EF9D4EBEE4761ull, 163 + 0x4CB4574010DA90DDull, 0xEE3CB090F30D2761ull, 164 + 0x79BD081CFD0B6265ull, 0x34B82574761CB0E8ull, 165 + 0xC1BD0B2B6667F1DAull, 0xE8C2505DEDFC86DDull, }; 166 + 167 + static struct ecc_curve gost_tc512a = { 168 + .name = "tc512a", 169 + .g = { 170 + .x = tc512a_g_x, 171 + .y = tc512a_g_y, 172 + .ndigits = 512 / 64, 173 + }, 174 + .p = tc512a_p, 175 + .n = tc512a_n, 176 + .a = tc512a_a, 177 + .b = tc512a_b 178 + }; 179 + 180 + /* OID_gostTC26Sign512B 1.2.643.7.1.2.1.2.2 */ 181 + static u64 tc512b_g_x[] = { 182 + 0x0000000000000002ull, 0x0000000000000000ull, 183 + 0x0000000000000000ull, 0x0000000000000000ull, 184 + 0x0000000000000000ull, 0x0000000000000000ull, 185 + 0x0000000000000000ull, 0x0000000000000000ull, }; 186 + static u64 tc512b_g_y[] = { 187 + 0x7E21340780FE41BDull, 0x28041055F94CEEECull, 188 + 0x152CBCAAF8C03988ull, 0xDCB228FD1EDF4A39ull, 189 + 0xBE6DD9E6C8EC7335ull, 0x3C123B697578C213ull, 190 + 0x2C071E3647A8940Full, 0x1A8F7EDA389B094Cull, }; 191 + static u64 tc512b_p[] = { /* p = 2^511 + 111 */ 192 + 0x000000000000006Full, 0x0000000000000000ull, 193 + 0x0000000000000000ull, 0x0000000000000000ull, 194 + 0x0000000000000000ull, 0x0000000000000000ull, 195 + 0x0000000000000000ull, 0x8000000000000000ull, }; 196 + static u64 tc512b_n[] = { 197 + 0xC6346C54374F25BDull, 0x8B996712101BEA0Eull, 198 + 0xACFDB77BD9D40CFAull, 0x49A1EC142565A545ull, 199 + 0x0000000000000001ull, 0x0000000000000000ull, 200 + 0x0000000000000000ull, 0x8000000000000000ull, }; 201 + static u64 tc512b_a[] = { /* a = p - 3 */ 202 + 0x000000000000006Cull, 0x0000000000000000ull, 203 + 0x0000000000000000ull, 0x0000000000000000ull, 204 + 0x0000000000000000ull, 0x0000000000000000ull, 205 + 0x0000000000000000ull, 0x8000000000000000ull, }; 206 + static u64 tc512b_b[] = { 207 + 0xFB8CCBC7C5140116ull, 0x50F78BEE1FA3106Eull, 208 + 0x7F8B276FAD1AB69Cull, 0x3E965D2DB1416D21ull, 209 + 0xBF85DC806C4B289Full, 0xB97C7D614AF138BCull, 210 + 0x7E3E06CF6F5E2517ull, 0x687D1B459DC84145ull, }; 211 + 212 + static struct ecc_curve gost_tc512b = { 213 + .name = "tc512b", 214 + .g = { 215 + .x = tc512b_g_x, 216 + .y = tc512b_g_y, 217 + .ndigits = 512 / 64, 218 + }, 219 + .p = tc512b_p, 220 + .n = tc512b_n, 221 + .a = tc512b_a, 222 + .b = tc512b_b 223 + }; 224 + 225 + #endif
+4
crypto/ecrdsa_params.asn1
··· 1 + EcrdsaParams ::= SEQUENCE { 2 + curve OBJECT IDENTIFIER ({ ecrdsa_param_curve }), 3 + digest OBJECT IDENTIFIER OPTIONAL ({ ecrdsa_param_digest }) 4 + }
+1
crypto/ecrdsa_pub_key.asn1
··· 1 + EcrdsaPubKey ::= OCTET STRING ({ ecrdsa_parse_pub_key })
+18
include/linux/oid_registry.h
··· 93 93 OID_authorityKeyIdentifier, /* 2.5.29.35 */ 94 94 OID_extKeyUsage, /* 2.5.29.37 */ 95 95 96 + /* EC-RDSA */ 97 + OID_gostCPSignA, /* 1.2.643.2.2.35.1 */ 98 + OID_gostCPSignB, /* 1.2.643.2.2.35.2 */ 99 + OID_gostCPSignC, /* 1.2.643.2.2.35.3 */ 100 + OID_gost2012PKey256, /* 1.2.643.7.1.1.1.1 */ 101 + OID_gost2012PKey512, /* 1.2.643.7.1.1.1.2 */ 102 + OID_gost2012Digest256, /* 1.2.643.7.1.1.2.2 */ 103 + OID_gost2012Digest512, /* 1.2.643.7.1.1.2.3 */ 104 + OID_gost2012Signature256, /* 1.2.643.7.1.1.3.2 */ 105 + OID_gost2012Signature512, /* 1.2.643.7.1.1.3.3 */ 106 + OID_gostTC26Sign256A, /* 1.2.643.7.1.2.1.1.1 */ 107 + OID_gostTC26Sign256B, /* 1.2.643.7.1.2.1.1.2 */ 108 + OID_gostTC26Sign256C, /* 1.2.643.7.1.2.1.1.3 */ 109 + OID_gostTC26Sign256D, /* 1.2.643.7.1.2.1.1.4 */ 110 + OID_gostTC26Sign512A, /* 1.2.643.7.1.2.1.2.1 */ 111 + OID_gostTC26Sign512B, /* 1.2.643.7.1.2.1.2.2 */ 112 + OID_gostTC26Sign512C, /* 1.2.643.7.1.2.1.2.3 */ 113 + 96 114 OID__NR 97 115 }; 98 116