***** BEGIN LICENSE BLOCK ***** Version: MPL 1.1/GPL 2.0/LGPL 2.1 The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is the elliptic curve math library. The Initial Developer of the Original Code is Sun Microsystems, Inc. Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 Sun Microsystems, Inc. All Rights Reserved. Contributor(s): Stephen Fung and Nils Gura , Sun Microsystems Laboratories Alternatively, the contents of this file may be used under the terms of either the GNU General Public License Version 2 or later (the "GPL"), or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which case the provisions of the GPL or the LGPL are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of either the GPL or the LGPL, and not to allow others to use your version of this file under the terms of the MPL, indicate your decision by deleting the provisions above and replace them with the notice and other provisions required by the GPL or the LGPL. If you do not delete the provisions above, a recipient may use your version of this file under the terms of any one of the MPL, the GPL or the LGPL. ***** END LICENSE BLOCK ***** The ECL exposes routines for constructing and converting curve parameters for internal use. The floating point code of the ECL provides algorithms for performing elliptic-curve point multiplications in floating point. The point multiplication algorithms perform calculations almost exclusively in floating point for efficiency, but have the same (integer) interface as the ECL for compatibility and to be easily wired-in to the ECL. Please see README file (not this README.FP file) for information on wiring-in. This has been implemented for 3 curves as specified in [1]: secp160r1 secp192r1 secp224r1 RATIONALE ========= Calculations are done in the floating-point unit (FPU) since it gives better performance on the UltraSPARC III chips. This is because the FPU allows for faster multiplication than the integer unit. The integer unit has a longer multiplication instruction latency, and does not allow full pipelining, as described in [2]. Since performance is an important selling feature of Elliptic Curve Cryptography (ECC), this implementation was created. DATA REPRESENTATION =================== Data is primarily represented in an array of double-precision floating point numbers. Generally, each array element has 24 bits of precision (i.e. be x * 2^y, where x is an integer of at most 24 bits, y some positive integer), although the actual implementation details are more complicated. e.g. a way to store an 80 bit number might be: double p[4] = { 632613 * 2^0, 329841 * 2^24, 9961 * 2^48, 51 * 2^64 }; See section ARITHMETIC OPERATIONS for more details. This implementation assumes that the floating-point unit rounding mode is round-to-even as specified in IEEE 754 (as opposed to chopping, rounding up, or rounding down). When subtracting integers represented as arrays of floating point numbers, some coefficients (array elements) may become negative. This effectively gives an extra bit of precision that is important for correctness in some cases. The described number presentation limits the size of integers to 1023 bits. This is due to an upper bound of 1024 for the exponent of a double precision floating point number as specified in IEEE-754. However, this is acceptable for ECC key sizes of the foreseeable future. DATA STRUCTURES =============== For more information on coordinate representations, see [3]. ecfp_aff_pt ----------- Affine EC Point Representation. This is the basic representation (x, y) of an elliptic curve point. ecfp_jac_pt ----------- Jacobian EC Point. This stores a point as (X, Y, Z), where the affine point corresponds to (X/Z^2, Y/Z^3). This allows for fewer inversions in calculations. ecfp_chud_pt ------------ Chudnovsky Jacobian Point. This representation stores a point as (X, Y, Z, Z^2, Z^3), the same as a Jacobian representation but also storing Z^2 and Z^3 for faster point additions. ecfp_jm_pt ---------- Modified Jacobian Point. This representation stores a point as (X, Y, Z, a*Z^4), the same as Jacobian representation but also storing a*Z^4 for faster point doublings. Here "a" represents the linear coefficient of x defining the curve. EC_group_fp ----------- Stores information on the elliptic curve group for floating point calculations. Contains curve specific information, as well as function pointers to routines, allowing different optimizations to be easily wired in. This should be made accessible from an ECGroup for the floating point implementations of point multiplication. POINT MULTIPLICATION ALGORITHMS =============================== Elliptic Curve Point multiplication can be done at a higher level orthogonal to the implementation of point additions and point doublings. There are a variety of algorithms that can be used. The following algorithms have been implemented: 4-bit Window (Jacobian Coordinates) Double & Add (Jacobian & Affine Coordinates) 5-bit Non-Adjacent Form (Modified Jacobian & Chudnovsky Jacobian) Currently, the fastest algorithm for multiplying a generic point is the 5-bit Non-Adjacent Form. See comments in ecp_fp.c for more details and references. SOURCE / HEADER FILES ===================== ecp_fp.c -------- Main source file for floating point calculations. Contains routines to convert from floating-point to integer (mp_int format), point multiplication algorithms, and several other routines. ecp_fp.h -------- Main header file. Contains most constants used and function prototypes. ecp_fp[160, 192, 224].c ----------------------- Source files for specific curves. Contains curve specific code such as specialized reduction based on the field defining prime. Contains code wiring-in different algorithms and optimizations. ecp_fpinc.c ----------- Source file that is included by ecp_fp[160, 192, 224].c. This generates functions with different preprocessor-defined names and loop iterations, allowing for static linking and strong compiler optimizations without code duplication. TESTING ======= The test suite can be found in ecl/tests/ecp_fpt. This tests and gets timings of the different algorithms for the curves implemented. ARITHMETIC OPERATIONS --------------------- The primary operations in ECC over the prime fields are modular arithmetic: i.e. n * m (mod p) and n + m (mod p). In this implementation, multiplication, addition, and reduction are implemented as separate functions. This enables computation of formulae with fewer reductions, e.g. (a * b) + (c * d) (mod p) rather than: ((a * b) (mod p)) + ((c * d) (mod p)) (mod p) This takes advantage of the fact that the double precision mantissa in floating point can hold numbers up to 2^53, i.e. it has some leeway to store larger intermediate numbers. See further detail in the section on FLOATING POINT PRECISION. Multiplication -------------- Multiplication is implemented in a standard polynomial multiplication fashion. The terms in opposite factors are pairwise multiplied and added together appropriately. Note that the result requires twice as many doubles for storage, as the bit size of the product is twice that of the multiplicands. e.g. suppose we have double n[3], m[3], r[6], and want to calculate r = n * m r[0] = n[0] * m[0] r[1] = n[0] * m[1] + n[1] * m[0] r[2] = n[0] * m[2] + n[1] * m[1] + n[2] * m[0] r[3] = n[1] * m[2] + n[2] * m[1] r[4] = n[2] * m[2] r[5] = 0 (This is used later to hold spillover from r[4], see tidying in the reduction section.) Addition -------- Addition is done term by term. The only caveat is to be careful with the number of terms that need to be added. When adding results of multiplication (before reduction), twice as many terms need to be added together. This is done in the addLong function. e.g. for double n[4], m[4], r[4]: r = n + m r[0] = n[0] + m[0] r[1] = n[1] + m[1] r[2] = n[2] + m[2] r[3] = n[3] + m[3] Modular Reduction ----------------- For the curves implemented, reduction is possible by fast reduction for Generalized Mersenne Primes, as described in [4]. For the floating point implementation, a significant step of the reduction process is tidying: that is, the propagation of carry bits from low-order to high-order coefficients to reduce the precision of each coefficient to 24 bits. This is done by adding and then subtracting ecfp_alpha, a large floating point number that induces precision roundoff. See [5] for more details on tidying using floating point arithmetic. e.g. suppose we have r = 961838 * 2^24 + 519308 then if we set alpha = 3 * 2^51 * 2^24, FP(FP(r + alpha) - alpha) = 961838 * 2^24, because the precision for the intermediate results is limited. Our values of alpha are chosen to truncate to a desired number of bits. The reduction is then performed as in [4], adding multiples of prime p. e.g. suppose we are working over a polynomial of 10^2. Take the number 2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95, stored in 5 elements for coefficients of 10^0, 10^2, ..., 10^8. We wish to reduce modulo p = 10^6 - 2 * 10^4 + 1 We can subtract off from the higher terms (2 * 10^8 + 11 * 10^6 + 53 * 10^4 + 23 * 10^2 + 95) - (2 * 10^2) * (10^6 - 2 * 10^4 + 1) = 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95 = 15 * 10^6 + 53 * 10^4 + 21 * 10^2 + 95 - (15) * (10^6 - 2 * 10^4 + 1) = 83 * 10^4 + 21 * 10^2 + 80 Integrated Example ------------------ This example shows how multiplication, addition, tidying, and reduction work together in our modular arithmetic. This is simplified from the actual implementation, but should convey the main concepts. Working over polynomials of 10^2 and with p as in the prior example, Let a = 16 * 10^4 + 53 * 10^2 + 33 let b = 81 * 10^4 + 31 * 10^2 + 49 let c = 22 * 10^4 + 0 * 10^2 + 95 And suppose we want to compute a * b + c mod p. We first do a multiplication: then a * b = 0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5100 * 10^4 + 3620 * 10^2 + 1617 Then we add in c before doing reduction, allowing us to get a * b + c = 0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712 We then perform a tidying on the upper half of the terms: 0 * 10^10 + 1296 * 10^8 + 4789 * 10^6 0 * 10^10 + (1296 + 47) * 10^8 + 89 * 10^6 0 * 10^10 + 1343 * 10^8 + 89 * 10^6 13 * 10^10 + 43 * 10^8 + 89 * 10^6 which then gives us 13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712 we then reduce modulo p similar to the reduction example above: 13 * 10^10 + 43 * 10^8 + 89 * 10^6 + 5122 * 10^4 + 3620 * 10^2 + 1712 - (13 * 10^4 * p) 69 * 10^8 + 89 * 10^6 + 5109 * 10^4 + 3620 * 10^2 + 1712 - (69 * 10^2 * p) 227 * 10^6 + 5109 * 10^4 + 3551 * 10^2 + 1712 - (227 * p) 5563 * 10^4 + 3551 * 10^2 + 1485 finally, we do tidying to get the precision of each term down to 2 digits 5563 * 10^4 + 3565 * 10^2 + 85 5598 * 10^4 + 65 * 10^2 + 85 55 * 10^6 + 98 * 10^4 + 65 * 10^2 + 85 and perform another reduction step - (55 * p) 208 * 10^4 + 65 * 10^2 + 30 There may be a small number of further reductions that could be done at this point, but this is typically done only at the end when converting from floating point to an integer unit representation. FLOATING POINT PRECISION ======================== This section discusses the precision of floating point numbers, which one writing new formulae or a larger bit size should be aware of. The danger is that an intermediate result may be required to store a mantissa larger than 53 bits, which would cause error by rounding off. Note that the tidying with IEEE rounding mode set to round-to-even allows negative numbers, which actually reduces the size of the double mantissa to 23 bits - since it rounds the mantissa to the nearest number modulo 2^24, i.e. roughly between -2^23 and 2^23. A multiplication increases the bit size to 2^46 * n, where n is the number of doubles to store a number. For the 224 bit curve, n = 10. This gives doubles of size 5 * 2^47. Adding two of these doubles gives a result of size 5 * 2^48, which is less than 2^53, so this is safe. Similar analysis can be done for other formulae to ensure numbers remain below 2^53. Extended-Precision Floating Point --------------------------------- Some platforms, notably x86 Linux, may use an extended-precision floating point representation that has a 64-bit mantissa. [6] Although this implementation is optimized for the IEEE standard 53-bit mantissa, it should work with the 64-bit mantissa. A check is done at run-time in the function ec_set_fp_precision that detects if the precision is greater than 53 bits, and runs code for the 64-bit mantissa accordingly. REFERENCES ========== [1] Certicom Corp., "SEC 2: Recommended Elliptic Curve Domain Parameters", Sept. 20, 2000. www.secg.org [2] Sun Microsystems Inc. UltraSPARC III Cu User's Manual, Version 1.0, May 2002, Table 4.4 [3] H. Cohen, A. Miyaji, and T. Ono, "Efficient Elliptic Curve Exponentiation Using Mixed Coordinates". [4] Henk C.A. van Tilborg, Generalized Mersenne Prime. http://www.win.tue.nl/~henkvt/GenMersenne.pdf [5] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2. [6] Daniel J. Bernstein, Floating-Point Arithmetic and Message Authentication, Journal of Cryptology, March 2000, Section 2 Notes.