Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: crypto/p224.cc

Issue 10822019: crypto: special case ∞+a, a+∞ and a+a in p224. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: ... Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | crypto/p224_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // This is an implementation of the P224 elliptic curve group. It's written to 5 // This is an implementation of the P224 elliptic curve group. It's written to
6 // be short and simple rather than fast, although it's still constant-time. 6 // be short and simple rather than fast, although it's still constant-time.
7 // 7 //
8 // See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. 8 // See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background.
9 9
10 #include "crypto/p224.h" 10 #include "crypto/p224.h"
(...skipping 14 matching lines...) Expand all
25 // Field elements are represented by a FieldElement, which is a typedef to an 25 // Field elements are represented by a FieldElement, which is a typedef to an
26 // array of 8 uint32's. The value of a FieldElement, a, is: 26 // array of 8 uint32's. The value of a FieldElement, a, is:
27 // a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7] 27 // a[0] + 2**28·a[1] + 2**56·a[1] + ... + 2**196·a[7]
28 // 28 //
29 // Using 28-bit limbs means that there's only 4 bits of headroom, which is less 29 // Using 28-bit limbs means that there's only 4 bits of headroom, which is less
30 // than we would really like. But it has the useful feature that we hit 2**224 30 // than we would really like. But it has the useful feature that we hit 2**224
31 // exactly, making the reflections during a reduce much nicer. 31 // exactly, making the reflections during a reduce much nicer.
32 32
33 using crypto::p224::FieldElement; 33 using crypto::p224::FieldElement;
34 34
35 // kP is the P224 prime.
36 const FieldElement kP = {
37 1, 0, 0, 268431360,
38 268435455, 268435455, 268435455, 268435455,
39 };
40
41 void Contract(FieldElement* inout);
42
43 // IsZero returns 0xffffffff if a == 0 mod p and 0 otherwise.
44 uint32 IsZero(const FieldElement& a) {
45 FieldElement minimal;
46 memcpy(&minimal, &a, sizeof(minimal));
47 Contract(&minimal);
48
49 uint32 is_zero = 0, is_p = 0;
50 for (unsigned i = 0; i < 8; i++) {
51 is_zero |= minimal[i];
52 is_p |= minimal[i] - kP[i];
53 }
54
55 // If either is_zero or is_p is 0, then we should return 1.
56 is_zero |= is_zero >> 16;
57 is_zero |= is_zero >> 8;
58 is_zero |= is_zero >> 4;
59 is_zero |= is_zero >> 2;
60 is_zero |= is_zero >> 1;
61
62 is_p |= is_p >> 16;
63 is_p |= is_p >> 8;
64 is_p |= is_p >> 4;
65 is_p |= is_p >> 2;
66 is_p |= is_p >> 1;
67
68 // For is_zero and is_p, the LSB is 0 iff all the bits are zero.
69 is_zero &= is_p & 1;
70 is_zero = (~is_zero) << 31;
71 is_zero = static_cast<int32>(is_zero) >> 31;
72 return is_zero;
73 }
74
35 // Add computes *out = a+b 75 // Add computes *out = a+b
36 // 76 //
37 // a[i] + b[i] < 2**32 77 // a[i] + b[i] < 2**32
38 void Add(FieldElement* out, const FieldElement& a, const FieldElement& b) { 78 void Add(FieldElement* out, const FieldElement& a, const FieldElement& b) {
39 for (int i = 0; i < 8; i++) { 79 for (int i = 0; i < 8; i++) {
40 (*out)[i] = a[i] + b[i]; 80 (*out)[i] = a[i] + b[i];
41 } 81 }
42 } 82 }
43 83
44 static const uint32 kTwo31p3 = (1u<<31) + (1u<<3); 84 static const uint32 kTwo31p3 = (1u<<31) + (1u<<3);
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 for (int i = 0; i < 3; i++) { 346 for (int i = 0; i < 3; i++) {
307 uint32 mask = static_cast<uint32>(static_cast<int32>(out[i]) >> 31); 347 uint32 mask = static_cast<uint32>(static_cast<int32>(out[i]) >> 31);
308 out[i] += (1 << 28) & mask; 348 out[i] += (1 << 28) & mask;
309 out[i+1] -= 1 & mask; 349 out[i+1] -= 1 & mask;
310 } 350 }
311 351
312 // The value is < 2**224, but maybe greater than p. In order to reduce to a 352 // The value is < 2**224, but maybe greater than p. In order to reduce to a
313 // unique, minimal value we see if the value is >= p and, if so, subtract p. 353 // unique, minimal value we see if the value is >= p and, if so, subtract p.
314 354
315 // First we build a mask from the top four limbs, which must all be 355 // First we build a mask from the top four limbs, which must all be
316 // equal to bottom28Bits if the whole value is >= p. If top4AllOnes 356 // equal to bottom28Bits if the whole value is >= p. If top_4_all_ones
317 // ends up with any zero bits in the bottom 28 bits, then this wasn't 357 // ends up with any zero bits in the bottom 28 bits, then this wasn't
318 // true. 358 // true.
319 uint32 top4AllOnes = 0xffffffffu; 359 uint32 top_4_all_ones = 0xffffffffu;
320 for (int i = 4; i < 8; i++) { 360 for (int i = 4; i < 8; i++) {
321 top4AllOnes &= (out[i] & kBottom28Bits) - 1; 361 top_4_all_ones &= out[i];
322 } 362 }
323 top4AllOnes |= 0xf0000000; 363 top_4_all_ones |= 0xf0000000;
324 // Now we replicate any zero bits to all the bits in top4AllOnes. 364 // Now we replicate any zero bits to all the bits in top_4_all_ones.
325 top4AllOnes &= top4AllOnes >> 16; 365 top_4_all_ones &= top_4_all_ones >> 16;
326 top4AllOnes &= top4AllOnes >> 8; 366 top_4_all_ones &= top_4_all_ones >> 8;
327 top4AllOnes &= top4AllOnes >> 4; 367 top_4_all_ones &= top_4_all_ones >> 4;
328 top4AllOnes &= top4AllOnes >> 2; 368 top_4_all_ones &= top_4_all_ones >> 2;
329 top4AllOnes &= top4AllOnes >> 1; 369 top_4_all_ones &= top_4_all_ones >> 1;
330 top4AllOnes = 370 top_4_all_ones =
331 static_cast<uint32>(static_cast<int32>(top4AllOnes << 31) >> 31); 371 static_cast<uint32>(static_cast<int32>(top_4_all_ones << 31) >> 31);
332 372
333 // Now we test whether the bottom three limbs are non-zero. 373 // Now we test whether the bottom three limbs are non-zero.
334 uint32 bottom3NonZero = out[0] | out[1] | out[2]; 374 uint32 bottom_3_non_zero = out[0] | out[1] | out[2];
335 bottom3NonZero |= bottom3NonZero >> 16; 375 bottom_3_non_zero |= bottom_3_non_zero >> 16;
336 bottom3NonZero |= bottom3NonZero >> 8; 376 bottom_3_non_zero |= bottom_3_non_zero >> 8;
337 bottom3NonZero |= bottom3NonZero >> 4; 377 bottom_3_non_zero |= bottom_3_non_zero >> 4;
338 bottom3NonZero |= bottom3NonZero >> 2; 378 bottom_3_non_zero |= bottom_3_non_zero >> 2;
339 bottom3NonZero |= bottom3NonZero >> 1; 379 bottom_3_non_zero |= bottom_3_non_zero >> 1;
340 bottom3NonZero = 380 bottom_3_non_zero =
341 static_cast<uint32>(static_cast<int32>(bottom3NonZero << 31) >> 31); 381 static_cast<uint32>(static_cast<int32>(bottom_3_non_zero) >> 31);
342 382
343 // Everything depends on the value of out[3]. 383 // Everything depends on the value of out[3].
344 // If it's > 0xffff000 and top4AllOnes != 0 then the whole value is >= p 384 // If it's > 0xffff000 and top_4_all_ones != 0 then the whole value is >= p
345 // If it's = 0xffff000 and top4AllOnes != 0 and bottom3NonZero != 0, 385 // If it's = 0xffff000 and top_4_all_ones != 0 and bottom_3_non_zero != 0,
346 // then the whole value is >= p 386 // then the whole value is >= p
347 // If it's < 0xffff000, then the whole value is < p 387 // If it's < 0xffff000, then the whole value is < p
348 uint32 n = out[3] - 0xffff000; 388 uint32 n = out[3] - 0xffff000;
349 uint32 out3Equal = n; 389 uint32 out_3_equal = n;
350 out3Equal |= out3Equal >> 16; 390 out_3_equal |= out_3_equal >> 16;
351 out3Equal |= out3Equal >> 8; 391 out_3_equal |= out_3_equal >> 8;
352 out3Equal |= out3Equal >> 4; 392 out_3_equal |= out_3_equal >> 4;
353 out3Equal |= out3Equal >> 2; 393 out_3_equal |= out_3_equal >> 2;
354 out3Equal |= out3Equal >> 1; 394 out_3_equal |= out_3_equal >> 1;
355 out3Equal = 395 out_3_equal =
356 ~static_cast<uint32>(static_cast<int32>(out3Equal << 31) >> 31); 396 ~static_cast<uint32>(static_cast<int32>(out_3_equal << 31) >> 31);
357 397
358 // If out[3] > 0xffff000 then n's MSB will be zero. 398 // If out[3] > 0xffff000 then n's MSB will be zero.
359 uint32 out3GT = ~static_cast<uint32>(static_cast<int32>(n << 31) >> 31); 399 uint32 out_3_gt = ~static_cast<uint32>(static_cast<int32>(n << 31) >> 31);
360 400
361 uint32 mask = top4AllOnes & ((out3Equal & bottom3NonZero) | out3GT); 401 uint32 mask = top_4_all_ones & ((out_3_equal & bottom_3_non_zero) | out_3_gt);
362 out[0] -= 1 & mask; 402 out[0] -= 1 & mask;
363 out[3] -= 0xffff000 & mask; 403 out[3] -= 0xffff000 & mask;
364 out[4] -= 0xfffffff & mask; 404 out[4] -= 0xfffffff & mask;
365 out[5] -= 0xfffffff & mask; 405 out[5] -= 0xfffffff & mask;
366 out[6] -= 0xfffffff & mask; 406 out[6] -= 0xfffffff & mask;
367 out[7] -= 0xfffffff & mask; 407 out[7] -= 0xfffffff & mask;
368 } 408 }
369 409
370 410
371 // Group element functions. 411 // Group element functions.
372 // 412 //
373 // These functions deal with group elements. The group is an elliptic curve 413 // These functions deal with group elements. The group is an elliptic curve
374 // group with a = -3 defined in FIPS 186-3, section D.2.2. 414 // group with a = -3 defined in FIPS 186-3, section D.2.2.
375 415
376 using crypto::p224::Point; 416 using crypto::p224::Point;
377 417
378 // kP is the P224 prime.
379 const FieldElement kP = {
380 1, 0, 0, 268431360,
381 268435455, 268435455, 268435455, 268435455,
382 };
383
384 // kB is parameter of the elliptic curve. 418 // kB is parameter of the elliptic curve.
385 const FieldElement kB = { 419 const FieldElement kB = {
386 55967668, 11768882, 265861671, 185302395, 420 55967668, 11768882, 265861671, 185302395,
387 39211076, 180311059, 84673715, 188764328, 421 39211076, 180311059, 84673715, 188764328,
388 }; 422 };
389 423
424 void CopyConditional(Point* out, const Point& a, uint32 mask);
425 void DoubleJacobian(Point* out, const Point& a);
426
390 // AddJacobian computes *out = a+b where a != b. 427 // AddJacobian computes *out = a+b where a != b.
391 void AddJacobian(Point *out, 428 void AddJacobian(Point *out,
392 const Point& a, 429 const Point& a,
393 const Point& b) { 430 const Point& b) {
394 // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-a dd-2007-bl 431 // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-a dd-2007-bl
395 FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v; 432 FieldElement z1z1, z2z2, u1, u2, s1, s2, h, i, j, r, v;
396 433
434 uint32 z1_is_zero = IsZero(a.z);
435 uint32 z2_is_zero = IsZero(b.z);
436
397 // Z1Z1 = Z1² 437 // Z1Z1 = Z1²
398 Square(&z1z1, a.z); 438 Square(&z1z1, a.z);
399 439
400 // Z2Z2 = Z2² 440 // Z2Z2 = Z2²
401 Square(&z2z2, b.z); 441 Square(&z2z2, b.z);
402 442
403 // U1 = X1*Z2Z2 443 // U1 = X1*Z2Z2
404 Mul(&u1, a.x, z2z2); 444 Mul(&u1, a.x, z2z2);
405 445
406 // U2 = X2*Z1Z1 446 // U2 = X2*Z1Z1
407 Mul(&u2, b.x, z1z1); 447 Mul(&u2, b.x, z1z1);
408 448
409 // S1 = Y1*Z2*Z2Z2 449 // S1 = Y1*Z2*Z2Z2
410 Mul(&s1, b.z, z2z2); 450 Mul(&s1, b.z, z2z2);
411 Mul(&s1, a.y, s1); 451 Mul(&s1, a.y, s1);
412 452
413 // S2 = Y2*Z1*Z1Z1 453 // S2 = Y2*Z1*Z1Z1
414 Mul(&s2, a.z, z1z1); 454 Mul(&s2, a.z, z1z1);
415 Mul(&s2, b.y, s2); 455 Mul(&s2, b.y, s2);
416 456
417 // H = U2-U1 457 // H = U2-U1
418 Subtract(&h, u2, u1); 458 Subtract(&h, u2, u1);
419 Reduce(&h); 459 Reduce(&h);
460 uint32 x_equal = IsZero(h);
420 461
421 // I = (2*H)² 462 // I = (2*H)²
422 for (int j = 0; j < 8; j++) { 463 for (int j = 0; j < 8; j++) {
423 i[j] = h[j] << 1; 464 i[j] = h[j] << 1;
424 } 465 }
425 Reduce(&i); 466 Reduce(&i);
426 Square(&i, i); 467 Square(&i, i);
427 468
428 // J = H*I 469 // J = H*I
429 Mul(&j, h, i); 470 Mul(&j, h, i);
430 // r = 2*(S2-S1) 471 // r = 2*(S2-S1)
431 Subtract(&r, s2, s1); 472 Subtract(&r, s2, s1);
432 Reduce(&r); 473 Reduce(&r);
474 uint32 y_equal = IsZero(r);
475
476 if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
477 // The two input points are the same therefore we must use the dedicated
478 // doubling function as the slope of the line is undefined.
479 DoubleJacobian(out, a);
480 return;
481 }
482
433 for (int i = 0; i < 8; i++) { 483 for (int i = 0; i < 8; i++) {
434 r[i] <<= 1; 484 r[i] <<= 1;
435 } 485 }
436 Reduce(&r); 486 Reduce(&r);
437 487
438 // V = U1*I 488 // V = U1*I
439 Mul(&v, u1, i); 489 Mul(&v, u1, i);
440 490
441 // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H 491 // Z3 = ((Z1+Z2)²-Z1Z1-Z2Z2)*H
442 Add(&z1z1, z1z1, z2z2); 492 Add(&z1z1, z1z1, z2z2);
(...skipping 17 matching lines...) Expand all
460 // Y3 = r*(V-X3)-2*S1*J 510 // Y3 = r*(V-X3)-2*S1*J
461 for (int i = 0; i < 8; i++) { 511 for (int i = 0; i < 8; i++) {
462 s1[i] <<= 1; 512 s1[i] <<= 1;
463 } 513 }
464 Mul(&s1, s1, j); 514 Mul(&s1, s1, j);
465 Subtract(&z1z1, v, out->x); 515 Subtract(&z1z1, v, out->x);
466 Reduce(&z1z1); 516 Reduce(&z1z1);
467 Mul(&z1z1, z1z1, r); 517 Mul(&z1z1, z1z1, r);
468 Subtract(&out->y, z1z1, s1); 518 Subtract(&out->y, z1z1, s1);
469 Reduce(&out->y); 519 Reduce(&out->y);
520
521 CopyConditional(out, a, z2_is_zero);
522 CopyConditional(out, b, z1_is_zero);
470 } 523 }
471 524
472 // DoubleJacobian computes *out = a+a. 525 // DoubleJacobian computes *out = a+a.
473 void DoubleJacobian(Point* out, const Point& a) { 526 void DoubleJacobian(Point* out, const Point& a) {
474 // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-d bl-2001-b 527 // See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-d bl-2001-b
475 FieldElement delta, gamma, beta, alpha, t; 528 FieldElement delta, gamma, beta, alpha, t;
476 529
477 Square(&delta, a.z); 530 Square(&delta, a.z);
478 Square(&gamma, a.y); 531 Square(&gamma, a.y);
479 Mul(&beta, a.x, gamma); 532 Mul(&beta, a.x, gamma);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
535 } 588 }
536 } 589 }
537 590
538 // ScalarMult calculates *out = a*scalar where scalar is a big-endian number of 591 // ScalarMult calculates *out = a*scalar where scalar is a big-endian number of
539 // length scalar_len and != 0. 592 // length scalar_len and != 0.
540 void ScalarMult(Point* out, const Point& a, 593 void ScalarMult(Point* out, const Point& a,
541 const uint8* scalar, size_t scalar_len) { 594 const uint8* scalar, size_t scalar_len) {
542 memset(out, 0, sizeof(*out)); 595 memset(out, 0, sizeof(*out));
543 Point tmp; 596 Point tmp;
544 597
545 uint32 first_bit = 0xffffffff;
546 for (size_t i = 0; i < scalar_len; i++) { 598 for (size_t i = 0; i < scalar_len; i++) {
547 for (unsigned int bit_num = 0; bit_num < 8; bit_num++) { 599 for (unsigned int bit_num = 0; bit_num < 8; bit_num++) {
548 DoubleJacobian(out, *out); 600 DoubleJacobian(out, *out);
549 uint32 bit = static_cast<uint32>(static_cast<int32>( 601 uint32 bit = static_cast<uint32>(static_cast<int32>(
550 (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31)); 602 (((scalar[i] >> (7 - bit_num)) & 1) << 31) >> 31));
551 AddJacobian(&tmp, a, *out); 603 AddJacobian(&tmp, a, *out);
552 CopyConditional(out, a, first_bit & bit); 604 CopyConditional(out, tmp, bit);
553 CopyConditional(out, tmp, ~first_bit & bit);
554 first_bit = first_bit & ~bit;
555 } 605 }
556 } 606 }
557 } 607 }
558 608
559 // Get224Bits reads 7 words from in and scatters their contents in 609 // Get224Bits reads 7 words from in and scatters their contents in
560 // little-endian form into 8 words at out, 28 bits per output word. 610 // little-endian form into 8 words at out, 28 bits per output word.
561 void Get224Bits(uint32* out, const uint32* in) { 611 void Get224Bits(uint32* out, const uint32* in) {
562 out[0] = NetToHost32(in[6]) & kBottom28Bits; 612 out[0] = NetToHost32(in[6]) & kBottom28Bits;
563 out[1] = ((NetToHost32(in[5]) << 4) | 613 out[1] = ((NetToHost32(in[5]) << 4) |
564 (NetToHost32(in[6]) >> 28)) & kBottom28Bits; 614 (NetToHost32(in[6]) >> 28)) & kBottom28Bits;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
621 Reduce(&rhs); 671 Reduce(&rhs);
622 672
623 ::Add(&rhs, rhs, kB); 673 ::Add(&rhs, rhs, kB);
624 Contract(&rhs); 674 Contract(&rhs);
625 return memcmp(&lhs, &rhs, sizeof(lhs)) == 0; 675 return memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
626 } 676 }
627 677
628 std::string Point::ToString() const { 678 std::string Point::ToString() const {
629 FieldElement zinv, zinv_sq, x, y; 679 FieldElement zinv, zinv_sq, x, y;
630 680
681 // If this is the point at infinity we return a string of all zeros.
682 if (IsZero(this->z)) {
683 static const char zeros[56] = {0};
684 return std::string(zeros, sizeof(zeros));
685 }
686
631 Invert(&zinv, this->z); 687 Invert(&zinv, this->z);
632 Square(&zinv_sq, zinv); 688 Square(&zinv_sq, zinv);
633 Mul(&x, this->x, zinv_sq); 689 Mul(&x, this->x, zinv_sq);
634 Mul(&zinv_sq, zinv_sq, zinv); 690 Mul(&zinv_sq, zinv_sq, zinv);
635 Mul(&y, this->y, zinv_sq); 691 Mul(&y, this->y, zinv_sq);
636 692
637 Contract(&x); 693 Contract(&x);
638 Contract(&y); 694 Contract(&y);
639 695
640 uint32 outwords[14]; 696 uint32 outwords[14];
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 Subtract(&out->y, kP, y); 734 Subtract(&out->y, kP, y);
679 Reduce(&out->y); 735 Reduce(&out->y);
680 736
681 memset(&out->z, 0, sizeof(out->z)); 737 memset(&out->z, 0, sizeof(out->z));
682 out->z[0] = 1; 738 out->z[0] = 1;
683 } 739 }
684 740
685 } // namespace p224 741 } // namespace p224
686 742
687 } // namespace crypto 743 } // namespace crypto
OLDNEW
« no previous file with comments | « no previous file | crypto/p224_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698