Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P-521 implementation with Fiat-crypto field arithmetic #376

Merged
merged 5 commits into from
Feb 7, 2022

Conversation

dkostic
Copy link
Contributor

@dkostic dkostic commented Jan 26, 2022

Issues:

CryptoAlg-923

Description of changes:

This PR adds the implementation of P-521 curve that uses Fiat-crypto field arithmetic. The implementation is done in the same way as for P-384. The main changes are:

  • Imported Fiat-crypto field arithmetic implementation in third_party directory (files p521_32.h and p521_64.h)
  • Added full P-521 implementation in file p521.c. The file contains implementation of:
    • Point arithmetic (addition and doubling)
    • Inversion of a scalar
    • Curve scalar multiplication functions (multiplication of an arbitrary point by a given scalar, multiplication of the base point by a given scalar, sum of the product of a given scalar with a given arbitrary point and a given scalar and the base point).
  • Updated make_tables.go script to support generating the pre-computed table for P-521 (the generated file is p521_tables.h).
  • Updated certain tests to reflect the fact that P-521 is not using Montgomery arithmetic anymore.
  • Slight refactoring of P-384 and some other files (mostly adjusting line widths to 80 characters).

Finally, the performance improvements of this change are:

  • ECDH faster by a factor of 3.7 and 3.9 on GV2 and x86, respectively.
  • ECDSA sign faster by a factor of 5.7 and 5.9 on GV2 and x86, respectively.
  • ECDSA verify by a factor of 2.3 and 2.4 on GV2 and x86, respectively.
    The raw numbers measure by ./tool/bssl speed -filter "P-521"

(x86) EC2 instance with Intel(R) Xeon(R) Platinum 8124M CPU:
Before:
Did 451 ECDH P-521 operations in 1099027us (410.4 ops/sec)
Did 792 ECDSA P-521 signing operations in 1083113us (731.2 ops/sec)
Did 781 ECDSA P-521 verify operations in 1077091us (725.1 ops/sec)

After:
Did 1716 ECDH P-521 operations in 1065345us (1610.7 ops/sec)
Did 4400 ECDSA P-521 signing operations in 1023071us (4300.8 ops/sec)
Did 1903 ECDSA P-521 verify operations in 1076533us (1767.7 ops/sec)

(Arm) EC2 instance with Graviton 2:
Before:
Did 154 ECDH P-521 operations in 1071138us (143.8 ops/sec)
Did 275 ECDSA P-521 signing operations in 1078510us (255.0 ops/sec)
Did 264 ECDSA P-521 verify operations in 1073877us (245.8 ops/sec)

After:
Did 572 ECDH P-521 operations in 1075348us (531.9 ops/sec)
Did 1540 ECDSA P-521 signing operations in 1054963us (1459.8 ops/sec)
Did 627 ECDSA P-521 verify operations in 1090150us (575.2 ops/sec)

Call-outs:

Point out areas that need special attention or support during the review process. Discuss architecture or design changes.

Testing:

How is this change tested (unit tests, fuzz tests, etc.)? Are there any testing steps to be verified by the reviewer?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

DominicDams
DominicDams previously approved these changes Feb 1, 2022
Copy link
Contributor

@nebeid nebeid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in the middle of make_tables.go. Will continue reviewing tomorrow.

crypto/ecdh_extra/ecdh_test.cc Outdated Show resolved Hide resolved
crypto/fipsmodule/ec/ec_test.cc Outdated Show resolved Hide resolved
Comment on lines +40 to +44

if err := writeP521Table("p521_table.h"); err != nil {
fmt.Fprintf(os.Stderr, "Error writing p521_table.h: %s\n", err)
os.Exit(1)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is different indentations in these lines than the ones above.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the indentation is fixed in the whole file now.

crypto/fipsmodule/ec/make_tables.go Outdated Show resolved Hide resolved
crypto/fipsmodule/ec/make_tables.go Outdated Show resolved Hide resolved
ret := make([]uint64, words)
mask := big.NewInt((1 << 58) - 1)
tmp := new(big.Int).Set(n)
for i := 0; i < words; i++ {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the stopping condition be tmp == 0 as an additional check on the correct calculation of words? Alternatively, we can check after the loop that tmp =0.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is no reason for additional checks here, there are no checks in the existing functions and the script is used only for generating the table. Any mistake here and the table would be wrong, which means the unit tests for the curve would fail.

mask := big.NewInt((1 << bits) - 1)
ret[i] = new(big.Int).And(tmp, mask).Uint64()
tmp.Rsh(tmp, bits)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment, not sure if there is a value in checking tmp=0 here.
Also the indentation seems off in the function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see my comment above. Indentation fixed.

Copy link
Contributor

@nebeid nebeid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still continuing

@@ -414,9 +514,40 @@ func writeU32Mont(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) err
})
}

type writeBigIntFunc func(w io.Writer, curve elliptic.Curve, n *big.Int, indent int) error
func writeU64(w io.Writer, curve elliptic.Curve, n *big.Int, indent int, bitSizes []uint) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think bitSizes is not used in this function nor the following one, nor in writeU32. Is there a reason to have it in the arguments?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't get me started on Go's limitations :) Because of the way all these functions are defined and used I couldn't find a more elegant way than adding the parameter to all the functions even if it's not used everywhere

crypto/fipsmodule/ec/make_tables.go Outdated Show resolved Hide resolved
crypto/fipsmodule/ec/make_tables.go Outdated Show resolved Hide resolved
// For each digit |d| in the current group read the corresponding point
// from the table and add it to |res|. If |d| is negative, negate
// the point before adding it to |res|.
int16_t d = rnaf[j];
// is_neg = (d < 0) ? 1 : 0
int16_t is_neg = (d >> 7) & 1;
int16_t is_neg = (d >> 15) & 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Thank you. There is another occurrence at line 772.
Just curious, was it causing errors in P-521?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it could cause errors only with window size >7 I think. Fixed 772.

fiat_secp521r1_selectznz(out, !!t, z, nz);
}

static void p521_from_generic(p521_felem out, const EC_FELEM *in) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I keep coming back to remember this: It may be worth it to add as a comment here (and in p384.c and p256.c) and before _to_generic that the input and output are in little-endian representation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added

out[P521_MUL_NWINDOWS - 1] = window;
}

// fiat_p521_select_point selects the |idx|-th projective point from the given
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function and the following one kept the fiat_ prefix which was removed in p384 ones.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks! changed

crypto/fipsmodule/ec/p384.c Outdated Show resolved Hide resolved
Comment on lines 657 to 659
p521_to_generic(&r->X, res[0]);
p521_to_generic(&r->Y, res[1]);
p521_to_generic(&r->Z, res[2]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these lines needed? I don't think r is used afterwards until they're repeated again at l. 675.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, leftover from debugging.

Comment on lines 142 to 143
p521_felem acc, t128, t16, t2, t256, t32, t4;
p521_felem t512, t516, t518, t519, t64, t8;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we can rearrange the variable names in their order of appearance, which I think is their ascending order, unless you'd like to keep it true to where it's copied from.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@dkostic dkostic merged commit afdddac into aws:main Feb 7, 2022
@dkostic dkostic deleted the p521-fiat-crypto branch February 7, 2022 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants