diff options
Diffstat (limited to 'nss/lib/freebl/ecl')
45 files changed, 5527 insertions, 11315 deletions
diff --git a/nss/lib/freebl/ecl/Makefile b/nss/lib/freebl/ecl/Makefile deleted file mode 100644 index 8237d06..0000000 --- a/nss/lib/freebl/ecl/Makefile +++ /dev/null @@ -1,195 +0,0 @@ -# -# Makefile for elliptic curve library - -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -## Define CC to be the C compiler you wish to use. The GNU cc -## compiler (gcc) should work, at the very least -#CC=cc -#CC=gcc - -## -## Define PERL to point to your local Perl interpreter. It -## should be Perl 5.x, although it's conceivable that Perl 4 -## might work ... I haven't tested it. -## -#PERL=/usr/bin/perl -#PERL=perl - -include ../mpi/target.mk - -## -## Define platform-dependent variables for use of floating-point code. -## -ifeq ($(TARGET),v9SOLARIS) -ECL_USE_FP=1 -else -ifeq ($(TARGET),v8plusSOLARIS) -ECL_USE_FP=1 -else -ifeq ($(TARGET),v8SOLARIS) -ECL_USE_FP=1 -else -ifeq ($(TARGET),x86LINUX) -ECL_USE_FP=1 -endif -endif -endif -endif - -## -## Add to definition of CFLAGS depending on use of floating-point code. -## -ifeq ($(ECL_USE_FP),1) -CFLAGS+= -DECL_USE_FP -endif - -## -## Define LIBS to include any libraries you need to link against. -## If NO_TABLE is define, LIBS should include '-lm' or whatever is -## necessary to bring in the math library. Otherwise, it can be -## left alone, unless your system has other peculiar requirements. -## -LIBS=-L../mpi -lmpi -lm#-lmalloc#-lefence - -## -## Define INCLUDES to include any include directories you need to -## compile with. -## -INCLUDES=-I../mpi -CFLAGS+= $(INCLUDES) $(XCFLAGS) - -## -## Define RANLIB to be the library header randomizer; you might not -## need this on some systems (just set it to 'echo' on these systems, -## such as IRIX) -## -RANLIB=echo - -## -## Define LIBOBJS to be the object files that will be created during -## the build process. -## -LIBOBJS = ecl.o ecl_curve.o ecl_mult.o ecl_gf.o \ - ec2_aff.o ec2_mont.o ec2_proj.o \ - ec2_163.o ec2_193.o ec2_233.o \ - ecp_aff.o ecp_jac.o ecp_mont.o \ - ec_naf.o ecp_jm.o \ - ecp_192.o ecp_224.o ecp_256.o ecp_384.o ecp_521.o \ - ecp_256_32.o -ifeq ($(ECL_USE_FP),1) -LIBOBJS+= ecp_fp160.o ecp_fp192.o ecp_fp224.o ecp_fp.o -endif - -## The headers contained in this library. -LIBHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h -APPHDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h ecl-curve.h -ifeq ($(ECL_GFP_ASSEMBLY_FP),1) -LIBHDRS += ecp_fp.h -APPHDRS += ecp_fp.h -endif - - -help: - @ echo "" - @ echo "The following targets can be built with this Makefile:" - @ echo "" - @ echo "libecl.a - elliptic curve library" - @ echo "tests - build command line tests" - @ echo "test - run command line tests" - @ echo "clean - clean up objects and such" - @ echo "" - -.SUFFIXES: .c .o .i - -.c.i: - $(CC) $(CFLAGS) -E $< > $@ - -#--------------------------------------- - -$(LIBOBJS): $(LIBHDRS) - -ecl.o: ecl.c $(LIBHDRS) -ecl_curve.o: ecl_curve.c $(LIBHDRS) -ecl_mult.o: ecl_mult.c $(LIBHDRS) -ecl_gf.o: ecl_gf.c $(LIBHDRS) -ec2_aff.o: ec2_aff.c $(LIBHDRS) -ec2_mont.o: ec2_mont.c $(LIBHDRS) -ec2_proj.o: ec2_proj.c $(LIBHDRS) -ec2_163.o: ec2_163.c $(LIBHDRS) -ec2_193.o: ec2_193.c $(LIBHDRS) -ec2_233.o: ec2_233.c $(LIBHDRS) -ecp_aff.o: ecp_aff.c $(LIBHDRS) -ecp_jac.o: ecp_jac.c $(LIBHDRS) -ecp_jm.o: ecp_jm.c $(LIBHDRS) -ecp_mont.o: ecp_mont.c $(LIBHDRS) -ecp_192.o: ecp_192.c $(LIBHDRS) -ecp_224.o: ecp_224.c $(LIBHDRS) -ecp_256.o: ecp_256.c $(LIBHDRS) -ecp_384.o: ecp_384.c $(LIBHDRS) -ecp_521.o: ecp_521.c $(LIBHDRS) -ecp_fp.o: ecp_fp.c $(LIBHDRS) -ifeq ($(ECL_USE_FP),1) -ecp_fp160.o: ecp_fp160.c ecp_fpinc.c $(LIBHDRS) -ecp_fp192.o: ecp_fp192.c ecp_fpinc.c $(LIBHDRS) -ecp_fp224.o: ecp_fp224.c ecp_fpinc.c $(LIBHDRS) -endif - -libecl.a: $(LIBOBJS) - ar -cvr libecl.a $(LIBOBJS) - $(RANLIB) libecl.a - -lib libs: libecl.a - -ecl.i: ecl.h - -#--------------------------------------- - -ECLTESTOBJS = ec2_test.o ecp_test.o ec_naft.o -ifeq ($(ECL_USE_FP),1) -ECLTESTOBJS+= ecp_fpt.o -endif -ECLTESTS = $(ECLTESTOBJS:.o=) - -$(ECLTESTOBJS): %.o: tests/%.c $(LIBHDRS) - $(CC) $(CFLAGS) -o $@ -c $< $(INCLUDES) - -$(ECLTESTS): %: %.o libecl.a - $(CC) $(CFLAGS) -o $@ $^ $(LIBS) - -ifeq ($(ECL_USE_FP),1) -tests: ec2_test ecp_test ec_naft ecp_fpt -else -tests: ec2_test ecp_test ec_naft -endif - -#--------------------------------------- - -ifeq ($(ECL_USE_FP),1) -test: tests - ./ecp_test - ./ec2_test - ./ec_naft - ./ecp_fpt -else -test: tests - ./ecp_test - ./ec_naft - ./ec2_test -endif - -#--------------------------------------- - -alltests: tests - -clean: - rm -f *.o *.a *.i - rm -f core - rm -f *~ .*~ - rm -f $(ECLTESTS) - -clobber: clean - -# END diff --git a/nss/lib/freebl/ecl/README b/nss/lib/freebl/ecl/README index f086cde..04a8b3b 100644 --- a/nss/lib/freebl/ecl/README +++ b/nss/lib/freebl/ecl/README @@ -24,9 +24,6 @@ and point multiplication operations. Used by higher level algorithms ecl-priv.h - Data structures and functions for internal use within the library. -ec2.h - Internal header file that contains all functions for point -arithmetic over binary polynomial fields. - ecp.h - Internal header file that contains all functions for point arithmetic over prime fields. @@ -268,30 +265,3 @@ function in ec2_k163.c: For an example of functions that use special field encodings, take a look at ecp_mont.c. - -TESTING -======= - -The ecl/tests directory contains a collection of standalone tests that -verify the correctness of the elliptic curve library. - -Both ecp_test and ec2_test take the following arguments: - - --print Print out results of each point arithmetic test. - --time Benchmark point operations and print results. - -The set of curves over which ecp_test and ec2_test run is coded into the -program, but can be changed by editing the source files. - -BUILDING -======== - -The ecl can be built as a standalone library, separate from NSS, -dependent only on the mpi library. To build the library: - - > cd ../mpi - > make libs - > cd ../ecl - > make libs - > make tests # to build test files - > make test # to run automated tests diff --git a/nss/lib/freebl/ecl/README.FP b/nss/lib/freebl/ecl/README.FP deleted file mode 100644 index 833f42e..0000000 --- a/nss/lib/freebl/ecl/README.FP +++ /dev/null @@ -1,284 +0,0 @@ -This Source Code Form is subject to the terms of the Mozilla Public -License, v. 2.0. If a copy of the MPL was not distributed with this -file, You can obtain one at http://mozilla.org/MPL/2.0/. - -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. diff --git a/nss/lib/freebl/ecl/curve25519_32.c b/nss/lib/freebl/ecl/curve25519_32.c new file mode 100644 index 0000000..0122961 --- /dev/null +++ b/nss/lib/freebl/ecl/curve25519_32.c @@ -0,0 +1,390 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Derived from public domain code by Matthew Dempsky and D. J. Bernstein. + */ + +#include "ecl-priv.h" +#include "mpi.h" + +#include <stdint.h> +#include <stdio.h> + +typedef uint32_t elem[32]; + +/* + * Add two field elements. + * out = a + b + */ +static void +add(elem out, const elem a, const elem b) +{ + uint32_t j; + uint32_t u = 0; + for (j = 0; j < 31; ++j) { + u += a[j] + b[j]; + out[j] = u & 0xFF; + u >>= 8; + } + u += a[31] + b[31]; + out[31] = u; +} + +/* + * Subtract two field elements. + * out = a - b + */ +static void +sub(elem out, const elem a, const elem b) +{ + uint32_t j; + uint32_t u; + u = 218; + for (j = 0; j < 31; ++j) { + u += a[j] + 0xFF00 - b[j]; + out[j] = u & 0xFF; + u >>= 8; + } + u += a[31] - b[31]; + out[31] = u; +} + +/* + * "Squeeze" an element after multiplication (and square). + */ +static void +squeeze(elem a) +{ + uint32_t j; + uint32_t u; + u = 0; + for (j = 0; j < 31; ++j) { + u += a[j]; + a[j] = u & 0xFF; + u >>= 8; + } + u += a[31]; + a[31] = u & 0x7F; + u = 19 * (u >> 7); + for (j = 0; j < 31; ++j) { + u += a[j]; + a[j] = u & 0xFF; + u >>= 8; + } + a[31] += u; +} + +static const elem minusp = { 19, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 128 }; + +/* + * Reduce point a by 2^255-19 + */ +static void +reduce(elem a) +{ + elem aorig; + uint32_t j; + uint32_t negative; + + for (j = 0; j < 32; ++j) { + aorig[j] = a[j]; + } + add(a, a, minusp); + negative = 1 + ~((a[31] >> 7) & 1); + for (j = 0; j < 32; ++j) { + a[j] ^= negative & (aorig[j] ^ a[j]); + } +} + +/* + * Multiplication and squeeze + * out = a * b + */ +static void +mult(elem out, const elem a, const elem b) +{ + uint32_t i; + uint32_t j; + uint32_t u; + + for (i = 0; i < 32; ++i) { + u = 0; + for (j = 0; j <= i; ++j) { + u += a[j] * b[i - j]; + } + for (j = i + 1; j < 32; ++j) { + u += 38 * a[j] * b[i + 32 - j]; + } + out[i] = u; + } + squeeze(out); +} + +/* + * Multiplication + * out = 121665 * a + */ +static void +mult121665(elem out, const elem a) +{ + uint32_t j; + uint32_t u; + + u = 0; + for (j = 0; j < 31; ++j) { + u += 121665 * a[j]; + out[j] = u & 0xFF; + u >>= 8; + } + u += 121665 * a[31]; + out[31] = u & 0x7F; + u = 19 * (u >> 7); + for (j = 0; j < 31; ++j) { + u += out[j]; + out[j] = u & 0xFF; + u >>= 8; + } + u += out[j]; + out[j] = u; +} + +/* + * Square a and squeeze the result. + * out = a * a + */ +static void +square(elem out, const elem a) +{ + uint32_t i; + uint32_t j; + uint32_t u; + + for (i = 0; i < 32; ++i) { + u = 0; + for (j = 0; j < i - j; ++j) { + u += a[j] * a[i - j]; + } + for (j = i + 1; j < i + 32 - j; ++j) { + u += 38 * a[j] * a[i + 32 - j]; + } + u *= 2; + if ((i & 1) == 0) { + u += a[i / 2] * a[i / 2]; + u += 38 * a[i / 2 + 16] * a[i / 2 + 16]; + } + out[i] = u; + } + squeeze(out); +} + +/* + * Constant time swap between r and s depending on b + */ +static void +cswap(uint32_t p[64], uint32_t q[64], uint32_t b) +{ + uint32_t j; + uint32_t swap = 1 + ~b; + + for (j = 0; j < 64; ++j) { + const uint32_t t = swap & (p[j] ^ q[j]); + p[j] ^= t; + q[j] ^= t; + } +} + +/* + * Montgomery ladder + */ +static void +monty(elem x_2_out, elem z_2_out, + const elem point, const elem scalar) +{ + uint32_t x_3[64] = { 0 }; + uint32_t x_2[64] = { 0 }; + uint32_t a0[64]; + uint32_t a1[64]; + uint32_t b0[64]; + uint32_t b1[64]; + uint32_t c1[64]; + uint32_t r[32]; + uint32_t s[32]; + uint32_t t[32]; + uint32_t u[32]; + uint32_t swap = 0; + uint32_t k_t = 0; + int j; + + for (j = 0; j < 32; ++j) { + x_3[j] = point[j]; + } + x_3[32] = 1; + x_2[0] = 1; + + for (j = 254; j >= 0; --j) { + k_t = (scalar[j >> 3] >> (j & 7)) & 1; + swap ^= k_t; + cswap(x_2, x_3, swap); + swap = k_t; + add(a0, x_2, x_2 + 32); + sub(a0 + 32, x_2, x_2 + 32); + add(a1, x_3, x_3 + 32); + sub(a1 + 32, x_3, x_3 + 32); + square(b0, a0); + square(b0 + 32, a0 + 32); + mult(b1, a1, a0 + 32); + mult(b1 + 32, a1 + 32, a0); + add(c1, b1, b1 + 32); + sub(c1 + 32, b1, b1 + 32); + square(r, c1 + 32); + sub(s, b0, b0 + 32); + mult121665(t, s); + add(u, t, b0); + mult(x_2, b0, b0 + 32); + mult(x_2 + 32, s, u); + square(x_3, c1); + mult(x_3 + 32, r, point); + } + + cswap(x_2, x_3, swap); + for (j = 0; j < 32; ++j) { + x_2_out[j] = x_2[j]; + } + for (j = 0; j < 32; ++j) { + z_2_out[j] = x_2[j + 32]; + } +} + +static void +recip(elem out, const elem z) +{ + elem z2; + elem z9; + elem z11; + elem z2_5_0; + elem z2_10_0; + elem z2_20_0; + elem z2_50_0; + elem z2_100_0; + elem t0; + elem t1; + int i; + + /* 2 */ square(z2, z); + /* 4 */ square(t1, z2); + /* 8 */ square(t0, t1); + /* 9 */ mult(z9, t0, z); + /* 11 */ mult(z11, z9, z2); + /* 22 */ square(t0, z11); + /* 2^5 - 2^0 = 31 */ mult(z2_5_0, t0, z9); + + /* 2^6 - 2^1 */ square(t0, z2_5_0); + /* 2^7 - 2^2 */ square(t1, t0); + /* 2^8 - 2^3 */ square(t0, t1); + /* 2^9 - 2^4 */ square(t1, t0); + /* 2^10 - 2^5 */ square(t0, t1); + /* 2^10 - 2^0 */ mult(z2_10_0, t0, z2_5_0); + + /* 2^11 - 2^1 */ square(t0, z2_10_0); + /* 2^12 - 2^2 */ square(t1, t0); + /* 2^20 - 2^10 */ + for (i = 2; i < 10; i += 2) { + square(t0, t1); + square(t1, t0); + } + /* 2^20 - 2^0 */ mult(z2_20_0, t1, z2_10_0); + + /* 2^21 - 2^1 */ square(t0, z2_20_0); + /* 2^22 - 2^2 */ square(t1, t0); + /* 2^40 - 2^20 */ + for (i = 2; i < 20; i += 2) { + square(t0, t1); + square(t1, t0); + } + /* 2^40 - 2^0 */ mult(t0, t1, z2_20_0); + + /* 2^41 - 2^1 */ square(t1, t0); + /* 2^42 - 2^2 */ square(t0, t1); + /* 2^50 - 2^10 */ + for (i = 2; i < 10; i += 2) { + square(t1, t0); + square(t0, t1); + } + /* 2^50 - 2^0 */ mult(z2_50_0, t0, z2_10_0); + + /* 2^51 - 2^1 */ square(t0, z2_50_0); + /* 2^52 - 2^2 */ square(t1, t0); + /* 2^100 - 2^50 */ + for (i = 2; i < 50; i += 2) { + square(t0, t1); + square(t1, t0); + } + /* 2^100 - 2^0 */ mult(z2_100_0, t1, z2_50_0); + + /* 2^101 - 2^1 */ square(t1, z2_100_0); + /* 2^102 - 2^2 */ square(t0, t1); + /* 2^200 - 2^100 */ + for (i = 2; i < 100; i += 2) { + square(t1, t0); + square(t0, t1); + } + /* 2^200 - 2^0 */ mult(t1, t0, z2_100_0); + + /* 2^201 - 2^1 */ square(t0, t1); + /* 2^202 - 2^2 */ square(t1, t0); + /* 2^250 - 2^50 */ + for (i = 2; i < 50; i += 2) { + square(t0, t1); + square(t1, t0); + } + /* 2^250 - 2^0 */ mult(t0, t1, z2_50_0); + + /* 2^251 - 2^1 */ square(t1, t0); + /* 2^252 - 2^2 */ square(t0, t1); + /* 2^253 - 2^3 */ square(t1, t0); + /* 2^254 - 2^4 */ square(t0, t1); + /* 2^255 - 2^5 */ square(t1, t0); + /* 2^255 - 21 */ mult(out, t1, z11); +} + +/* + * Computes q = Curve25519(p, s) + */ +SECStatus +ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p) +{ + elem point = { 0 }; + elem x_2 = { 0 }; + elem z_2 = { 0 }; + elem X = { 0 }; + elem scalar = { 0 }; + uint32_t i; + + /* read and mask scalar */ + for (i = 0; i < 32; ++i) { + scalar[i] = s[i]; + } + scalar[0] &= 0xF8; + scalar[31] &= 0x7F; + scalar[31] |= 64; + + /* read and mask point */ + for (i = 0; i < 32; ++i) { + point[i] = p[i]; + } + point[31] &= 0x7F; + + monty(x_2, z_2, point, scalar); + recip(z_2, z_2); + mult(X, x_2, z_2); + reduce(X); + for (i = 0; i < 32; ++i) { + q[i] = X[i]; + } + return 0; +} diff --git a/nss/lib/freebl/ecl/curve25519_64.c b/nss/lib/freebl/ecl/curve25519_64.c new file mode 100644 index 0000000..89327ad --- /dev/null +++ b/nss/lib/freebl/ecl/curve25519_64.c @@ -0,0 +1,514 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Derived from public domain C code by Adan Langley and Daniel J. Bernstein + */ + +#include "uint128.h" + +#include "ecl-priv.h" +#include "mpi.h" + +#include <stdint.h> +#include <stdio.h> +#include <string.h> + +typedef uint8_t u8; +typedef uint64_t felem; + +/* Sum two numbers: output += in */ +static void +fsum(felem *output, const felem *in) +{ + unsigned i; + for (i = 0; i < 5; ++i) { + output[i] += in[i]; + } +} + +/* Find the difference of two numbers: output = in - output + * (note the order of the arguments!) + */ +static void +fdifference_backwards(felem *ioutput, const felem *iin) +{ + static const int64_t twotothe51 = ((int64_t)1l << 51); + const int64_t *in = (const int64_t *)iin; + int64_t *out = (int64_t *)ioutput; + + out[0] = in[0] - out[0]; + out[1] = in[1] - out[1]; + out[2] = in[2] - out[2]; + out[3] = in[3] - out[3]; + out[4] = in[4] - out[4]; + + // An arithmetic shift right of 63 places turns a positive number to 0 and a + // negative number to all 1's. This gives us a bitmask that lets us avoid + // side-channel prone branches. + int64_t t; + +#define NEGCHAIN(a, b) \ + t = out[a] >> 63; \ + out[a] += twotothe51 & t; \ + out[b] -= 1 & t; + +#define NEGCHAIN19(a, b) \ + t = out[a] >> 63; \ + out[a] += twotothe51 & t; \ + out[b] -= 19 & t; + + NEGCHAIN(0, 1); + NEGCHAIN(1, 2); + NEGCHAIN(2, 3); + NEGCHAIN(3, 4); + NEGCHAIN19(4, 0); + NEGCHAIN(0, 1); + NEGCHAIN(1, 2); + NEGCHAIN(2, 3); + NEGCHAIN(3, 4); +} + +/* Multiply a number by a scalar: output = in * scalar */ +static void +fscalar_product(felem *output, const felem *in, + const felem scalar) +{ + uint128_t tmp, tmp2; + + tmp = mul6464(in[0], scalar); + output[0] = mask51(tmp); + + tmp2 = mul6464(in[1], scalar); + tmp = add128(tmp2, rshift128(tmp, 51)); + output[1] = mask51(tmp); + + tmp2 = mul6464(in[2], scalar); + tmp = add128(tmp2, rshift128(tmp, 51)); + output[2] = mask51(tmp); + + tmp2 = mul6464(in[3], scalar); + tmp = add128(tmp2, rshift128(tmp, 51)); + output[3] = mask51(tmp); + + tmp2 = mul6464(in[4], scalar); + tmp = add128(tmp2, rshift128(tmp, 51)); + output[4] = mask51(tmp); + + output[0] += mask_lower(rshift128(tmp, 51)) * 19; +} + +/* Multiply two numbers: output = in2 * in + * + * output must be distinct to both inputs. The inputs are reduced coefficient + * form, the output is not. + */ +static void +fmul(felem *output, const felem *in2, const felem *in) +{ + uint128_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + + t0 = mul6464(in[0], in2[0]); + t1 = add128(mul6464(in[1], in2[0]), mul6464(in[0], in2[1])); + t2 = add128(add128(mul6464(in[0], in2[2]), + mul6464(in[2], in2[0])), + mul6464(in[1], in2[1])); + t3 = add128(add128(add128(mul6464(in[0], in2[3]), + mul6464(in[3], in2[0])), + mul6464(in[1], in2[2])), + mul6464(in[2], in2[1])); + t4 = add128(add128(add128(add128(mul6464(in[0], in2[4]), + mul6464(in[4], in2[0])), + mul6464(in[3], in2[1])), + mul6464(in[1], in2[3])), + mul6464(in[2], in2[2])); + t5 = add128(add128(add128(mul6464(in[4], in2[1]), + mul6464(in[1], in2[4])), + mul6464(in[2], in2[3])), + mul6464(in[3], in2[2])); + t6 = add128(add128(mul6464(in[4], in2[2]), + mul6464(in[2], in2[4])), + mul6464(in[3], in2[3])); + t7 = add128(mul6464(in[3], in2[4]), mul6464(in[4], in2[3])); + t8 = mul6464(in[4], in2[4]); + + t0 = add128(t0, mul12819(t5)); + t1 = add128(t1, mul12819(t6)); + t2 = add128(t2, mul12819(t7)); + t3 = add128(t3, mul12819(t8)); + + t1 = add128(t1, rshift128(t0, 51)); + t0 = mask51full(t0); + t2 = add128(t2, rshift128(t1, 51)); + t1 = mask51full(t1); + t3 = add128(t3, rshift128(t2, 51)); + t4 = add128(t4, rshift128(t3, 51)); + t0 = add128(t0, mul12819(rshift128(t4, 51))); + t1 = add128(t1, rshift128(t0, 51)); + t2 = mask51full(t2); + t2 = add128(t2, rshift128(t1, 51)); + + output[0] = mask51(t0); + output[1] = mask51(t1); + output[2] = mask_lower(t2); + output[3] = mask51(t3); + output[4] = mask51(t4); +} + +static void +fsquare(felem *output, const felem *in) +{ + uint128_t t0, t1, t2, t3, t4, t5, t6, t7, t8; + + t0 = mul6464(in[0], in[0]); + t1 = lshift128(mul6464(in[0], in[1]), 1); + t2 = add128(lshift128(mul6464(in[0], in[2]), 1), + mul6464(in[1], in[1])); + t3 = add128(lshift128(mul6464(in[0], in[3]), 1), + lshift128(mul6464(in[1], in[2]), 1)); + t4 = add128(add128(lshift128(mul6464(in[0], in[4]), 1), + lshift128(mul6464(in[3], in[1]), 1)), + mul6464(in[2], in[2])); + t5 = add128(lshift128(mul6464(in[4], in[1]), 1), + lshift128(mul6464(in[2], in[3]), 1)); + t6 = add128(lshift128(mul6464(in[4], in[2]), 1), + mul6464(in[3], in[3])); + t7 = lshift128(mul6464(in[3], in[4]), 1); + t8 = mul6464(in[4], in[4]); + + t0 = add128(t0, mul12819(t5)); + t1 = add128(t1, mul12819(t6)); + t2 = add128(t2, mul12819(t7)); + t3 = add128(t3, mul12819(t8)); + + t1 = add128(t1, rshift128(t0, 51)); + t0 = mask51full(t0); + t2 = add128(t2, rshift128(t1, 51)); + t1 = mask51full(t1); + t3 = add128(t3, rshift128(t2, 51)); + t4 = add128(t4, rshift128(t3, 51)); + t0 = add128(t0, mul12819(rshift128(t4, 51))); + t1 = add128(t1, rshift128(t0, 51)); + + output[0] = mask51(t0); + output[1] = mask_lower(t1); + output[2] = mask51(t2); + output[3] = mask51(t3); + output[4] = mask51(t4); +} + +/* Take a 32-byte number and expand it into polynomial form */ +static void NO_SANITIZE_ALIGNMENT +fexpand(felem *output, const u8 *in) +{ + output[0] = *((const uint64_t *)(in)) & MASK51; + output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51; + output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51; + output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51; + output[4] = (*((const uint64_t *)(in + 25)) >> 4) & MASK51; +} + +/* Take a fully reduced polynomial form number and contract it into a + * 32-byte array + */ +static void +fcontract(u8 *output, const felem *input) +{ + uint128_t t0 = init128x(input[0]); + uint128_t t1 = init128x(input[1]); + uint128_t t2 = init128x(input[2]); + uint128_t t3 = init128x(input[3]); + uint128_t t4 = init128x(input[4]); + uint128_t tmp = init128x(19); + + t1 = add128(t1, rshift128(t0, 51)); + t0 = mask51full(t0); + t2 = add128(t2, rshift128(t1, 51)); + t1 = mask51full(t1); + t3 = add128(t3, rshift128(t2, 51)); + t2 = mask51full(t2); + t4 = add128(t4, rshift128(t3, 51)); + t3 = mask51full(t3); + t0 = add128(t0, mul12819(rshift128(t4, 51))); + t4 = mask51full(t4); + + t1 = add128(t1, rshift128(t0, 51)); + t0 = mask51full(t0); + t2 = add128(t2, rshift128(t1, 51)); + t1 = mask51full(t1); + t3 = add128(t3, rshift128(t2, 51)); + t2 = mask51full(t2); + t4 = add128(t4, rshift128(t3, 51)); + t3 = mask51full(t3); + t0 = add128(t0, mul12819(rshift128(t4, 51))); + t4 = mask51full(t4); + + /* now t is between 0 and 2^255-1, properly carried. */ + /* case 1: between 0 and 2^255-20. case 2: between 2^255-19 and 2^255-1. */ + + t0 = add128(t0, tmp); + + t1 = add128(t1, rshift128(t0, 51)); + t0 = mask51full(t0); + t2 = add128(t2, rshift128(t1, 51)); + t1 = mask51full(t1); + t3 = add128(t3, rshift128(t2, 51)); + t2 = mask51full(t2); + t4 = add128(t4, rshift128(t3, 51)); + t3 = mask51full(t3); + t0 = add128(t0, mul12819(rshift128(t4, 51))); + t4 = mask51full(t4); + + /* now between 19 and 2^255-1 in both cases, and offset by 19. */ + + t0 = add128(t0, init128x(0x8000000000000 - 19)); + tmp = init128x(0x8000000000000 - 1); + t1 = add128(t1, tmp); + t2 = add128(t2, tmp); + t3 = add128(t3, tmp); + t4 = add128(t4, tmp); + + /* now between 2^255 and 2^256-20, and offset by 2^255. */ + + t1 = add128(t1, rshift128(t0, 51)); + t0 = mask51full(t0); + t2 = add128(t2, rshift128(t1, 51)); + t1 = mask51full(t1); + t3 = add128(t3, rshift128(t2, 51)); + t2 = mask51full(t2); + t4 = add128(t4, rshift128(t3, 51)); + t3 = mask51full(t3); + t4 = mask51full(t4); + + *((uint64_t *)(output)) = mask_lower(t0) | mask_lower(t1) << 51; + *((uint64_t *)(output + 8)) = (mask_lower(t1) >> 13) | (mask_lower(t2) << 38); + *((uint64_t *)(output + 16)) = (mask_lower(t2) >> 26) | (mask_lower(t3) << 25); + *((uint64_t *)(output + 24)) = (mask_lower(t3) >> 39) | (mask_lower(t4) << 12); +} + +/* Input: Q, Q', Q-Q' + * Output: 2Q, Q+Q' + * + * x2 z3: long form + * x3 z3: long form + * x z: short form, destroyed + * xprime zprime: short form, destroyed + * qmqp: short form, preserved + */ +static void +fmonty(felem *x2, felem *z2, /* output 2Q */ + felem *x3, felem *z3, /* output Q + Q' */ + felem *x, felem *z, /* input Q */ + felem *xprime, felem *zprime, /* input Q' */ + const felem *qmqp /* input Q - Q' */) +{ + felem origx[5], origxprime[5], zzz[5], xx[5], zz[5], xxprime[5], zzprime[5], + zzzprime[5]; + + memcpy(origx, x, 5 * sizeof(felem)); + fsum(x, z); + fdifference_backwards(z, origx); // does x - z + + memcpy(origxprime, xprime, sizeof(felem) * 5); + fsum(xprime, zprime); + fdifference_backwards(zprime, origxprime); + fmul(xxprime, xprime, z); + fmul(zzprime, x, zprime); + memcpy(origxprime, xxprime, sizeof(felem) * 5); + fsum(xxprime, zzprime); + fdifference_backwards(zzprime, origxprime); + fsquare(x3, xxprime); + fsquare(zzzprime, zzprime); + fmul(z3, zzzprime, qmqp); + + fsquare(xx, x); + fsquare(zz, z); + fmul(x2, xx, zz); + fdifference_backwards(zz, xx); // does zz = xx - zz + fscalar_product(zzz, zz, 121665); + fsum(zzz, xx); + fmul(z2, zz, zzz); +} + +// ----------------------------------------------------------------------------- +// Maybe swap the contents of two felem arrays (@a and @b), each @len elements +// long. Perform the swap iff @swap is non-zero. +// +// This function performs the swap without leaking any side-channel +// information. +// ----------------------------------------------------------------------------- +static void +swap_conditional(felem *a, felem *b, unsigned len, felem iswap) +{ + unsigned i; + const felem swap = 1 + ~iswap; + + for (i = 0; i < len; ++i) { + const felem x = swap & (a[i] ^ b[i]); + a[i] ^= x; + b[i] ^= x; + } +} + +/* Calculates nQ where Q is the x-coordinate of a point on the curve + * + * resultx/resultz: the x coordinate of the resulting curve point (short form) + * n: a 32-byte number + * q: a point of the curve (short form) + */ +static void +cmult(felem *resultx, felem *resultz, const u8 *n, const felem *q) +{ + felem a[5] = { 0 }, b[5] = { 1 }, c[5] = { 1 }, d[5] = { 0 }; + felem *nqpqx = a, *nqpqz = b, *nqx = c, *nqz = d, *t; + felem e[5] = { 0 }, f[5] = { 1 }, g[5] = { 0 }, h[5] = { 1 }; + felem *nqpqx2 = e, *nqpqz2 = f, *nqx2 = g, *nqz2 = h; + + unsigned i, j; + + memcpy(nqpqx, q, sizeof(felem) * 5); + + for (i = 0; i < 32; ++i) { + u8 byte = n[31 - i]; + for (j = 0; j < 8; ++j) { + const felem bit = byte >> 7; + + swap_conditional(nqx, nqpqx, 5, bit); + swap_conditional(nqz, nqpqz, 5, bit); + fmonty(nqx2, nqz2, nqpqx2, nqpqz2, nqx, nqz, nqpqx, nqpqz, q); + swap_conditional(nqx2, nqpqx2, 5, bit); + swap_conditional(nqz2, nqpqz2, 5, bit); + + t = nqx; + nqx = nqx2; + nqx2 = t; + t = nqz; + nqz = nqz2; + nqz2 = t; + t = nqpqx; + nqpqx = nqpqx2; + nqpqx2 = t; + t = nqpqz; + nqpqz = nqpqz2; + nqpqz2 = t; + + byte <<= 1; + } + } + + memcpy(resultx, nqx, sizeof(felem) * 5); + memcpy(resultz, nqz, sizeof(felem) * 5); +} + +// ----------------------------------------------------------------------------- +// Shamelessly copied from djb's code +// ----------------------------------------------------------------------------- +static void +crecip(felem *out, const felem *z) +{ + felem z2[5]; + felem z9[5]; + felem z11[5]; + felem z2_5_0[5]; + felem z2_10_0[5]; + felem z2_20_0[5]; + felem z2_50_0[5]; + felem z2_100_0[5]; + felem t0[5]; + felem t1[5]; + int i; + + /* 2 */ fsquare(z2, z); + /* 4 */ fsquare(t1, z2); + /* 8 */ fsquare(t0, t1); + /* 9 */ fmul(z9, t0, z); + /* 11 */ fmul(z11, z9, z2); + /* 22 */ fsquare(t0, z11); + /* 2^5 - 2^0 = 31 */ fmul(z2_5_0, t0, z9); + + /* 2^6 - 2^1 */ fsquare(t0, z2_5_0); + /* 2^7 - 2^2 */ fsquare(t1, t0); + /* 2^8 - 2^3 */ fsquare(t0, t1); + /* 2^9 - 2^4 */ fsquare(t1, t0); + /* 2^10 - 2^5 */ fsquare(t0, t1); + /* 2^10 - 2^0 */ fmul(z2_10_0, t0, z2_5_0); + + /* 2^11 - 2^1 */ fsquare(t0, z2_10_0); + /* 2^12 - 2^2 */ fsquare(t1, t0); + /* 2^20 - 2^10 */ for (i = 2; i < 10; i += 2) { + fsquare(t0, t1); + fsquare(t1, t0); + } + /* 2^20 - 2^0 */ fmul(z2_20_0, t1, z2_10_0); + + /* 2^21 - 2^1 */ fsquare(t0, z2_20_0); + /* 2^22 - 2^2 */ fsquare(t1, t0); + /* 2^40 - 2^20 */ for (i = 2; i < 20; i += 2) { + fsquare(t0, t1); + fsquare(t1, t0); + } + /* 2^40 - 2^0 */ fmul(t0, t1, z2_20_0); + + /* 2^41 - 2^1 */ fsquare(t1, t0); + /* 2^42 - 2^2 */ fsquare(t0, t1); + /* 2^50 - 2^10 */ for (i = 2; i < 10; i += 2) { + fsquare(t1, t0); + fsquare(t0, t1); + } + /* 2^50 - 2^0 */ fmul(z2_50_0, t0, z2_10_0); + + /* 2^51 - 2^1 */ fsquare(t0, z2_50_0); + /* 2^52 - 2^2 */ fsquare(t1, t0); + /* 2^100 - 2^50 */ for (i = 2; i < 50; i += 2) { + fsquare(t0, t1); + fsquare(t1, t0); + } + /* 2^100 - 2^0 */ fmul(z2_100_0, t1, z2_50_0); + + /* 2^101 - 2^1 */ fsquare(t1, z2_100_0); + /* 2^102 - 2^2 */ fsquare(t0, t1); + /* 2^200 - 2^100 */ for (i = 2; i < 100; i += 2) { + fsquare(t1, t0); + fsquare(t0, t1); + } + /* 2^200 - 2^0 */ fmul(t1, t0, z2_100_0); + + /* 2^201 - 2^1 */ fsquare(t0, t1); + /* 2^202 - 2^2 */ fsquare(t1, t0); + /* 2^250 - 2^50 */ for (i = 2; i < 50; i += 2) { + fsquare(t0, t1); + fsquare(t1, t0); + } + /* 2^250 - 2^0 */ fmul(t0, t1, z2_50_0); + + /* 2^251 - 2^1 */ fsquare(t1, t0); + /* 2^252 - 2^2 */ fsquare(t0, t1); + /* 2^253 - 2^3 */ fsquare(t1, t0); + /* 2^254 - 2^4 */ fsquare(t0, t1); + /* 2^255 - 2^5 */ fsquare(t1, t0); + /* 2^255 - 21 */ fmul(out, t1, z11); +} + +SECStatus +ec_Curve25519_mul(uint8_t *mypublic, const uint8_t *secret, + const uint8_t *basepoint) +{ + felem bp[5], x[5], z[5], zmone[5]; + uint8_t e[32]; + int i; + + for (i = 0; i < 32; ++i) { + e[i] = secret[i]; + } + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + fexpand(bp, basepoint); + cmult(x, z, e, bp); + crecip(zmone, z); + fmul(z, x, zmone); + fcontract(mypublic, z); + + return 0; +} diff --git a/nss/lib/freebl/ecl/ec2.h b/nss/lib/freebl/ecl/ec2.h deleted file mode 100644 index 5d75d48..0000000 --- a/nss/lib/freebl/ecl/ec2.h +++ /dev/null @@ -1,92 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef __ec2_h_ -#define __ec2_h_ - -#include "ecl-priv.h" - -/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ -mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py); - -/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */ -mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py); - -/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, - * qy). Uses affine coordinates. */ -mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, const ECGroup *group); - -/* Computes R = P - Q. Uses affine coordinates. */ -mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, const ECGroup *group); - -/* Computes R = 2P. Uses affine coordinates. */ -mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); - -/* Validates a point on a GF2m curve. */ -mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group); - -/* by default, this routine is unused and thus doesn't need to be compiled */ -#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF -/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters - * a, b and p are the elliptic curve coefficients and the irreducible that - * determines the field GF2m. Uses affine coordinates. */ -mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); -#endif - -/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters - * a, b and p are the elliptic curve coefficients and the irreducible that - * determines the field GF2m. Uses Montgomery projective coordinates. */ -mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); - -#ifdef ECL_ENABLE_GF2M_PROJ -/* Converts a point P(px, py) from affine coordinates to projective - * coordinates R(rx, ry, rz). */ -mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, mp_int *rz, const ECGroup *group); - -/* Converts a point P(px, py, pz) from projective coordinates to affine - * coordinates R(rx, ry). */ -mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py, - const mp_int *pz, mp_int *rx, mp_int *ry, - const ECGroup *group); - -/* Checks if point P(px, py, pz) is at infinity. Uses projective - * coordinates. */ -mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py, - const mp_int *pz); - -/* Sets P(px, py, pz) to be the point at infinity. Uses projective - * coordinates. */ -mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz); - -/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is - * (qx, qy, qz). Uses projective coordinates. */ -mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py, - const mp_int *pz, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, - mp_int *rz, const ECGroup *group); - -/* Computes R = 2P. Uses projective coordinates. */ -mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py, - const mp_int *pz, mp_int *rx, mp_int *ry, - mp_int *rz, const ECGroup *group); - -/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters - * a, b and p are the elliptic curve coefficients and the prime that - * determines the field GF2m. Uses projective coordinates. */ -mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); -#endif - -#endif /* __ec2_h_ */ diff --git a/nss/lib/freebl/ecl/ec2_163.c b/nss/lib/freebl/ecl/ec2_163.c deleted file mode 100644 index 8ed40a4..0000000 --- a/nss/lib/freebl/ecl/ec2_163.c +++ /dev/null @@ -1,223 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ec2.h" -#include "mp_gf2m.h" -#include "mp_gf2m-priv.h" -#include "mpi.h" -#include "mpi-priv.h" -#include <stdlib.h> - -/* Fast reduction for polynomials over a 163-bit curve. Assumes reduction - * polynomial with terms {163, 7, 6, 3, 0}. */ -mp_err -ec_GF2m_163_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit *u, z; - - if (a != r) { - MP_CHECKOK(mp_copy(a, r)); - } -#ifdef ECL_SIXTY_FOUR_BIT - if (MP_USED(r) < 6) { - MP_CHECKOK(s_mp_pad(r, 6)); - } - u = MP_DIGITS(r); - MP_USED(r) = 6; - - /* u[5] only has 6 significant bits */ - z = u[5]; - u[2] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29); - z = u[4]; - u[2] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35); - u[1] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29); - z = u[3]; - u[1] ^= (z >> 28) ^ (z >> 29) ^ (z >> 32) ^ (z >> 35); - u[0] ^= (z << 36) ^ (z << 35) ^ (z << 32) ^ (z << 29); - z = u[2] >> 35; /* z only has 29 significant bits */ - u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z; - /* clear bits above 163 */ - u[5] = u[4] = u[3] = 0; - u[2] ^= z << 35; -#else - if (MP_USED(r) < 11) { - MP_CHECKOK(s_mp_pad(r, 11)); - } - u = MP_DIGITS(r); - MP_USED(r) = 11; - - /* u[11] only has 6 significant bits */ - z = u[10]; - u[5] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); - u[4] ^= (z << 29); - z = u[9]; - u[5] ^= (z >> 28) ^ (z >> 29); - u[4] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); - u[3] ^= (z << 29); - z = u[8]; - u[4] ^= (z >> 28) ^ (z >> 29); - u[3] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); - u[2] ^= (z << 29); - z = u[7]; - u[3] ^= (z >> 28) ^ (z >> 29); - u[2] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); - u[1] ^= (z << 29); - z = u[6]; - u[2] ^= (z >> 28) ^ (z >> 29); - u[1] ^= (z << 4) ^ (z << 3) ^ z ^ (z >> 3); - u[0] ^= (z << 29); - z = u[5] >> 3; /* z only has 29 significant bits */ - u[1] ^= (z >> 25) ^ (z >> 26); - u[0] ^= (z << 7) ^ (z << 6) ^ (z << 3) ^ z; - /* clear bits above 163 */ - u[11] = u[10] = u[9] = u[8] = u[7] = u[6] = 0; - u[5] ^= z << 3; -#endif - s_mp_clamp(r); - - CLEANUP: - return res; -} - -/* Fast squaring for polynomials over a 163-bit curve. Assumes reduction - * polynomial with terms {163, 7, 6, 3, 0}. */ -mp_err -ec_GF2m_163_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit *u, *v; - - v = MP_DIGITS(a); - -#ifdef ECL_SIXTY_FOUR_BIT - if (MP_USED(a) < 3) { - return mp_bsqrmod(a, meth->irr_arr, r); - } - if (MP_USED(r) < 6) { - MP_CHECKOK(s_mp_pad(r, 6)); - } - MP_USED(r) = 6; -#else - if (MP_USED(a) < 6) { - return mp_bsqrmod(a, meth->irr_arr, r); - } - if (MP_USED(r) < 12) { - MP_CHECKOK(s_mp_pad(r, 12)); - } - MP_USED(r) = 12; -#endif - u = MP_DIGITS(r); - -#ifdef ECL_THIRTY_TWO_BIT - u[11] = gf2m_SQR1(v[5]); - u[10] = gf2m_SQR0(v[5]); - u[9] = gf2m_SQR1(v[4]); - u[8] = gf2m_SQR0(v[4]); - u[7] = gf2m_SQR1(v[3]); - u[6] = gf2m_SQR0(v[3]); -#endif - u[5] = gf2m_SQR1(v[2]); - u[4] = gf2m_SQR0(v[2]); - u[3] = gf2m_SQR1(v[1]); - u[2] = gf2m_SQR0(v[1]); - u[1] = gf2m_SQR1(v[0]); - u[0] = gf2m_SQR0(v[0]); - return ec_GF2m_163_mod(r, r, meth); - - CLEANUP: - return res; -} - -/* Fast multiplication for polynomials over a 163-bit curve. Assumes - * reduction polynomial with terms {163, 7, 6, 3, 0}. */ -mp_err -ec_GF2m_163_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit a2 = 0, a1 = 0, a0, b2 = 0, b1 = 0, b0; - -#ifdef ECL_THIRTY_TWO_BIT - mp_digit a5 = 0, a4 = 0, a3 = 0, b5 = 0, b4 = 0, b3 = 0; - mp_digit rm[6]; -#endif - - if (a == b) { - return ec_GF2m_163_sqr(a, r, meth); - } else { - switch (MP_USED(a)) { -#ifdef ECL_THIRTY_TWO_BIT - case 6: - a5 = MP_DIGIT(a, 5); - case 5: - a4 = MP_DIGIT(a, 4); - case 4: - a3 = MP_DIGIT(a, 3); -#endif - case 3: - a2 = MP_DIGIT(a, 2); - case 2: - a1 = MP_DIGIT(a, 1); - default: - a0 = MP_DIGIT(a, 0); - } - switch (MP_USED(b)) { -#ifdef ECL_THIRTY_TWO_BIT - case 6: - b5 = MP_DIGIT(b, 5); - case 5: - b4 = MP_DIGIT(b, 4); - case 4: - b3 = MP_DIGIT(b, 3); -#endif - case 3: - b2 = MP_DIGIT(b, 2); - case 2: - b1 = MP_DIGIT(b, 1); - default: - b0 = MP_DIGIT(b, 0); - } -#ifdef ECL_SIXTY_FOUR_BIT - MP_CHECKOK(s_mp_pad(r, 6)); - s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0); - MP_USED(r) = 6; - s_mp_clamp(r); -#else - MP_CHECKOK(s_mp_pad(r, 12)); - s_bmul_3x3(MP_DIGITS(r) + 6, a5, a4, a3, b5, b4, b3); - s_bmul_3x3(MP_DIGITS(r), a2, a1, a0, b2, b1, b0); - s_bmul_3x3(rm, a5 ^ a2, a4 ^ a1, a3 ^ a0, b5 ^ b2, b4 ^ b1, - b3 ^ b0); - rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 11); - rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 10); - rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 9); - rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 8); - rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 7); - rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 6); - MP_DIGIT(r, 8) ^= rm[5]; - MP_DIGIT(r, 7) ^= rm[4]; - MP_DIGIT(r, 6) ^= rm[3]; - MP_DIGIT(r, 5) ^= rm[2]; - MP_DIGIT(r, 4) ^= rm[1]; - MP_DIGIT(r, 3) ^= rm[0]; - MP_USED(r) = 12; - s_mp_clamp(r); -#endif - return ec_GF2m_163_mod(r, r, meth); - } - - CLEANUP: - return res; -} - -/* Wire in fast field arithmetic for 163-bit curves. */ -mp_err -ec_group_set_gf2m163(ECGroup *group, ECCurveName name) -{ - group->meth->field_mod = &ec_GF2m_163_mod; - group->meth->field_mul = &ec_GF2m_163_mul; - group->meth->field_sqr = &ec_GF2m_163_sqr; - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ec2_193.c b/nss/lib/freebl/ecl/ec2_193.c deleted file mode 100644 index edb38a6..0000000 --- a/nss/lib/freebl/ecl/ec2_193.c +++ /dev/null @@ -1,240 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ec2.h" -#include "mp_gf2m.h" -#include "mp_gf2m-priv.h" -#include "mpi.h" -#include "mpi-priv.h" -#include <stdlib.h> - -/* Fast reduction for polynomials over a 193-bit curve. Assumes reduction - * polynomial with terms {193, 15, 0}. */ -mp_err -ec_GF2m_193_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit *u, z; - - if (a != r) { - MP_CHECKOK(mp_copy(a, r)); - } -#ifdef ECL_SIXTY_FOUR_BIT - if (MP_USED(r) < 7) { - MP_CHECKOK(s_mp_pad(r, 7)); - } - u = MP_DIGITS(r); - MP_USED(r) = 7; - - /* u[6] only has 2 significant bits */ - z = u[6]; - u[3] ^= (z << 14) ^ (z >> 1); - u[2] ^= (z << 63); - z = u[5]; - u[3] ^= (z >> 50); - u[2] ^= (z << 14) ^ (z >> 1); - u[1] ^= (z << 63); - z = u[4]; - u[2] ^= (z >> 50); - u[1] ^= (z << 14) ^ (z >> 1); - u[0] ^= (z << 63); - z = u[3] >> 1; /* z only has 63 significant bits */ - u[1] ^= (z >> 49); - u[0] ^= (z << 15) ^ z; - /* clear bits above 193 */ - u[6] = u[5] = u[4] = 0; - u[3] ^= z << 1; -#else - if (MP_USED(r) < 13) { - MP_CHECKOK(s_mp_pad(r, 13)); - } - u = MP_DIGITS(r); - MP_USED(r) = 13; - - /* u[12] only has 2 significant bits */ - z = u[12]; - u[6] ^= (z << 14) ^ (z >> 1); - u[5] ^= (z << 31); - z = u[11]; - u[6] ^= (z >> 18); - u[5] ^= (z << 14) ^ (z >> 1); - u[4] ^= (z << 31); - z = u[10]; - u[5] ^= (z >> 18); - u[4] ^= (z << 14) ^ (z >> 1); - u[3] ^= (z << 31); - z = u[9]; - u[4] ^= (z >> 18); - u[3] ^= (z << 14) ^ (z >> 1); - u[2] ^= (z << 31); - z = u[8]; - u[3] ^= (z >> 18); - u[2] ^= (z << 14) ^ (z >> 1); - u[1] ^= (z << 31); - z = u[7]; - u[2] ^= (z >> 18); - u[1] ^= (z << 14) ^ (z >> 1); - u[0] ^= (z << 31); - z = u[6] >> 1; /* z only has 31 significant bits */ - u[1] ^= (z >> 17); - u[0] ^= (z << 15) ^ z; - /* clear bits above 193 */ - u[12] = u[11] = u[10] = u[9] = u[8] = u[7] = 0; - u[6] ^= z << 1; -#endif - s_mp_clamp(r); - - CLEANUP: - return res; -} - -/* Fast squaring for polynomials over a 193-bit curve. Assumes reduction - * polynomial with terms {193, 15, 0}. */ -mp_err -ec_GF2m_193_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit *u, *v; - - v = MP_DIGITS(a); - -#ifdef ECL_SIXTY_FOUR_BIT - if (MP_USED(a) < 4) { - return mp_bsqrmod(a, meth->irr_arr, r); - } - if (MP_USED(r) < 7) { - MP_CHECKOK(s_mp_pad(r, 7)); - } - MP_USED(r) = 7; -#else - if (MP_USED(a) < 7) { - return mp_bsqrmod(a, meth->irr_arr, r); - } - if (MP_USED(r) < 13) { - MP_CHECKOK(s_mp_pad(r, 13)); - } - MP_USED(r) = 13; -#endif - u = MP_DIGITS(r); - -#ifdef ECL_THIRTY_TWO_BIT - u[12] = gf2m_SQR0(v[6]); - u[11] = gf2m_SQR1(v[5]); - u[10] = gf2m_SQR0(v[5]); - u[9] = gf2m_SQR1(v[4]); - u[8] = gf2m_SQR0(v[4]); - u[7] = gf2m_SQR1(v[3]); -#endif - u[6] = gf2m_SQR0(v[3]); - u[5] = gf2m_SQR1(v[2]); - u[4] = gf2m_SQR0(v[2]); - u[3] = gf2m_SQR1(v[1]); - u[2] = gf2m_SQR0(v[1]); - u[1] = gf2m_SQR1(v[0]); - u[0] = gf2m_SQR0(v[0]); - return ec_GF2m_193_mod(r, r, meth); - - CLEANUP: - return res; -} - -/* Fast multiplication for polynomials over a 193-bit curve. Assumes - * reduction polynomial with terms {193, 15, 0}. */ -mp_err -ec_GF2m_193_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0; - -#ifdef ECL_THIRTY_TWO_BIT - mp_digit a6 = 0, a5 = 0, a4 = 0, b6 = 0, b5 = 0, b4 = 0; - mp_digit rm[8]; -#endif - - if (a == b) { - return ec_GF2m_193_sqr(a, r, meth); - } else { - switch (MP_USED(a)) { -#ifdef ECL_THIRTY_TWO_BIT - case 7: - a6 = MP_DIGIT(a, 6); - case 6: - a5 = MP_DIGIT(a, 5); - case 5: - a4 = MP_DIGIT(a, 4); -#endif - case 4: - a3 = MP_DIGIT(a, 3); - case 3: - a2 = MP_DIGIT(a, 2); - case 2: - a1 = MP_DIGIT(a, 1); - default: - a0 = MP_DIGIT(a, 0); - } - switch (MP_USED(b)) { -#ifdef ECL_THIRTY_TWO_BIT - case 7: - b6 = MP_DIGIT(b, 6); - case 6: - b5 = MP_DIGIT(b, 5); - case 5: - b4 = MP_DIGIT(b, 4); -#endif - case 4: - b3 = MP_DIGIT(b, 3); - case 3: - b2 = MP_DIGIT(b, 2); - case 2: - b1 = MP_DIGIT(b, 1); - default: - b0 = MP_DIGIT(b, 0); - } -#ifdef ECL_SIXTY_FOUR_BIT - MP_CHECKOK(s_mp_pad(r, 8)); - s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); - MP_USED(r) = 8; - s_mp_clamp(r); -#else - MP_CHECKOK(s_mp_pad(r, 14)); - s_bmul_3x3(MP_DIGITS(r) + 8, a6, a5, a4, b6, b5, b4); - s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); - s_bmul_4x4(rm, a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b3, b6 ^ b2, b5 ^ b1, - b4 ^ b0); - rm[7] ^= MP_DIGIT(r, 7); - rm[6] ^= MP_DIGIT(r, 6); - rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13); - rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12); - rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11); - rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10); - rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9); - rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8); - MP_DIGIT(r, 11) ^= rm[7]; - MP_DIGIT(r, 10) ^= rm[6]; - MP_DIGIT(r, 9) ^= rm[5]; - MP_DIGIT(r, 8) ^= rm[4]; - MP_DIGIT(r, 7) ^= rm[3]; - MP_DIGIT(r, 6) ^= rm[2]; - MP_DIGIT(r, 5) ^= rm[1]; - MP_DIGIT(r, 4) ^= rm[0]; - MP_USED(r) = 14; - s_mp_clamp(r); -#endif - return ec_GF2m_193_mod(r, r, meth); - } - - CLEANUP: - return res; -} - -/* Wire in fast field arithmetic for 193-bit curves. */ -mp_err -ec_group_set_gf2m193(ECGroup *group, ECCurveName name) -{ - group->meth->field_mod = &ec_GF2m_193_mod; - group->meth->field_mul = &ec_GF2m_193_mul; - group->meth->field_sqr = &ec_GF2m_193_sqr; - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ec2_233.c b/nss/lib/freebl/ecl/ec2_233.c deleted file mode 100644 index f73673c..0000000 --- a/nss/lib/freebl/ecl/ec2_233.c +++ /dev/null @@ -1,263 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ec2.h" -#include "mp_gf2m.h" -#include "mp_gf2m-priv.h" -#include "mpi.h" -#include "mpi-priv.h" -#include <stdlib.h> - -/* Fast reduction for polynomials over a 233-bit curve. Assumes reduction - * polynomial with terms {233, 74, 0}. */ -mp_err -ec_GF2m_233_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit *u, z; - - if (a != r) { - MP_CHECKOK(mp_copy(a, r)); - } -#ifdef ECL_SIXTY_FOUR_BIT - if (MP_USED(r) < 8) { - MP_CHECKOK(s_mp_pad(r, 8)); - } - u = MP_DIGITS(r); - MP_USED(r) = 8; - - /* u[7] only has 18 significant bits */ - z = u[7]; - u[4] ^= (z << 33) ^ (z >> 41); - u[3] ^= (z << 23); - z = u[6]; - u[4] ^= (z >> 31); - u[3] ^= (z << 33) ^ (z >> 41); - u[2] ^= (z << 23); - z = u[5]; - u[3] ^= (z >> 31); - u[2] ^= (z << 33) ^ (z >> 41); - u[1] ^= (z << 23); - z = u[4]; - u[2] ^= (z >> 31); - u[1] ^= (z << 33) ^ (z >> 41); - u[0] ^= (z << 23); - z = u[3] >> 41; /* z only has 23 significant bits */ - u[1] ^= (z << 10); - u[0] ^= z; - /* clear bits above 233 */ - u[7] = u[6] = u[5] = u[4] = 0; - u[3] ^= z << 41; -#else - if (MP_USED(r) < 15) { - MP_CHECKOK(s_mp_pad(r, 15)); - } - u = MP_DIGITS(r); - MP_USED(r) = 15; - - /* u[14] only has 18 significant bits */ - z = u[14]; - u[9] ^= (z << 1); - u[7] ^= (z >> 9); - u[6] ^= (z << 23); - z = u[13]; - u[9] ^= (z >> 31); - u[8] ^= (z << 1); - u[6] ^= (z >> 9); - u[5] ^= (z << 23); - z = u[12]; - u[8] ^= (z >> 31); - u[7] ^= (z << 1); - u[5] ^= (z >> 9); - u[4] ^= (z << 23); - z = u[11]; - u[7] ^= (z >> 31); - u[6] ^= (z << 1); - u[4] ^= (z >> 9); - u[3] ^= (z << 23); - z = u[10]; - u[6] ^= (z >> 31); - u[5] ^= (z << 1); - u[3] ^= (z >> 9); - u[2] ^= (z << 23); - z = u[9]; - u[5] ^= (z >> 31); - u[4] ^= (z << 1); - u[2] ^= (z >> 9); - u[1] ^= (z << 23); - z = u[8]; - u[4] ^= (z >> 31); - u[3] ^= (z << 1); - u[1] ^= (z >> 9); - u[0] ^= (z << 23); - z = u[7] >> 9; /* z only has 23 significant bits */ - u[3] ^= (z >> 22); - u[2] ^= (z << 10); - u[0] ^= z; - /* clear bits above 233 */ - u[14] = u[13] = u[12] = u[11] = u[10] = u[9] = u[8] = 0; - u[7] ^= z << 9; -#endif - s_mp_clamp(r); - - CLEANUP: - return res; -} - -/* Fast squaring for polynomials over a 233-bit curve. Assumes reduction - * polynomial with terms {233, 74, 0}. */ -mp_err -ec_GF2m_233_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit *u, *v; - - v = MP_DIGITS(a); - -#ifdef ECL_SIXTY_FOUR_BIT - if (MP_USED(a) < 4) { - return mp_bsqrmod(a, meth->irr_arr, r); - } - if (MP_USED(r) < 8) { - MP_CHECKOK(s_mp_pad(r, 8)); - } - MP_USED(r) = 8; -#else - if (MP_USED(a) < 8) { - return mp_bsqrmod(a, meth->irr_arr, r); - } - if (MP_USED(r) < 15) { - MP_CHECKOK(s_mp_pad(r, 15)); - } - MP_USED(r) = 15; -#endif - u = MP_DIGITS(r); - -#ifdef ECL_THIRTY_TWO_BIT - u[14] = gf2m_SQR0(v[7]); - u[13] = gf2m_SQR1(v[6]); - u[12] = gf2m_SQR0(v[6]); - u[11] = gf2m_SQR1(v[5]); - u[10] = gf2m_SQR0(v[5]); - u[9] = gf2m_SQR1(v[4]); - u[8] = gf2m_SQR0(v[4]); -#endif - u[7] = gf2m_SQR1(v[3]); - u[6] = gf2m_SQR0(v[3]); - u[5] = gf2m_SQR1(v[2]); - u[4] = gf2m_SQR0(v[2]); - u[3] = gf2m_SQR1(v[1]); - u[2] = gf2m_SQR0(v[1]); - u[1] = gf2m_SQR1(v[0]); - u[0] = gf2m_SQR0(v[0]); - return ec_GF2m_233_mod(r, r, meth); - - CLEANUP: - return res; -} - -/* Fast multiplication for polynomials over a 233-bit curve. Assumes - * reduction polynomial with terms {233, 74, 0}. */ -mp_err -ec_GF2m_233_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit a3 = 0, a2 = 0, a1 = 0, a0, b3 = 0, b2 = 0, b1 = 0, b0; - -#ifdef ECL_THIRTY_TWO_BIT - mp_digit a7 = 0, a6 = 0, a5 = 0, a4 = 0, b7 = 0, b6 = 0, b5 = 0, b4 = - 0; - mp_digit rm[8]; -#endif - - if (a == b) { - return ec_GF2m_233_sqr(a, r, meth); - } else { - switch (MP_USED(a)) { -#ifdef ECL_THIRTY_TWO_BIT - case 8: - a7 = MP_DIGIT(a, 7); - case 7: - a6 = MP_DIGIT(a, 6); - case 6: - a5 = MP_DIGIT(a, 5); - case 5: - a4 = MP_DIGIT(a, 4); -#endif - case 4: - a3 = MP_DIGIT(a, 3); - case 3: - a2 = MP_DIGIT(a, 2); - case 2: - a1 = MP_DIGIT(a, 1); - default: - a0 = MP_DIGIT(a, 0); - } - switch (MP_USED(b)) { -#ifdef ECL_THIRTY_TWO_BIT - case 8: - b7 = MP_DIGIT(b, 7); - case 7: - b6 = MP_DIGIT(b, 6); - case 6: - b5 = MP_DIGIT(b, 5); - case 5: - b4 = MP_DIGIT(b, 4); -#endif - case 4: - b3 = MP_DIGIT(b, 3); - case 3: - b2 = MP_DIGIT(b, 2); - case 2: - b1 = MP_DIGIT(b, 1); - default: - b0 = MP_DIGIT(b, 0); - } -#ifdef ECL_SIXTY_FOUR_BIT - MP_CHECKOK(s_mp_pad(r, 8)); - s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); - MP_USED(r) = 8; - s_mp_clamp(r); -#else - MP_CHECKOK(s_mp_pad(r, 16)); - s_bmul_4x4(MP_DIGITS(r) + 8, a7, a6, a5, a4, b7, b6, b5, b4); - s_bmul_4x4(MP_DIGITS(r), a3, a2, a1, a0, b3, b2, b1, b0); - s_bmul_4x4(rm, a7 ^ a3, a6 ^ a2, a5 ^ a1, a4 ^ a0, b7 ^ b3, - b6 ^ b2, b5 ^ b1, b4 ^ b0); - rm[7] ^= MP_DIGIT(r, 7) ^ MP_DIGIT(r, 15); - rm[6] ^= MP_DIGIT(r, 6) ^ MP_DIGIT(r, 14); - rm[5] ^= MP_DIGIT(r, 5) ^ MP_DIGIT(r, 13); - rm[4] ^= MP_DIGIT(r, 4) ^ MP_DIGIT(r, 12); - rm[3] ^= MP_DIGIT(r, 3) ^ MP_DIGIT(r, 11); - rm[2] ^= MP_DIGIT(r, 2) ^ MP_DIGIT(r, 10); - rm[1] ^= MP_DIGIT(r, 1) ^ MP_DIGIT(r, 9); - rm[0] ^= MP_DIGIT(r, 0) ^ MP_DIGIT(r, 8); - MP_DIGIT(r, 11) ^= rm[7]; - MP_DIGIT(r, 10) ^= rm[6]; - MP_DIGIT(r, 9) ^= rm[5]; - MP_DIGIT(r, 8) ^= rm[4]; - MP_DIGIT(r, 7) ^= rm[3]; - MP_DIGIT(r, 6) ^= rm[2]; - MP_DIGIT(r, 5) ^= rm[1]; - MP_DIGIT(r, 4) ^= rm[0]; - MP_USED(r) = 16; - s_mp_clamp(r); -#endif - return ec_GF2m_233_mod(r, r, meth); - } - - CLEANUP: - return res; -} - -/* Wire in fast field arithmetic for 233-bit curves. */ -mp_err -ec_group_set_gf2m233(ECGroup *group, ECCurveName name) -{ - group->meth->field_mod = &ec_GF2m_233_mod; - group->meth->field_mul = &ec_GF2m_233_mul; - group->meth->field_sqr = &ec_GF2m_233_sqr; - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ec2_aff.c b/nss/lib/freebl/ecl/ec2_aff.c deleted file mode 100644 index 50edc54..0000000 --- a/nss/lib/freebl/ecl/ec2_aff.c +++ /dev/null @@ -1,312 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ec2.h" -#include "mplogic.h" -#include "mp_gf2m.h" -#include <stdlib.h> - -/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ -mp_err -ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py) -{ - - if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) { - return MP_YES; - } else { - return MP_NO; - } - -} - -/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */ -mp_err -ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py) -{ - mp_zero(px); - mp_zero(py); - return MP_OKAY; -} - -/* Computes R = P + Q based on IEEE P1363 A.10.2. Elliptic curve points P, - * Q, and R can all be identical. Uses affine coordinates. */ -mp_err -ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, - const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int lambda, tempx, tempy; - - MP_DIGITS(&lambda) = 0; - MP_DIGITS(&tempx) = 0; - MP_DIGITS(&tempy) = 0; - MP_CHECKOK(mp_init(&lambda)); - MP_CHECKOK(mp_init(&tempx)); - MP_CHECKOK(mp_init(&tempy)); - /* if P = inf, then R = Q */ - if (ec_GF2m_pt_is_inf_aff(px, py) == 0) { - MP_CHECKOK(mp_copy(qx, rx)); - MP_CHECKOK(mp_copy(qy, ry)); - res = MP_OKAY; - goto CLEANUP; - } - /* if Q = inf, then R = P */ - if (ec_GF2m_pt_is_inf_aff(qx, qy) == 0) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - res = MP_OKAY; - goto CLEANUP; - } - /* if px != qx, then lambda = (py+qy) / (px+qx), tempx = a + lambda^2 - * + lambda + px + qx */ - if (mp_cmp(px, qx) != 0) { - MP_CHECKOK(group->meth->field_add(py, qy, &tempy, group->meth)); - MP_CHECKOK(group->meth->field_add(px, qx, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_div(&tempy, &tempx, &lambda, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, &lambda, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, &group->curvea, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, px, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, qx, &tempx, group->meth)); - } else { - /* if py != qy or qx = 0, then R = inf */ - if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qx) == 0)) { - mp_zero(rx); - mp_zero(ry); - res = MP_OKAY; - goto CLEANUP; - } - /* lambda = qx + qy / qx */ - MP_CHECKOK(group->meth->field_div(qy, qx, &lambda, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&lambda, qx, &lambda, group->meth)); - /* tempx = a + lambda^2 + lambda */ - MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, &lambda, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, &group->curvea, &tempx, group->meth)); - } - /* ry = (qx + tempx) * lambda + tempx + qy */ - MP_CHECKOK(group->meth->field_add(qx, &tempx, &tempy, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(&tempy, &lambda, &tempy, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempy, &tempx, &tempy, group->meth)); - MP_CHECKOK(group->meth->field_add(&tempy, qy, ry, group->meth)); - /* rx = tempx */ - MP_CHECKOK(mp_copy(&tempx, rx)); - - CLEANUP: - mp_clear(&lambda); - mp_clear(&tempx); - mp_clear(&tempy); - return res; -} - -/* Computes R = P - Q. Elliptic curve points P, Q, and R can all be - * identical. Uses affine coordinates. */ -mp_err -ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, - const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int nqy; - - MP_DIGITS(&nqy) = 0; - MP_CHECKOK(mp_init(&nqy)); - /* nqy = qx+qy */ - MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth)); - MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group)); - CLEANUP: - mp_clear(&nqy); - return res; -} - -/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses - * affine coordinates. */ -mp_err -ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group) -{ - return group->point_add(px, py, px, py, rx, ry, group); -} - -/* by default, this routine is unused and thus doesn't need to be compiled */ -#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF -/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and - * R can be identical. Uses affine coordinates. */ -mp_err -ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int k, k3, qx, qy, sx, sy; - int b1, b3, i, l; - - MP_DIGITS(&k) = 0; - MP_DIGITS(&k3) = 0; - MP_DIGITS(&qx) = 0; - MP_DIGITS(&qy) = 0; - MP_DIGITS(&sx) = 0; - MP_DIGITS(&sy) = 0; - MP_CHECKOK(mp_init(&k)); - MP_CHECKOK(mp_init(&k3)); - MP_CHECKOK(mp_init(&qx)); - MP_CHECKOK(mp_init(&qy)); - MP_CHECKOK(mp_init(&sx)); - MP_CHECKOK(mp_init(&sy)); - - /* if n = 0 then r = inf */ - if (mp_cmp_z(n) == 0) { - mp_zero(rx); - mp_zero(ry); - res = MP_OKAY; - goto CLEANUP; - } - /* Q = P, k = n */ - MP_CHECKOK(mp_copy(px, &qx)); - MP_CHECKOK(mp_copy(py, &qy)); - MP_CHECKOK(mp_copy(n, &k)); - /* if n < 0 then Q = -Q, k = -k */ - if (mp_cmp_z(n) < 0) { - MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth)); - MP_CHECKOK(mp_neg(&k, &k)); - } -#ifdef ECL_DEBUG /* basic double and add method */ - l = mpl_significant_bits(&k) - 1; - MP_CHECKOK(mp_copy(&qx, &sx)); - MP_CHECKOK(mp_copy(&qy, &sy)); - for (i = l - 1; i >= 0; i--) { - /* S = 2S */ - MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); - /* if k_i = 1, then S = S + Q */ - if (mpl_get_bit(&k, i) != 0) { - MP_CHECKOK(group-> - point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); - } - } -#else /* double and add/subtract method from - * standard */ - /* k3 = 3 * k */ - MP_CHECKOK(mp_set_int(&k3, 3)); - MP_CHECKOK(mp_mul(&k, &k3, &k3)); - /* S = Q */ - MP_CHECKOK(mp_copy(&qx, &sx)); - MP_CHECKOK(mp_copy(&qy, &sy)); - /* l = index of high order bit in binary representation of 3*k */ - l = mpl_significant_bits(&k3) - 1; - /* for i = l-1 downto 1 */ - for (i = l - 1; i >= 1; i--) { - /* S = 2S */ - MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); - b3 = MP_GET_BIT(&k3, i); - b1 = MP_GET_BIT(&k, i); - /* if k3_i = 1 and k_i = 0, then S = S + Q */ - if ((b3 == 1) && (b1 == 0)) { - MP_CHECKOK(group-> - point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); - /* if k3_i = 0 and k_i = 1, then S = S - Q */ - } else if ((b3 == 0) && (b1 == 1)) { - MP_CHECKOK(group-> - point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group)); - } - } -#endif - /* output S */ - MP_CHECKOK(mp_copy(&sx, rx)); - MP_CHECKOK(mp_copy(&sy, ry)); - - CLEANUP: - mp_clear(&k); - mp_clear(&k3); - mp_clear(&qx); - mp_clear(&qy); - mp_clear(&sx); - mp_clear(&sy); - return res; -} -#endif - -/* Validates a point on a GF2m curve. */ -mp_err -ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) -{ - mp_err res = MP_NO; - mp_int accl, accr, tmp, pxt, pyt; - - MP_DIGITS(&accl) = 0; - MP_DIGITS(&accr) = 0; - MP_DIGITS(&tmp) = 0; - MP_DIGITS(&pxt) = 0; - MP_DIGITS(&pyt) = 0; - MP_CHECKOK(mp_init(&accl)); - MP_CHECKOK(mp_init(&accr)); - MP_CHECKOK(mp_init(&tmp)); - MP_CHECKOK(mp_init(&pxt)); - MP_CHECKOK(mp_init(&pyt)); - - /* 1: Verify that publicValue is not the point at infinity */ - if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) { - res = MP_NO; - goto CLEANUP; - } - /* 2: Verify that the coordinates of publicValue are elements - * of the field. - */ - if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || - (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) { - res = MP_NO; - goto CLEANUP; - } - /* 3: Verify that publicValue is on the curve. */ - if (group->meth->field_enc) { - group->meth->field_enc(px, &pxt, group->meth); - group->meth->field_enc(py, &pyt, group->meth); - } else { - mp_copy(px, &pxt); - mp_copy(py, &pyt); - } - /* left-hand side: y^2 + x*y */ - MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) ); - MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) ); - /* right-hand side: x^3 + a*x^2 + b */ - MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) ); - MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) ); - MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) ); - /* check LHS - RHS == 0 */ - MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) ); - if (mp_cmp_z(&accr) != 0) { - res = MP_NO; - goto CLEANUP; - } - /* 4: Verify that the order of the curve times the publicValue - * is the point at infinity. - */ - MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) ); - if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { - res = MP_NO; - goto CLEANUP; - } - - res = MP_YES; - -CLEANUP: - mp_clear(&accl); - mp_clear(&accr); - mp_clear(&tmp); - mp_clear(&pxt); - mp_clear(&pyt); - return res; -} diff --git a/nss/lib/freebl/ecl/ec2_mont.c b/nss/lib/freebl/ecl/ec2_mont.c deleted file mode 100644 index 8d35f25..0000000 --- a/nss/lib/freebl/ecl/ec2_mont.c +++ /dev/null @@ -1,238 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ec2.h" -#include "mplogic.h" -#include "mp_gf2m.h" -#include <stdlib.h> - -/* Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery - * projective coordinates. Uses algorithm Mdouble in appendix of Lopez, J. - * and Dahab, R. "Fast multiplication on elliptic curves over GF(2^m) - * without precomputation". modified to not require precomputation of - * c=b^{2^{m-1}}. */ -static mp_err -gf2m_Mdouble(mp_int *x, mp_int *z, const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int t1; - - MP_DIGITS(&t1) = 0; - MP_CHECKOK(mp_init(&t1)); - - MP_CHECKOK(group->meth->field_sqr(x, x, group->meth)); - MP_CHECKOK(group->meth->field_sqr(z, &t1, group->meth)); - MP_CHECKOK(group->meth->field_mul(x, &t1, z, group->meth)); - MP_CHECKOK(group->meth->field_sqr(x, x, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(&group->curveb, &t1, &t1, group->meth)); - MP_CHECKOK(group->meth->field_add(x, &t1, x, group->meth)); - - CLEANUP: - mp_clear(&t1); - return res; -} - -/* Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in - * Montgomery projective coordinates. Uses algorithm Madd in appendix of - * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over - * GF(2^m) without precomputation". */ -static mp_err -gf2m_Madd(const mp_int *x, mp_int *x1, mp_int *z1, mp_int *x2, mp_int *z2, - const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int t1, t2; - - MP_DIGITS(&t1) = 0; - MP_DIGITS(&t2) = 0; - MP_CHECKOK(mp_init(&t1)); - MP_CHECKOK(mp_init(&t2)); - - MP_CHECKOK(mp_copy(x, &t1)); - MP_CHECKOK(group->meth->field_mul(x1, z2, x1, group->meth)); - MP_CHECKOK(group->meth->field_mul(z1, x2, z1, group->meth)); - MP_CHECKOK(group->meth->field_mul(x1, z1, &t2, group->meth)); - MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth)); - MP_CHECKOK(group->meth->field_sqr(z1, z1, group->meth)); - MP_CHECKOK(group->meth->field_mul(z1, &t1, x1, group->meth)); - MP_CHECKOK(group->meth->field_add(x1, &t2, x1, group->meth)); - - CLEANUP: - mp_clear(&t1); - mp_clear(&t2); - return res; -} - -/* Compute the x, y affine coordinates from the point (x1, z1) (x2, z2) - * using Montgomery point multiplication algorithm Mxy() in appendix of - * Lopex, J. and Dahab, R. "Fast multiplication on elliptic curves over - * GF(2^m) without precomputation". Returns: 0 on error 1 if return value - * should be the point at infinity 2 otherwise */ -static int -gf2m_Mxy(const mp_int *x, const mp_int *y, mp_int *x1, mp_int *z1, - mp_int *x2, mp_int *z2, const ECGroup *group) -{ - mp_err res = MP_OKAY; - int ret = 0; - mp_int t3, t4, t5; - - MP_DIGITS(&t3) = 0; - MP_DIGITS(&t4) = 0; - MP_DIGITS(&t5) = 0; - MP_CHECKOK(mp_init(&t3)); - MP_CHECKOK(mp_init(&t4)); - MP_CHECKOK(mp_init(&t5)); - - if (mp_cmp_z(z1) == 0) { - mp_zero(x2); - mp_zero(z2); - ret = 1; - goto CLEANUP; - } - - if (mp_cmp_z(z2) == 0) { - MP_CHECKOK(mp_copy(x, x2)); - MP_CHECKOK(group->meth->field_add(x, y, z2, group->meth)); - ret = 2; - goto CLEANUP; - } - - MP_CHECKOK(mp_set_int(&t5, 1)); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(&t5, &t5, group->meth)); - } - - MP_CHECKOK(group->meth->field_mul(z1, z2, &t3, group->meth)); - - MP_CHECKOK(group->meth->field_mul(z1, x, z1, group->meth)); - MP_CHECKOK(group->meth->field_add(z1, x1, z1, group->meth)); - MP_CHECKOK(group->meth->field_mul(z2, x, z2, group->meth)); - MP_CHECKOK(group->meth->field_mul(z2, x1, x1, group->meth)); - MP_CHECKOK(group->meth->field_add(z2, x2, z2, group->meth)); - - MP_CHECKOK(group->meth->field_mul(z2, z1, z2, group->meth)); - MP_CHECKOK(group->meth->field_sqr(x, &t4, group->meth)); - MP_CHECKOK(group->meth->field_add(&t4, y, &t4, group->meth)); - MP_CHECKOK(group->meth->field_mul(&t4, &t3, &t4, group->meth)); - MP_CHECKOK(group->meth->field_add(&t4, z2, &t4, group->meth)); - - MP_CHECKOK(group->meth->field_mul(&t3, x, &t3, group->meth)); - MP_CHECKOK(group->meth->field_div(&t5, &t3, &t3, group->meth)); - MP_CHECKOK(group->meth->field_mul(&t3, &t4, &t4, group->meth)); - MP_CHECKOK(group->meth->field_mul(x1, &t3, x2, group->meth)); - MP_CHECKOK(group->meth->field_add(x2, x, z2, group->meth)); - - MP_CHECKOK(group->meth->field_mul(z2, &t4, z2, group->meth)); - MP_CHECKOK(group->meth->field_add(z2, y, z2, group->meth)); - - ret = 2; - - CLEANUP: - mp_clear(&t3); - mp_clear(&t4); - mp_clear(&t5); - if (res == MP_OKAY) { - return ret; - } else { - return 0; - } -} - -/* Computes R = nP based on algorithm 2P of Lopex, J. and Dahab, R. "Fast - * multiplication on elliptic curves over GF(2^m) without - * precomputation". Elliptic curve points P and R can be identical. Uses - * Montgomery projective coordinates. */ -mp_err -ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int x1, x2, z1, z2; - int i, j; - mp_digit top_bit, mask; - - MP_DIGITS(&x1) = 0; - MP_DIGITS(&x2) = 0; - MP_DIGITS(&z1) = 0; - MP_DIGITS(&z2) = 0; - MP_CHECKOK(mp_init(&x1)); - MP_CHECKOK(mp_init(&x2)); - MP_CHECKOK(mp_init(&z1)); - MP_CHECKOK(mp_init(&z2)); - - /* if result should be point at infinity */ - if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) { - MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry)); - goto CLEANUP; - } - - MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */ - MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */ - MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 = - * x1^2 = - * px^2 */ - MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth)); - MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2 - * = - * px^4 - * + - * b - */ - - /* find top-most bit and go one past it */ - i = MP_USED(n) - 1; - j = MP_DIGIT_BIT - 1; - top_bit = 1; - top_bit <<= MP_DIGIT_BIT - 1; - mask = top_bit; - while (!(MP_DIGITS(n)[i] & mask)) { - mask >>= 1; - j--; - } - mask >>= 1; - j--; - - /* if top most bit was at word break, go to next word */ - if (!mask) { - i--; - j = MP_DIGIT_BIT - 1; - mask = top_bit; - } - - for (; i >= 0; i--) { - for (; j >= 0; j--) { - if (MP_DIGITS(n)[i] & mask) { - MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group)); - MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group)); - } else { - MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group)); - MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group)); - } - mask >>= 1; - } - j = MP_DIGIT_BIT - 1; - mask = top_bit; - } - - /* convert out of "projective" coordinates */ - i = gf2m_Mxy(px, py, &x1, &z1, &x2, &z2, group); - if (i == 0) { - res = MP_BADARG; - goto CLEANUP; - } else if (i == 1) { - MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry)); - } else { - MP_CHECKOK(mp_copy(&x2, rx)); - MP_CHECKOK(mp_copy(&z2, ry)); - } - - CLEANUP: - mp_clear(&x1); - mp_clear(&x2); - mp_clear(&z1); - mp_clear(&z2); - return res; -} diff --git a/nss/lib/freebl/ecl/ec2_proj.c b/nss/lib/freebl/ecl/ec2_proj.c deleted file mode 100644 index 9378982..0000000 --- a/nss/lib/freebl/ecl/ec2_proj.c +++ /dev/null @@ -1,333 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ec2.h" -#include "mplogic.h" -#include "mp_gf2m.h" -#include <stdlib.h> -#ifdef ECL_DEBUG -#include <assert.h> -#endif - -/* by default, these routines are unused and thus don't need to be compiled */ -#ifdef ECL_ENABLE_GF2M_PROJ -/* Converts a point P(px, py) from affine coordinates to projective - * coordinates R(rx, ry, rz). Assumes input is already field-encoded using - * field_enc, and returns output that is still field-encoded. */ -mp_err -ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, mp_int *rz, const ECGroup *group) -{ - mp_err res = MP_OKAY; - - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - MP_CHECKOK(mp_set_int(rz, 1)); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth)); - } - CLEANUP: - return res; -} - -/* Converts a point P(px, py, pz) from projective coordinates to affine - * coordinates R(rx, ry). P and R can share x and y coordinates. Assumes - * input is already field-encoded using field_enc, and returns output that - * is still field-encoded. */ -mp_err -ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py, const mp_int *pz, - mp_int *rx, mp_int *ry, const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int z1, z2; - - MP_DIGITS(&z1) = 0; - MP_DIGITS(&z2) = 0; - MP_CHECKOK(mp_init(&z1)); - MP_CHECKOK(mp_init(&z2)); - - /* if point at infinity, then set point at infinity and exit */ - if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) { - MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry)); - goto CLEANUP; - } - - /* transform (px, py, pz) into (px / pz, py / pz^2) */ - if (mp_cmp_d(pz, 1) == 0) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - } else { - MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth)); - MP_CHECKOK(group->meth->field_mul(px, &z1, rx, group->meth)); - MP_CHECKOK(group->meth->field_mul(py, &z2, ry, group->meth)); - } - - CLEANUP: - mp_clear(&z1); - mp_clear(&z2); - return res; -} - -/* Checks if point P(px, py, pz) is at infinity. Uses projective - * coordinates. */ -mp_err -ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py, - const mp_int *pz) -{ - return mp_cmp_z(pz); -} - -/* Sets P(px, py, pz) to be the point at infinity. Uses projective - * coordinates. */ -mp_err -ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz) -{ - mp_zero(pz); - return MP_OKAY; -} - -/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is - * (qx, qy, 1). Elliptic curve points P, Q, and R can all be identical. - * Uses mixed projective-affine coordinates. Assumes input is already - * field-encoded using field_enc, and returns output that is still - * field-encoded. Uses equation (3) from Hankerson, Hernandez, Menezes. - * Software Implementation of Elliptic Curve Cryptography Over Binary - * Fields. */ -mp_err -ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py, const mp_int *pz, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, mp_int *rz, const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int A, B, C, D, E, F, G; - - /* If either P or Q is the point at infinity, then return the other - * point */ - if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) { - return ec_GF2m_pt_aff2proj(qx, qy, rx, ry, rz, group); - } - if (ec_GF2m_pt_is_inf_aff(qx, qy) == MP_YES) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - return mp_copy(pz, rz); - } - - MP_DIGITS(&A) = 0; - MP_DIGITS(&B) = 0; - MP_DIGITS(&C) = 0; - MP_DIGITS(&D) = 0; - MP_DIGITS(&E) = 0; - MP_DIGITS(&F) = 0; - MP_DIGITS(&G) = 0; - MP_CHECKOK(mp_init(&A)); - MP_CHECKOK(mp_init(&B)); - MP_CHECKOK(mp_init(&C)); - MP_CHECKOK(mp_init(&D)); - MP_CHECKOK(mp_init(&E)); - MP_CHECKOK(mp_init(&F)); - MP_CHECKOK(mp_init(&G)); - - /* D = pz^2 */ - MP_CHECKOK(group->meth->field_sqr(pz, &D, group->meth)); - - /* A = qy * pz^2 + py */ - MP_CHECKOK(group->meth->field_mul(qy, &D, &A, group->meth)); - MP_CHECKOK(group->meth->field_add(&A, py, &A, group->meth)); - - /* B = qx * pz + px */ - MP_CHECKOK(group->meth->field_mul(qx, pz, &B, group->meth)); - MP_CHECKOK(group->meth->field_add(&B, px, &B, group->meth)); - - /* C = pz * B */ - MP_CHECKOK(group->meth->field_mul(pz, &B, &C, group->meth)); - - /* D = B^2 * (C + a * pz^2) (using E as a temporary variable) */ - MP_CHECKOK(group->meth-> - field_mul(&group->curvea, &D, &D, group->meth)); - MP_CHECKOK(group->meth->field_add(&C, &D, &D, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&B, &E, group->meth)); - MP_CHECKOK(group->meth->field_mul(&E, &D, &D, group->meth)); - - /* rz = C^2 */ - MP_CHECKOK(group->meth->field_sqr(&C, rz, group->meth)); - - /* E = A * C */ - MP_CHECKOK(group->meth->field_mul(&A, &C, &E, group->meth)); - - /* rx = A^2 + D + E */ - MP_CHECKOK(group->meth->field_sqr(&A, rx, group->meth)); - MP_CHECKOK(group->meth->field_add(rx, &D, rx, group->meth)); - MP_CHECKOK(group->meth->field_add(rx, &E, rx, group->meth)); - - /* F = rx + qx * rz */ - MP_CHECKOK(group->meth->field_mul(qx, rz, &F, group->meth)); - MP_CHECKOK(group->meth->field_add(rx, &F, &F, group->meth)); - - /* G = rx + qy * rz */ - MP_CHECKOK(group->meth->field_mul(qy, rz, &G, group->meth)); - MP_CHECKOK(group->meth->field_add(rx, &G, &G, group->meth)); - - /* ry = E * F + rz * G (using G as a temporary variable) */ - MP_CHECKOK(group->meth->field_mul(rz, &G, &G, group->meth)); - MP_CHECKOK(group->meth->field_mul(&E, &F, ry, group->meth)); - MP_CHECKOK(group->meth->field_add(ry, &G, ry, group->meth)); - - CLEANUP: - mp_clear(&A); - mp_clear(&B); - mp_clear(&C); - mp_clear(&D); - mp_clear(&E); - mp_clear(&F); - mp_clear(&G); - return res; -} - -/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses - * projective coordinates. - * - * Assumes input is already field-encoded using field_enc, and returns - * output that is still field-encoded. - * - * Uses equation (3) from Hankerson, Hernandez, Menezes. Software - * Implementation of Elliptic Curve Cryptography Over Binary Fields. - */ -mp_err -ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py, const mp_int *pz, - mp_int *rx, mp_int *ry, mp_int *rz, - const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int t0, t1; - - if (ec_GF2m_pt_is_inf_proj(px, py, pz) == MP_YES) { - return ec_GF2m_pt_set_inf_proj(rx, ry, rz); - } - - MP_DIGITS(&t0) = 0; - MP_DIGITS(&t1) = 0; - MP_CHECKOK(mp_init(&t0)); - MP_CHECKOK(mp_init(&t1)); - - /* t0 = px^2 */ - /* t1 = pz^2 */ - MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth)); - MP_CHECKOK(group->meth->field_sqr(pz, &t1, group->meth)); - - /* rz = px^2 * pz^2 */ - MP_CHECKOK(group->meth->field_mul(&t0, &t1, rz, group->meth)); - - /* t0 = px^4 */ - /* t1 = b * pz^4 */ - MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&t1, &t1, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(&group->curveb, &t1, &t1, group->meth)); - - /* rx = px^4 + b * pz^4 */ - MP_CHECKOK(group->meth->field_add(&t0, &t1, rx, group->meth)); - - /* ry = b * pz^4 * rz + rx * (a * rz + py^2 + b * pz^4) */ - MP_CHECKOK(group->meth->field_sqr(py, ry, group->meth)); - MP_CHECKOK(group->meth->field_add(ry, &t1, ry, group->meth)); - /* t0 = a * rz */ - MP_CHECKOK(group->meth-> - field_mul(&group->curvea, rz, &t0, group->meth)); - MP_CHECKOK(group->meth->field_add(&t0, ry, ry, group->meth)); - MP_CHECKOK(group->meth->field_mul(rx, ry, ry, group->meth)); - /* t1 = b * pz^4 * rz */ - MP_CHECKOK(group->meth->field_mul(&t1, rz, &t1, group->meth)); - MP_CHECKOK(group->meth->field_add(&t1, ry, ry, group->meth)); - - CLEANUP: - mp_clear(&t0); - mp_clear(&t1); - return res; -} - -/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters - * a, b and p are the elliptic curve coefficients and the prime that - * determines the field GF2m. Elliptic curve points P and R can be - * identical. Uses mixed projective-affine coordinates. Assumes input is - * already field-encoded using field_enc, and returns output that is still - * field-encoded. Uses 4-bit window method. */ -mp_err -ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) -{ - mp_err res = MP_OKAY; - mp_int precomp[16][2], rz; - mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 16 * 2], *t; - int i, ni, d; - - ARGCHK(group != NULL, MP_BADARG); - ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); - - /* initialize precomputation table */ - t = precomp_arr; - for (i = 0; i < 16; i++) { - /* x co-ord */ - MP_SIGN(&precomp[i][0]) = MP_ZPOS; - MP_ALLOC(&precomp[i][0]) = ECL_MAX_FIELD_SIZE_DIGITS; - MP_USED(&precomp[i][0]) = 1; - *t = 0; - MP_DIGITS(&precomp[i][0]) = t; - t += ECL_MAX_FIELD_SIZE_DIGITS; - /* y co-ord */ - MP_SIGN(&precomp[i][1]) = MP_ZPOS; - MP_ALLOC(&precomp[i][1]) = ECL_MAX_FIELD_SIZE_DIGITS; - MP_USED(&precomp[i][1]) = 1; - *t = 0; - MP_DIGITS(&precomp[i][1]) = t; - t += ECL_MAX_FIELD_SIZE_DIGITS; - } - - /* fill precomputation table */ - mp_zero(&precomp[0][0]); - mp_zero(&precomp[0][1]); - MP_CHECKOK(mp_copy(px, &precomp[1][0])); - MP_CHECKOK(mp_copy(py, &precomp[1][1])); - for (i = 2; i < 16; i++) { - MP_CHECKOK(group-> - point_add(&precomp[1][0], &precomp[1][1], - &precomp[i - 1][0], &precomp[i - 1][1], - &precomp[i][0], &precomp[i][1], group)); - } - - d = (mpl_significant_bits(n) + 3) / 4; - - /* R = inf */ - MP_DIGITS(&rz) = 0; - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(ec_GF2m_pt_set_inf_proj(rx, ry, &rz)); - - for (i = d - 1; i >= 0; i--) { - /* compute window ni */ - ni = MP_GET_BIT(n, 4 * i + 3); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i + 2); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i + 1); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i); - /* R = 2^4 * R */ - MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GF2m_pt_dbl_proj(rx, ry, &rz, rx, ry, &rz, group)); - /* R = R + (ni * P) */ - MP_CHECKOK(ec_GF2m_pt_add_proj - (rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry, - &rz, group)); - } - - /* convert result S to affine coordinates */ - MP_CHECKOK(ec_GF2m_pt_proj2aff(rx, ry, &rz, rx, ry, group)); - - CLEANUP: - mp_clear(&rz); - return res; -} -#endif diff --git a/nss/lib/freebl/ecl/ec_naf.c b/nss/lib/freebl/ecl/ec_naf.c index 3db6f30..cad08cb 100644 --- a/nss/lib/freebl/ecl/ec_naf.c +++ b/nss/lib/freebl/ecl/ec_naf.c @@ -4,22 +4,22 @@ #include "ecl-priv.h" -/* Returns 2^e as an integer. This is meant to be used for small powers of +/* Returns 2^e as an integer. This is meant to be used for small powers of * two. */ int ec_twoTo(int e) { - int a = 1; - int i; + int a = 1; + int i; - for (i = 0; i < e; i++) { - a *= 2; - } - return a; + for (i = 0; i < e; i++) { + a *= 2; + } + return a; } /* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should - * be an array of signed char's to output to, bitsize should be the number + * be an array of signed char's to output to, bitsize should be the number * of bits of out, in is the original scalar, and w is the window size. * NAF is discussed in the paper: D. Hankerson, J. Hernandez and A. * Menezes, "Software implementation of elliptic curve cryptography over @@ -27,43 +27,42 @@ ec_twoTo(int e) mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in, int w) { - mp_int k; - mp_err res = MP_OKAY; - int i, twowm1, mask; + mp_int k; + mp_err res = MP_OKAY; + int i, twowm1, mask; - twowm1 = ec_twoTo(w - 1); - mask = 2 * twowm1 - 1; + twowm1 = ec_twoTo(w - 1); + mask = 2 * twowm1 - 1; - MP_DIGITS(&k) = 0; - MP_CHECKOK(mp_init_copy(&k, in)); + MP_DIGITS(&k) = 0; + MP_CHECKOK(mp_init_copy(&k, in)); - i = 0; - /* Compute wNAF form */ - while (mp_cmp_z(&k) > 0) { - if (mp_isodd(&k)) { - out[i] = MP_DIGIT(&k, 0) & mask; - if (out[i] >= twowm1) - out[i] -= 2 * twowm1; - - /* Subtract off out[i]. Note mp_sub_d only works with - * unsigned digits */ - if (out[i] >= 0) { - mp_sub_d(&k, out[i], &k); - } else { - mp_add_d(&k, -(out[i]), &k); - } - } else { - out[i] = 0; - } - mp_div_2(&k, &k); - i++; - } - /* Zero out the remaining elements of the out array. */ - for (; i < bitsize + 1; i++) { - out[i] = 0; - } - CLEANUP: - mp_clear(&k); - return res; + i = 0; + /* Compute wNAF form */ + while (mp_cmp_z(&k) > 0) { + if (mp_isodd(&k)) { + out[i] = MP_DIGIT(&k, 0) & mask; + if (out[i] >= twowm1) + out[i] -= 2 * twowm1; + /* Subtract off out[i]. Note mp_sub_d only works with + * unsigned digits */ + if (out[i] >= 0) { + MP_CHECKOK(mp_sub_d(&k, out[i], &k)); + } else { + MP_CHECKOK(mp_add_d(&k, -(out[i]), &k)); + } + } else { + out[i] = 0; + } + MP_CHECKOK(mp_div_2(&k, &k)); + i++; + } + /* Zero out the remaining elements of the out array. */ + for (; i < bitsize + 1; i++) { + out[i] = 0; + } +CLEANUP: + mp_clear(&k); + return res; } diff --git a/nss/lib/freebl/ecl/ecl-curve.h b/nss/lib/freebl/ecl/ecl-curve.h index d81d6df..df06139 100644 --- a/nss/lib/freebl/ecl/ecl-curve.h +++ b/nss/lib/freebl/ecl/ecl-curve.h @@ -8,103 +8,116 @@ #ifndef __ecl_curve_h_ #define __ecl_curve_h_ -#ifdef NSS_ECC_MORE_THAN_SUITE_B -#error This source file is for Basic ECC only . -#endif +/* copied from certt.h */ +#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define KU_KEY_AGREEMENT (0x08) /* bit 4 */ static const ECCurveParams ecCurve_NIST_P256 = { - "NIST-P256", ECField_GFp, 256, - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1 + "NIST-P256", ECField_GFp, 256, + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", + 1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT }; static const ECCurveParams ecCurve_NIST_P384 = { - "NIST-P384", ECField_GFp, 384, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", - "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", - "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", - "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", - 1 + "NIST-P384", ECField_GFp, 384, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT }; static const ECCurveParams ecCurve_NIST_P521 = { - "NIST-P521", ECField_GFp, 521, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", - "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", - "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", - "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - 1 + "NIST-P521", ECField_GFp, 521, + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT +}; + +static const ECCurveParams ecCurve25519 = { + "Curve25519", ECField_GFp, 255, + "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed", + "076D06", + "00", + "0900000000000000000000000000000000000000000000000000000000000000", + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9", + "1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed", + 8, 128, 32, KU_KEY_AGREEMENT }; /* mapping between ECCurveName enum and pointers to ECCurveParams */ static const ECCurveParams *ecCurve_map[] = { - NULL, /* ECCurve_noName */ - NULL, /* ECCurve_NIST_P192 */ - NULL, /* ECCurve_NIST_P224 */ - &ecCurve_NIST_P256, /* ECCurve_NIST_P256 */ - &ecCurve_NIST_P384, /* ECCurve_NIST_P384 */ - &ecCurve_NIST_P521, /* ECCurve_NIST_P521 */ - NULL, /* ECCurve_NIST_K163 */ - NULL, /* ECCurve_NIST_B163 */ - NULL, /* ECCurve_NIST_K233 */ - NULL, /* ECCurve_NIST_B233 */ - NULL, /* ECCurve_NIST_K283 */ - NULL, /* ECCurve_NIST_B283 */ - NULL, /* ECCurve_NIST_K409 */ - NULL, /* ECCurve_NIST_B409 */ - NULL, /* ECCurve_NIST_K571 */ - NULL, /* ECCurve_NIST_B571 */ - NULL, /* ECCurve_X9_62_PRIME_192V2 */ - NULL, /* ECCurve_X9_62_PRIME_192V3 */ - NULL, /* ECCurve_X9_62_PRIME_239V1 */ - NULL, /* ECCurve_X9_62_PRIME_239V2 */ - NULL, /* ECCurve_X9_62_PRIME_239V3 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB163V1 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB163V2 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB163V3 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB176V1 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB191V1 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB191V2 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB191V3 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB208W1 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB239V1 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB239V2 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB239V3 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB272W1 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB304W1 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB359V1 */ - NULL, /* ECCurve_X9_62_CHAR2_PNB368W1 */ - NULL, /* ECCurve_X9_62_CHAR2_TNB431R1 */ - NULL, /* ECCurve_SECG_PRIME_112R1 */ - NULL, /* ECCurve_SECG_PRIME_112R2 */ - NULL, /* ECCurve_SECG_PRIME_128R1 */ - NULL, /* ECCurve_SECG_PRIME_128R2 */ - NULL, /* ECCurve_SECG_PRIME_160K1 */ - NULL, /* ECCurve_SECG_PRIME_160R1 */ - NULL, /* ECCurve_SECG_PRIME_160R2 */ - NULL, /* ECCurve_SECG_PRIME_192K1 */ - NULL, /* ECCurve_SECG_PRIME_224K1 */ - NULL, /* ECCurve_SECG_PRIME_256K1 */ - NULL, /* ECCurve_SECG_CHAR2_113R1 */ - NULL, /* ECCurve_SECG_CHAR2_113R2 */ - NULL, /* ECCurve_SECG_CHAR2_131R1 */ - NULL, /* ECCurve_SECG_CHAR2_131R2 */ - NULL, /* ECCurve_SECG_CHAR2_163R1 */ - NULL, /* ECCurve_SECG_CHAR2_193R1 */ - NULL, /* ECCurve_SECG_CHAR2_193R2 */ - NULL, /* ECCurve_SECG_CHAR2_239K1 */ - NULL, /* ECCurve_WTLS_1 */ - NULL, /* ECCurve_WTLS_8 */ - NULL, /* ECCurve_WTLS_9 */ - NULL /* ECCurve_pastLastCurve */ + NULL, /* ECCurve_noName */ + NULL, /* ECCurve_NIST_P192 */ + NULL, /* ECCurve_NIST_P224 */ + &ecCurve_NIST_P256, /* ECCurve_NIST_P256 */ + &ecCurve_NIST_P384, /* ECCurve_NIST_P384 */ + &ecCurve_NIST_P521, /* ECCurve_NIST_P521 */ + NULL, /* ECCurve_NIST_K163 */ + NULL, /* ECCurve_NIST_B163 */ + NULL, /* ECCurve_NIST_K233 */ + NULL, /* ECCurve_NIST_B233 */ + NULL, /* ECCurve_NIST_K283 */ + NULL, /* ECCurve_NIST_B283 */ + NULL, /* ECCurve_NIST_K409 */ + NULL, /* ECCurve_NIST_B409 */ + NULL, /* ECCurve_NIST_K571 */ + NULL, /* ECCurve_NIST_B571 */ + NULL, /* ECCurve_X9_62_PRIME_192V2 */ + NULL, /* ECCurve_X9_62_PRIME_192V3 */ + NULL, /* ECCurve_X9_62_PRIME_239V1 */ + NULL, /* ECCurve_X9_62_PRIME_239V2 */ + NULL, /* ECCurve_X9_62_PRIME_239V3 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB163V1 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB163V2 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB163V3 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB176V1 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB191V1 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB191V2 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB191V3 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB208W1 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB239V1 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB239V2 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB239V3 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB272W1 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB304W1 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB359V1 */ + NULL, /* ECCurve_X9_62_CHAR2_PNB368W1 */ + NULL, /* ECCurve_X9_62_CHAR2_TNB431R1 */ + NULL, /* ECCurve_SECG_PRIME_112R1 */ + NULL, /* ECCurve_SECG_PRIME_112R2 */ + NULL, /* ECCurve_SECG_PRIME_128R1 */ + NULL, /* ECCurve_SECG_PRIME_128R2 */ + NULL, /* ECCurve_SECG_PRIME_160K1 */ + NULL, /* ECCurve_SECG_PRIME_160R1 */ + NULL, /* ECCurve_SECG_PRIME_160R2 */ + NULL, /* ECCurve_SECG_PRIME_192K1 */ + NULL, /* ECCurve_SECG_PRIME_224K1 */ + NULL, /* ECCurve_SECG_PRIME_256K1 */ + NULL, /* ECCurve_SECG_CHAR2_113R1 */ + NULL, /* ECCurve_SECG_CHAR2_113R2 */ + NULL, /* ECCurve_SECG_CHAR2_131R1 */ + NULL, /* ECCurve_SECG_CHAR2_131R2 */ + NULL, /* ECCurve_SECG_CHAR2_163R1 */ + NULL, /* ECCurve_SECG_CHAR2_193R1 */ + NULL, /* ECCurve_SECG_CHAR2_193R2 */ + NULL, /* ECCurve_SECG_CHAR2_239K1 */ + NULL, /* ECCurve_WTLS_1 */ + NULL, /* ECCurve_WTLS_8 */ + NULL, /* ECCurve_WTLS_9 */ + &ecCurve25519, /* ECCurve25519 */ + NULL /* ECCurve_pastLastCurve */ }; #endif diff --git a/nss/lib/freebl/ecl/ecl-exp.h b/nss/lib/freebl/ecl/ecl-exp.h index b79eb30..44adb8a 100644 --- a/nss/lib/freebl/ecl/ecl-exp.h +++ b/nss/lib/freebl/ecl/ecl-exp.h @@ -7,156 +7,161 @@ /* Curve field type */ typedef enum { - ECField_GFp, - ECField_GF2m + ECField_GFp, + ECField_GF2m } ECField; /* Hexadecimal encoding of curve parameters */ struct ECCurveParamsStr { - char *text; - ECField field; - unsigned int size; - char *irr; - char *curvea; - char *curveb; - char *genx; - char *geny; - char *order; - int cofactor; + char *text; + ECField field; + unsigned int size; + char *irr; + char *curvea; + char *curveb; + char *genx; + char *geny; + char *order; + int cofactor; + int security; + int pointSize; + unsigned int usage; }; typedef struct ECCurveParamsStr ECCurveParams; /* Named curve parameters */ typedef enum { - ECCurve_noName = 0, - - /* NIST prime curves */ - ECCurve_NIST_P192, - ECCurve_NIST_P224, - ECCurve_NIST_P256, - ECCurve_NIST_P384, - ECCurve_NIST_P521, - - /* NIST binary curves */ - ECCurve_NIST_K163, - ECCurve_NIST_B163, - ECCurve_NIST_K233, - ECCurve_NIST_B233, - ECCurve_NIST_K283, - ECCurve_NIST_B283, - ECCurve_NIST_K409, - ECCurve_NIST_B409, - ECCurve_NIST_K571, - ECCurve_NIST_B571, - - /* ANSI X9.62 prime curves */ - /* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */ - ECCurve_X9_62_PRIME_192V2, - ECCurve_X9_62_PRIME_192V3, - ECCurve_X9_62_PRIME_239V1, - ECCurve_X9_62_PRIME_239V2, - ECCurve_X9_62_PRIME_239V3, - /* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */ - - /* ANSI X9.62 binary curves */ - ECCurve_X9_62_CHAR2_PNB163V1, - ECCurve_X9_62_CHAR2_PNB163V2, - ECCurve_X9_62_CHAR2_PNB163V3, - ECCurve_X9_62_CHAR2_PNB176V1, - ECCurve_X9_62_CHAR2_TNB191V1, - ECCurve_X9_62_CHAR2_TNB191V2, - ECCurve_X9_62_CHAR2_TNB191V3, - ECCurve_X9_62_CHAR2_PNB208W1, - ECCurve_X9_62_CHAR2_TNB239V1, - ECCurve_X9_62_CHAR2_TNB239V2, - ECCurve_X9_62_CHAR2_TNB239V3, - ECCurve_X9_62_CHAR2_PNB272W1, - ECCurve_X9_62_CHAR2_PNB304W1, - ECCurve_X9_62_CHAR2_TNB359V1, - ECCurve_X9_62_CHAR2_PNB368W1, - ECCurve_X9_62_CHAR2_TNB431R1, - - /* SEC2 prime curves */ - ECCurve_SECG_PRIME_112R1, - ECCurve_SECG_PRIME_112R2, - ECCurve_SECG_PRIME_128R1, - ECCurve_SECG_PRIME_128R2, - ECCurve_SECG_PRIME_160K1, - ECCurve_SECG_PRIME_160R1, - ECCurve_SECG_PRIME_160R2, - ECCurve_SECG_PRIME_192K1, - /* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */ - ECCurve_SECG_PRIME_224K1, - /* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */ - ECCurve_SECG_PRIME_256K1, - /* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */ - /* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */ - /* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */ - - /* SEC2 binary curves */ - ECCurve_SECG_CHAR2_113R1, - ECCurve_SECG_CHAR2_113R2, - ECCurve_SECG_CHAR2_131R1, - ECCurve_SECG_CHAR2_131R2, - /* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */ - ECCurve_SECG_CHAR2_163R1, - /* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */ - ECCurve_SECG_CHAR2_193R1, - ECCurve_SECG_CHAR2_193R2, - /* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */ - /* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */ - ECCurve_SECG_CHAR2_239K1, - /* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */ - /* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */ - /* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */ - /* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */ - /* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */ - /* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */ - - /* WTLS curves */ - ECCurve_WTLS_1, - /* there is no WTLS 2 curve */ - /* ECCurve_WTLS_3 == ECCurve_NIST_K163 */ - /* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */ - /* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */ - /* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */ - /* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */ - ECCurve_WTLS_8, - ECCurve_WTLS_9, - /* ECCurve_WTLS_10 == ECCurve_NIST_K233 */ - /* ECCurve_WTLS_11 == ECCurve_NIST_B233 */ - /* ECCurve_WTLS_12 == ECCurve_NIST_P224 */ - - ECCurve_pastLastCurve + ECCurve_noName = 0, + + /* NIST prime curves */ + ECCurve_NIST_P192, /* not supported */ + ECCurve_NIST_P224, /* not supported */ + ECCurve_NIST_P256, + ECCurve_NIST_P384, + ECCurve_NIST_P521, + + /* NIST binary curves */ + ECCurve_NIST_K163, /* not supported */ + ECCurve_NIST_B163, /* not supported */ + ECCurve_NIST_K233, /* not supported */ + ECCurve_NIST_B233, /* not supported */ + ECCurve_NIST_K283, /* not supported */ + ECCurve_NIST_B283, /* not supported */ + ECCurve_NIST_K409, /* not supported */ + ECCurve_NIST_B409, /* not supported */ + ECCurve_NIST_K571, /* not supported */ + ECCurve_NIST_B571, /* not supported */ + + /* ANSI X9.62 prime curves */ + /* ECCurve_X9_62_PRIME_192V1 == ECCurve_NIST_P192 */ + ECCurve_X9_62_PRIME_192V2, /* not supported */ + ECCurve_X9_62_PRIME_192V3, /* not supported */ + ECCurve_X9_62_PRIME_239V1, /* not supported */ + ECCurve_X9_62_PRIME_239V2, /* not supported */ + ECCurve_X9_62_PRIME_239V3, /* not supported */ + /* ECCurve_X9_62_PRIME_256V1 == ECCurve_NIST_P256 */ + + /* ANSI X9.62 binary curves */ + ECCurve_X9_62_CHAR2_PNB163V1, /* not supported */ + ECCurve_X9_62_CHAR2_PNB163V2, /* not supported */ + ECCurve_X9_62_CHAR2_PNB163V3, /* not supported */ + ECCurve_X9_62_CHAR2_PNB176V1, /* not supported */ + ECCurve_X9_62_CHAR2_TNB191V1, /* not supported */ + ECCurve_X9_62_CHAR2_TNB191V2, /* not supported */ + ECCurve_X9_62_CHAR2_TNB191V3, /* not supported */ + ECCurve_X9_62_CHAR2_PNB208W1, /* not supported */ + ECCurve_X9_62_CHAR2_TNB239V1, /* not supported */ + ECCurve_X9_62_CHAR2_TNB239V2, /* not supported */ + ECCurve_X9_62_CHAR2_TNB239V3, /* not supported */ + ECCurve_X9_62_CHAR2_PNB272W1, /* not supported */ + ECCurve_X9_62_CHAR2_PNB304W1, /* not supported */ + ECCurve_X9_62_CHAR2_TNB359V1, /* not supported */ + ECCurve_X9_62_CHAR2_PNB368W1, /* not supported */ + ECCurve_X9_62_CHAR2_TNB431R1, /* not supported */ + + /* SEC2 prime curves */ + ECCurve_SECG_PRIME_112R1, /* not supported */ + ECCurve_SECG_PRIME_112R2, /* not supported */ + ECCurve_SECG_PRIME_128R1, /* not supported */ + ECCurve_SECG_PRIME_128R2, /* not supported */ + ECCurve_SECG_PRIME_160K1, /* not supported */ + ECCurve_SECG_PRIME_160R1, /* not supported */ + ECCurve_SECG_PRIME_160R2, /* not supported */ + ECCurve_SECG_PRIME_192K1, /* not supported */ + /* ECCurve_SECG_PRIME_192R1 == ECCurve_NIST_P192 */ + ECCurve_SECG_PRIME_224K1, /* not supported */ + /* ECCurve_SECG_PRIME_224R1 == ECCurve_NIST_P224 */ + ECCurve_SECG_PRIME_256K1, /* not supported */ + /* ECCurve_SECG_PRIME_256R1 == ECCurve_NIST_P256 */ + /* ECCurve_SECG_PRIME_384R1 == ECCurve_NIST_P384 */ + /* ECCurve_SECG_PRIME_521R1 == ECCurve_NIST_P521 */ + + /* SEC2 binary curves */ + ECCurve_SECG_CHAR2_113R1, /* not supported */ + ECCurve_SECG_CHAR2_113R2, /* not supported */ + ECCurve_SECG_CHAR2_131R1, /* not supported */ + ECCurve_SECG_CHAR2_131R2, /* not supported */ + /* ECCurve_SECG_CHAR2_163K1 == ECCurve_NIST_K163 */ + ECCurve_SECG_CHAR2_163R1, /* not supported */ + /* ECCurve_SECG_CHAR2_163R2 == ECCurve_NIST_B163 */ + ECCurve_SECG_CHAR2_193R1, /* not supported */ + ECCurve_SECG_CHAR2_193R2, /* not supported */ + /* ECCurve_SECG_CHAR2_233K1 == ECCurve_NIST_K233 */ + /* ECCurve_SECG_CHAR2_233R1 == ECCurve_NIST_B233 */ + ECCurve_SECG_CHAR2_239K1, /* not supported */ + /* ECCurve_SECG_CHAR2_283K1 == ECCurve_NIST_K283 */ + /* ECCurve_SECG_CHAR2_283R1 == ECCurve_NIST_B283 */ + /* ECCurve_SECG_CHAR2_409K1 == ECCurve_NIST_K409 */ + /* ECCurve_SECG_CHAR2_409R1 == ECCurve_NIST_B409 */ + /* ECCurve_SECG_CHAR2_571K1 == ECCurve_NIST_K571 */ + /* ECCurve_SECG_CHAR2_571R1 == ECCurve_NIST_B571 */ + + /* WTLS curves */ + ECCurve_WTLS_1, /* not supported */ + /* there is no WTLS 2 curve */ + /* ECCurve_WTLS_3 == ECCurve_NIST_K163 */ + /* ECCurve_WTLS_4 == ECCurve_SECG_CHAR2_113R1 */ + /* ECCurve_WTLS_5 == ECCurve_X9_62_CHAR2_PNB163V1 */ + /* ECCurve_WTLS_6 == ECCurve_SECG_PRIME_112R1 */ + /* ECCurve_WTLS_7 == ECCurve_SECG_PRIME_160R1 */ + ECCurve_WTLS_8, /* not supported */ + ECCurve_WTLS_9, /* not supported */ + /* ECCurve_WTLS_10 == ECCurve_NIST_K233 */ + /* ECCurve_WTLS_11 == ECCurve_NIST_B233 */ + /* ECCurve_WTLS_12 == ECCurve_NIST_P224 */ + + ECCurve25519, + + ECCurve_pastLastCurve } ECCurveName; /* Aliased named curves */ -#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192 +#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192 /* not supported */ #define ECCurve_X9_62_PRIME_256V1 ECCurve_NIST_P256 -#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192 -#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224 +#define ECCurve_SECG_PRIME_192R1 ECCurve_NIST_P192 /* not supported */ +#define ECCurve_SECG_PRIME_224R1 ECCurve_NIST_P224 /* not supported */ #define ECCurve_SECG_PRIME_256R1 ECCurve_NIST_P256 #define ECCurve_SECG_PRIME_384R1 ECCurve_NIST_P384 #define ECCurve_SECG_PRIME_521R1 ECCurve_NIST_P521 -#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163 -#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163 -#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233 -#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233 -#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283 -#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283 -#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409 -#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409 -#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571 -#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571 -#define ECCurve_WTLS_3 ECCurve_NIST_K163 -#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1 -#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1 -#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1 -#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1 -#define ECCurve_WTLS_10 ECCurve_NIST_K233 -#define ECCurve_WTLS_11 ECCurve_NIST_B233 -#define ECCurve_WTLS_12 ECCurve_NIST_P224 - -#endif /* __ecl_exp_h_ */ +#define ECCurve_SECG_CHAR2_163K1 ECCurve_NIST_K163 /* not supported */ +#define ECCurve_SECG_CHAR2_163R2 ECCurve_NIST_B163 /* not supported */ +#define ECCurve_SECG_CHAR2_233K1 ECCurve_NIST_K233 /* not supported */ +#define ECCurve_SECG_CHAR2_233R1 ECCurve_NIST_B233 /* not supported */ +#define ECCurve_SECG_CHAR2_283K1 ECCurve_NIST_K283 /* not supported */ +#define ECCurve_SECG_CHAR2_283R1 ECCurve_NIST_B283 /* not supported */ +#define ECCurve_SECG_CHAR2_409K1 ECCurve_NIST_K409 /* not supported */ +#define ECCurve_SECG_CHAR2_409R1 ECCurve_NIST_B409 /* not supported */ +#define ECCurve_SECG_CHAR2_571K1 ECCurve_NIST_K571 /* not supported */ +#define ECCurve_SECG_CHAR2_571R1 ECCurve_NIST_B571 /* not supported */ +#define ECCurve_WTLS_3 ECCurve_NIST_K163 /* not supported */ +#define ECCurve_WTLS_4 ECCurve_SECG_CHAR2_113R1 /* not supported */ +#define ECCurve_WTLS_5 ECCurve_X9_62_CHAR2_PNB163V1 /* not supported */ +#define ECCurve_WTLS_6 ECCurve_SECG_PRIME_112R1 /* not supported */ +#define ECCurve_WTLS_7 ECCurve_SECG_PRIME_160R1 /* not supported */ +#define ECCurve_WTLS_10 ECCurve_NIST_K233 /* not supported */ +#define ECCurve_WTLS_11 ECCurve_NIST_B233 /* not supported */ +#define ECCurve_WTLS_12 ECCurve_NIST_P224 /* not supported */ + +#endif /* __ecl_exp_h_ */ diff --git a/nss/lib/freebl/ecl/ecl-priv.h b/nss/lib/freebl/ecl/ecl-priv.h index 16f80a4..f43f193 100644 --- a/nss/lib/freebl/ecl/ecl-priv.h +++ b/nss/lib/freebl/ecl/ecl-priv.h @@ -8,6 +8,7 @@ #include "ecl.h" #include "mpi.h" #include "mplogic.h" +#include "../blapii.h" /* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */ /* the following needs to go away... */ @@ -18,212 +19,219 @@ #endif #define ECL_CURVE_DIGITS(curve_size_in_bits) \ - (((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8)) -#define ECL_BITS (sizeof(mp_digit)*8) -#define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit)) + (((curve_size_in_bits) + (sizeof(mp_digit) * 8 - 1)) / (sizeof(mp_digit) * 8)) +#define ECL_BITS (sizeof(mp_digit) * 8) +#define ECL_MAX_FIELD_SIZE_DIGITS (80 / sizeof(mp_digit)) -/* Gets the i'th bit in the binary representation of a. If i >= length(a), +/* Gets the i'th bit in the binary representation of a. If i >= length(a), * then return 0. (The above behaviour differs from mpl_get_bit, which * causes an error if i >= length(a).) */ #define MP_GET_BIT(a, i) \ - ((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i)) + ((i) >= mpl_significant_bits((a))) ? 0 : mpl_get_bit((a), (i)) #if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD) -#define MP_ADD_CARRY(a1, a2, s, carry) \ - { mp_word w; \ - w = ((mp_word)carry) + (a1) + (a2); \ - s = ACCUM(w); \ - carry = CARRYOUT(w); } +#define MP_ADD_CARRY(a1, a2, s, carry) \ + { \ + mp_word w; \ + w = ((mp_word)carry) + (a1) + (a2); \ + s = ACCUM(w); \ + carry = CARRYOUT(w); \ + } #define MP_SUB_BORROW(a1, a2, s, borrow) \ - { mp_word w; \ - w = ((mp_word)(a1)) - (a2) - borrow; \ - s = ACCUM(w); \ - borrow = (w >> MP_DIGIT_BIT) & 1; } + { \ + mp_word w; \ + w = ((mp_word)(a1)) - (a2)-borrow; \ + s = ACCUM(w); \ + borrow = (w >> MP_DIGIT_BIT) & 1; \ + } #else -/* NOTE, +/* NOTE, * carry and borrow are both read and written. * a1 or a2 and s could be the same variable. * don't trash those outputs until their respective inputs have * been read. */ -#define MP_ADD_CARRY(a1, a2, s, carry) \ - { mp_digit tmp,sum; \ - tmp = (a1); \ - sum = tmp + (a2); \ - tmp = (sum < tmp); /* detect overflow */ \ - s = sum += carry; \ - carry = tmp + (sum < carry); } +#define MP_ADD_CARRY(a1, a2, s, carry) \ + { \ + mp_digit tmp, sum; \ + tmp = (a1); \ + sum = tmp + (a2); \ + tmp = (sum < tmp); /* detect overflow */ \ + s = sum += carry; \ + carry = tmp + (sum < carry); \ + } -#define MP_SUB_BORROW(a1, a2, s, borrow) \ - { mp_digit tmp; \ - tmp = (a1); \ - s = tmp - (a2); \ - tmp = (s > tmp); /* detect borrow */ \ - if (borrow && !s--) tmp++; \ - borrow = tmp; } +#define MP_SUB_BORROW(a1, a2, s, borrow) \ + { \ + mp_digit tmp; \ + tmp = (a1); \ + s = tmp - (a2); \ + tmp = (s > tmp); /* detect borrow */ \ + if (borrow && !s--) \ + tmp++; \ + borrow = tmp; \ + } #endif - struct GFMethodStr; typedef struct GFMethodStr GFMethod; struct GFMethodStr { - /* Indicates whether the structure was constructed from dynamic memory - * or statically created. */ - int constructed; - /* Irreducible that defines the field. For prime fields, this is the - * prime p. For binary polynomial fields, this is the bitstring - * representation of the irreducible polynomial. */ - mp_int irr; - /* For prime fields, the value irr_arr[0] is the number of bits in the - * field. For binary polynomial fields, the irreducible polynomial - * f(t) is represented as an array of unsigned int[], where f(t) is - * of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0] - * > p[1] > ... > p[4] = 0. */ - unsigned int irr_arr[5]; - /* Field arithmetic methods. All methods (except field_enc and - * field_dec) are assumed to take field-encoded parameters and return - * field-encoded values. All methods (except field_enc and field_dec) - * are required to be implemented. */ - mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); - mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth); - mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); - mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth); - mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); - mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth); - mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); - mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth); - mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth); - /* Extra storage for implementation-specific data. Any memory - * allocated to these extra fields will be cleared by extra_free. */ - void *extra1; - void *extra2; - void (*extra_free) (GFMethod *meth); + /* Indicates whether the structure was constructed from dynamic memory + * or statically created. */ + int constructed; + /* Irreducible that defines the field. For prime fields, this is the + * prime p. For binary polynomial fields, this is the bitstring + * representation of the irreducible polynomial. */ + mp_int irr; + /* For prime fields, the value irr_arr[0] is the number of bits in the + * field. For binary polynomial fields, the irreducible polynomial + * f(t) is represented as an array of unsigned int[], where f(t) is + * of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0] + * > p[1] > ... > p[4] = 0. */ + unsigned int irr_arr[5]; + /* Field arithmetic methods. All methods (except field_enc and + * field_dec) are assumed to take field-encoded parameters and return + * field-encoded values. All methods (except field_enc and field_dec) + * are required to be implemented. */ + mp_err (*field_add)(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth); + mp_err (*field_neg)(const mp_int *a, mp_int *r, const GFMethod *meth); + mp_err (*field_sub)(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth); + mp_err (*field_mod)(const mp_int *a, mp_int *r, const GFMethod *meth); + mp_err (*field_mul)(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth); + mp_err (*field_sqr)(const mp_int *a, mp_int *r, const GFMethod *meth); + mp_err (*field_div)(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth); + mp_err (*field_enc)(const mp_int *a, mp_int *r, const GFMethod *meth); + mp_err (*field_dec)(const mp_int *a, mp_int *r, const GFMethod *meth); + /* Extra storage for implementation-specific data. Any memory + * allocated to these extra fields will be cleared by extra_free. */ + void *extra1; + void *extra2; + void (*extra_free)(GFMethod *meth); }; /* Construct generic GFMethods. */ GFMethod *GFMethod_consGFp(const mp_int *irr); GFMethod *GFMethod_consGFp_mont(const mp_int *irr); -GFMethod *GFMethod_consGF2m(const mp_int *irr, - const unsigned int irr_arr[5]); + /* Free the memory allocated (if any) to a GFMethod object. */ void GFMethod_free(GFMethod *meth); struct ECGroupStr { - /* Indicates whether the structure was constructed from dynamic memory - * or statically created. */ - int constructed; - /* Field definition and arithmetic. */ - GFMethod *meth; - /* Textual representation of curve name, if any. */ - char *text; - /* Curve parameters, field-encoded. */ - mp_int curvea, curveb; - /* x and y coordinates of the base point, field-encoded. */ - mp_int genx, geny; - /* Order and cofactor of the base point. */ - mp_int order; - int cofactor; - /* Point arithmetic methods. All methods are assumed to take - * field-encoded parameters and return field-encoded values. All - * methods (except base_point_mul and points_mul) are required to be - * implemented. */ - mp_err (*point_add) (const mp_int *px, const mp_int *py, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, const ECGroup *group); - mp_err (*point_sub) (const mp_int *px, const mp_int *py, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, const ECGroup *group); - mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); - mp_err (*point_mul) (const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); - mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry, - const ECGroup *group); - mp_err (*points_mul) (const mp_int *k1, const mp_int *k2, - const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); - mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group); - /* Extra storage for implementation-specific data. Any memory - * allocated to these extra fields will be cleared by extra_free. */ - void *extra1; - void *extra2; - void (*extra_free) (ECGroup *group); + /* Indicates whether the structure was constructed from dynamic memory + * or statically created. */ + int constructed; + /* Field definition and arithmetic. */ + GFMethod *meth; + /* Textual representation of curve name, if any. */ + char *text; + /* Curve parameters, field-encoded. */ + mp_int curvea, curveb; + /* x and y coordinates of the base point, field-encoded. */ + mp_int genx, geny; + /* Order and cofactor of the base point. */ + mp_int order; + int cofactor; + /* Point arithmetic methods. All methods are assumed to take + * field-encoded parameters and return field-encoded values. All + * methods (except base_point_mul and points_mul) are required to be + * implemented. */ + mp_err (*point_add)(const mp_int *px, const mp_int *py, + const mp_int *qx, const mp_int *qy, mp_int *rx, + mp_int *ry, const ECGroup *group); + mp_err (*point_sub)(const mp_int *px, const mp_int *py, + const mp_int *qx, const mp_int *qy, mp_int *rx, + mp_int *ry, const ECGroup *group); + mp_err (*point_dbl)(const mp_int *px, const mp_int *py, mp_int *rx, + mp_int *ry, const ECGroup *group); + mp_err (*point_mul)(const mp_int *n, const mp_int *px, + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group); + mp_err (*base_point_mul)(const mp_int *n, mp_int *rx, mp_int *ry, + const ECGroup *group); + mp_err (*points_mul)(const mp_int *k1, const mp_int *k2, + const mp_int *px, const mp_int *py, mp_int *rx, + mp_int *ry, const ECGroup *group); + mp_err (*validate_point)(const mp_int *px, const mp_int *py, const ECGroup *group); + /* Extra storage for implementation-specific data. Any memory + * allocated to these extra fields will be cleared by extra_free. */ + void *extra1; + void *extra2; + void (*extra_free)(ECGroup *group); }; /* Wrapper functions for generic prime field arithmetic. */ mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); /* fixed length in-line adds. Count is in words */ mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); /* Wrapper functions for generic binary polynomial field arithmetic. */ mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); /* Montgomery prime field arithmetic. */ mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth); + const GFMethod *meth); mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth); mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth); void ec_GFp_extra_free_mont(GFMethod *meth); /* point multiplication */ mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, - const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); + const mp_int *px, const mp_int *py, mp_int *rx, + mp_int *ry, const ECGroup *group); mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, - const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); + const mp_int *px, const mp_int *py, mp_int *rx, + mp_int *ry, const ECGroup *group); /* Computes the windowed non-adjacent-form (NAF) of a scalar. Out should - * be an array of signed char's to output to, bitsize should be the number + * be an array of signed char's to output to, bitsize should be the number * of bits of out, in is the original scalar, and w is the window size. * NAF is discussed in the paper: D. Hankerson, J. Hernandez and A. * Menezes, "Software implementation of elliptic curve cryptography over * binary fields", Proc. CHES 2000. */ mp_err ec_compute_wNAF(signed char *out, int bitsize, const mp_int *in, - int w); + int w); /* Optimized field arithmetic */ mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName); @@ -245,4 +253,5 @@ mp_err ec_group_set_nistp192_fp(ECGroup *group); mp_err ec_group_set_nistp224_fp(ECGroup *group); #endif -#endif /* __ecl_priv_h_ */ +SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p); +#endif /* __ecl_priv_h_ */ diff --git a/nss/lib/freebl/ecl/ecl.c b/nss/lib/freebl/ecl/ecl.c index d55e593..3540af7 100644 --- a/nss/lib/freebl/ecl/ecl.c +++ b/nss/lib/freebl/ecl/ecl.c @@ -6,7 +6,6 @@ #include "mplogic.h" #include "ecl.h" #include "ecl-priv.h" -#include "ec2.h" #include "ecp.h" #include <stdlib.h> #include <string.h> @@ -15,382 +14,288 @@ ECGroup * ECGroup_new() { - mp_err res = MP_OKAY; - ECGroup *group; - group = (ECGroup *) malloc(sizeof(ECGroup)); - if (group == NULL) - return NULL; - group->constructed = MP_YES; - group->meth = NULL; - group->text = NULL; - MP_DIGITS(&group->curvea) = 0; - MP_DIGITS(&group->curveb) = 0; - MP_DIGITS(&group->genx) = 0; - MP_DIGITS(&group->geny) = 0; - MP_DIGITS(&group->order) = 0; - group->base_point_mul = NULL; - group->points_mul = NULL; - group->validate_point = NULL; - group->extra1 = NULL; - group->extra2 = NULL; - group->extra_free = NULL; - MP_CHECKOK(mp_init(&group->curvea)); - MP_CHECKOK(mp_init(&group->curveb)); - MP_CHECKOK(mp_init(&group->genx)); - MP_CHECKOK(mp_init(&group->geny)); - MP_CHECKOK(mp_init(&group->order)); + mp_err res = MP_OKAY; + ECGroup *group; + group = (ECGroup *)malloc(sizeof(ECGroup)); + if (group == NULL) + return NULL; + group->constructed = MP_YES; + group->meth = NULL; + group->text = NULL; + MP_DIGITS(&group->curvea) = 0; + MP_DIGITS(&group->curveb) = 0; + MP_DIGITS(&group->genx) = 0; + MP_DIGITS(&group->geny) = 0; + MP_DIGITS(&group->order) = 0; + group->base_point_mul = NULL; + group->points_mul = NULL; + group->validate_point = NULL; + group->extra1 = NULL; + group->extra2 = NULL; + group->extra_free = NULL; + MP_CHECKOK(mp_init(&group->curvea)); + MP_CHECKOK(mp_init(&group->curveb)); + MP_CHECKOK(mp_init(&group->genx)); + MP_CHECKOK(mp_init(&group->geny)); + MP_CHECKOK(mp_init(&group->order)); - CLEANUP: - if (res != MP_OKAY) { - ECGroup_free(group); - return NULL; - } - return group; +CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; } /* Construct a generic ECGroup for elliptic curves over prime fields. */ ECGroup * ECGroup_consGFp(const mp_int *irr, const mp_int *curvea, - const mp_int *curveb, const mp_int *genx, - const mp_int *geny, const mp_int *order, int cofactor) + const mp_int *curveb, const mp_int *genx, + const mp_int *geny, const mp_int *order, int cofactor) { - mp_err res = MP_OKAY; - ECGroup *group = NULL; + mp_err res = MP_OKAY; + ECGroup *group = NULL; - group = ECGroup_new(); - if (group == NULL) - return NULL; + group = ECGroup_new(); + if (group == NULL) + return NULL; - group->meth = GFMethod_consGFp(irr); - if (group->meth == NULL) { - res = MP_MEM; - goto CLEANUP; - } - MP_CHECKOK(mp_copy(curvea, &group->curvea)); - MP_CHECKOK(mp_copy(curveb, &group->curveb)); - MP_CHECKOK(mp_copy(genx, &group->genx)); - MP_CHECKOK(mp_copy(geny, &group->geny)); - MP_CHECKOK(mp_copy(order, &group->order)); - group->cofactor = cofactor; - group->point_add = &ec_GFp_pt_add_aff; - group->point_sub = &ec_GFp_pt_sub_aff; - group->point_dbl = &ec_GFp_pt_dbl_aff; - group->point_mul = &ec_GFp_pt_mul_jm_wNAF; - group->base_point_mul = NULL; - group->points_mul = &ec_GFp_pts_mul_jac; - group->validate_point = &ec_GFp_validate_point; + group->meth = GFMethod_consGFp(irr); + if (group->meth == NULL) { + res = MP_MEM; + goto CLEANUP; + } + MP_CHECKOK(mp_copy(curvea, &group->curvea)); + MP_CHECKOK(mp_copy(curveb, &group->curveb)); + MP_CHECKOK(mp_copy(genx, &group->genx)); + MP_CHECKOK(mp_copy(geny, &group->geny)); + MP_CHECKOK(mp_copy(order, &group->order)); + group->cofactor = cofactor; + group->point_add = &ec_GFp_pt_add_aff; + group->point_sub = &ec_GFp_pt_sub_aff; + group->point_dbl = &ec_GFp_pt_dbl_aff; + group->point_mul = &ec_GFp_pt_mul_jm_wNAF; + group->base_point_mul = NULL; + group->points_mul = &ec_GFp_pts_mul_jac; + group->validate_point = &ec_GFp_validate_point; - CLEANUP: - if (res != MP_OKAY) { - ECGroup_free(group); - return NULL; - } - return group; +CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; } /* Construct a generic ECGroup for elliptic curves over prime fields with * field arithmetic implemented in Montgomery coordinates. */ ECGroup * ECGroup_consGFp_mont(const mp_int *irr, const mp_int *curvea, - const mp_int *curveb, const mp_int *genx, - const mp_int *geny, const mp_int *order, int cofactor) + const mp_int *curveb, const mp_int *genx, + const mp_int *geny, const mp_int *order, int cofactor) { - mp_err res = MP_OKAY; - ECGroup *group = NULL; + mp_err res = MP_OKAY; + ECGroup *group = NULL; - group = ECGroup_new(); - if (group == NULL) - return NULL; + group = ECGroup_new(); + if (group == NULL) + return NULL; - group->meth = GFMethod_consGFp_mont(irr); - if (group->meth == NULL) { - res = MP_MEM; - goto CLEANUP; - } - MP_CHECKOK(group->meth-> - field_enc(curvea, &group->curvea, group->meth)); - MP_CHECKOK(group->meth-> - field_enc(curveb, &group->curveb, group->meth)); - MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth)); - MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth)); - MP_CHECKOK(mp_copy(order, &group->order)); - group->cofactor = cofactor; - group->point_add = &ec_GFp_pt_add_aff; - group->point_sub = &ec_GFp_pt_sub_aff; - group->point_dbl = &ec_GFp_pt_dbl_aff; - group->point_mul = &ec_GFp_pt_mul_jm_wNAF; - group->base_point_mul = NULL; - group->points_mul = &ec_GFp_pts_mul_jac; - group->validate_point = &ec_GFp_validate_point; + group->meth = GFMethod_consGFp_mont(irr); + if (group->meth == NULL) { + res = MP_MEM; + goto CLEANUP; + } + MP_CHECKOK(group->meth->field_enc(curvea, &group->curvea, group->meth)); + MP_CHECKOK(group->meth->field_enc(curveb, &group->curveb, group->meth)); + MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth)); + MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth)); + MP_CHECKOK(mp_copy(order, &group->order)); + group->cofactor = cofactor; + group->point_add = &ec_GFp_pt_add_aff; + group->point_sub = &ec_GFp_pt_sub_aff; + group->point_dbl = &ec_GFp_pt_dbl_aff; + group->point_mul = &ec_GFp_pt_mul_jm_wNAF; + group->base_point_mul = NULL; + group->points_mul = &ec_GFp_pts_mul_jac; + group->validate_point = &ec_GFp_validate_point; - CLEANUP: - if (res != MP_OKAY) { - ECGroup_free(group); - return NULL; - } - return group; +CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; } -#ifdef NSS_ECC_MORE_THAN_SUITE_B -/* Construct a generic ECGroup for elliptic curves over binary polynomial - * fields. */ -ECGroup * -ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5], - const mp_int *curvea, const mp_int *curveb, - const mp_int *genx, const mp_int *geny, - const mp_int *order, int cofactor) -{ - mp_err res = MP_OKAY; - ECGroup *group = NULL; - - group = ECGroup_new(); - if (group == NULL) - return NULL; - - group->meth = GFMethod_consGF2m(irr, irr_arr); - if (group->meth == NULL) { - res = MP_MEM; - goto CLEANUP; - } - MP_CHECKOK(mp_copy(curvea, &group->curvea)); - MP_CHECKOK(mp_copy(curveb, &group->curveb)); - MP_CHECKOK(mp_copy(genx, &group->genx)); - MP_CHECKOK(mp_copy(geny, &group->geny)); - MP_CHECKOK(mp_copy(order, &group->order)); - group->cofactor = cofactor; - group->point_add = &ec_GF2m_pt_add_aff; - group->point_sub = &ec_GF2m_pt_sub_aff; - group->point_dbl = &ec_GF2m_pt_dbl_aff; - group->point_mul = &ec_GF2m_pt_mul_mont; - group->base_point_mul = NULL; - group->points_mul = &ec_pts_mul_basic; - group->validate_point = &ec_GF2m_validate_point; - - CLEANUP: - if (res != MP_OKAY) { - ECGroup_free(group); - return NULL; - } - return group; -} -#endif - /* Construct ECGroup from hex parameters and name, if any. Called by * ECGroup_fromHex and ECGroup_fromName. */ ECGroup * ecgroup_fromNameAndHex(const ECCurveName name, - const ECCurveParams * params) + const ECCurveParams *params) { - mp_int irr, curvea, curveb, genx, geny, order; - int bits; - ECGroup *group = NULL; - mp_err res = MP_OKAY; + mp_int irr, curvea, curveb, genx, geny, order; + int bits; + ECGroup *group = NULL; + mp_err res = MP_OKAY; - /* initialize values */ - MP_DIGITS(&irr) = 0; - MP_DIGITS(&curvea) = 0; - MP_DIGITS(&curveb) = 0; - MP_DIGITS(&genx) = 0; - MP_DIGITS(&geny) = 0; - MP_DIGITS(&order) = 0; - MP_CHECKOK(mp_init(&irr)); - MP_CHECKOK(mp_init(&curvea)); - MP_CHECKOK(mp_init(&curveb)); - MP_CHECKOK(mp_init(&genx)); - MP_CHECKOK(mp_init(&geny)); - MP_CHECKOK(mp_init(&order)); - MP_CHECKOK(mp_read_radix(&irr, params->irr, 16)); - MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16)); - MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16)); - MP_CHECKOK(mp_read_radix(&genx, params->genx, 16)); - MP_CHECKOK(mp_read_radix(&geny, params->geny, 16)); - MP_CHECKOK(mp_read_radix(&order, params->order, 16)); + /* initialize values */ + MP_DIGITS(&irr) = 0; + MP_DIGITS(&curvea) = 0; + MP_DIGITS(&curveb) = 0; + MP_DIGITS(&genx) = 0; + MP_DIGITS(&geny) = 0; + MP_DIGITS(&order) = 0; + MP_CHECKOK(mp_init(&irr)); + MP_CHECKOK(mp_init(&curvea)); + MP_CHECKOK(mp_init(&curveb)); + MP_CHECKOK(mp_init(&genx)); + MP_CHECKOK(mp_init(&geny)); + MP_CHECKOK(mp_init(&order)); + MP_CHECKOK(mp_read_radix(&irr, params->irr, 16)); + MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16)); + MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16)); + MP_CHECKOK(mp_read_radix(&genx, params->genx, 16)); + MP_CHECKOK(mp_read_radix(&geny, params->geny, 16)); + MP_CHECKOK(mp_read_radix(&order, params->order, 16)); - /* determine number of bits */ - bits = mpl_significant_bits(&irr) - 1; - if (bits < MP_OKAY) { - res = bits; - goto CLEANUP; - } + /* determine number of bits */ + bits = mpl_significant_bits(&irr) - 1; + if (bits < MP_OKAY) { + res = bits; + goto CLEANUP; + } - /* determine which optimizations (if any) to use */ - if (params->field == ECField_GFp) { - switch (name) { -#ifdef NSS_ECC_MORE_THAN_SUITE_B -#ifdef ECL_USE_FP - case ECCurve_SECG_PRIME_160R1: - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_secp160r1_fp(group)); - break; -#endif - case ECCurve_SECG_PRIME_192R1: -#ifdef ECL_USE_FP - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_nistp192_fp(group)); -#else - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_gfp192(group, name)); -#endif - break; - case ECCurve_SECG_PRIME_224R1: -#ifdef ECL_USE_FP - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_nistp224_fp(group)); -#else - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_gfp224(group, name)); -#endif - break; -#endif /* NSS_ECC_MORE_THAN_SUITE_B */ - case ECCurve_SECG_PRIME_256R1: - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_gfp256(group, name)); - MP_CHECKOK(ec_group_set_gfp256_32(group, name)); - break; - case ECCurve_SECG_PRIME_521R1: - group = - ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - MP_CHECKOK(ec_group_set_gfp521(group, name)); - break; - default: - /* use generic arithmetic */ - group = - ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - } -#ifdef NSS_ECC_MORE_THAN_SUITE_B - } else if (params->field == ECField_GF2m) { - group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor); - if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } - if ((name == ECCurve_NIST_K163) || - (name == ECCurve_NIST_B163) || - (name == ECCurve_SECG_CHAR2_163R1)) { - MP_CHECKOK(ec_group_set_gf2m163(group, name)); - } else if ((name == ECCurve_SECG_CHAR2_193R1) || - (name == ECCurve_SECG_CHAR2_193R2)) { - MP_CHECKOK(ec_group_set_gf2m193(group, name)); - } else if ((name == ECCurve_NIST_K233) || - (name == ECCurve_NIST_B233)) { - MP_CHECKOK(ec_group_set_gf2m233(group, name)); - } -#endif - } else { - res = MP_UNDEF; - goto CLEANUP; - } + /* determine which optimizations (if any) to use */ + if (params->field == ECField_GFp) { + switch (name) { + case ECCurve_SECG_PRIME_256R1: + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + if (group == NULL) { + res = MP_UNDEF; + goto CLEANUP; + } + MP_CHECKOK(ec_group_set_gfp256(group, name)); + MP_CHECKOK(ec_group_set_gfp256_32(group, name)); + break; + case ECCurve_SECG_PRIME_521R1: + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + if (group == NULL) { + res = MP_UNDEF; + goto CLEANUP; + } + MP_CHECKOK(ec_group_set_gfp521(group, name)); + break; + default: + /* use generic arithmetic */ + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + if (group == NULL) { + res = MP_UNDEF; + goto CLEANUP; + } + } + } else { + res = MP_UNDEF; + goto CLEANUP; + } - /* set name, if any */ - if ((group != NULL) && (params->text != NULL)) { - group->text = strdup(params->text); - if (group->text == NULL) { - res = MP_MEM; - } - } + /* set name, if any */ + if ((group != NULL) && (params->text != NULL)) { + group->text = strdup(params->text); + if (group->text == NULL) { + res = MP_MEM; + } + } - CLEANUP: - mp_clear(&irr); - mp_clear(&curvea); - mp_clear(&curveb); - mp_clear(&genx); - mp_clear(&geny); - mp_clear(&order); - if (res != MP_OKAY) { - ECGroup_free(group); - return NULL; - } - return group; +CLEANUP: + mp_clear(&irr); + mp_clear(&curvea); + mp_clear(&curveb); + mp_clear(&genx); + mp_clear(&geny); + mp_clear(&order); + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; } /* Construct ECGroup from hexadecimal representations of parameters. */ ECGroup * -ECGroup_fromHex(const ECCurveParams * params) +ECGroup_fromHex(const ECCurveParams *params) { - return ecgroup_fromNameAndHex(ECCurve_noName, params); + return ecgroup_fromNameAndHex(ECCurve_noName, params); } /* Construct ECGroup from named parameters. */ ECGroup * ECGroup_fromName(const ECCurveName name) { - ECGroup *group = NULL; - ECCurveParams *params = NULL; - mp_err res = MP_OKAY; + ECGroup *group = NULL; + ECCurveParams *params = NULL; + mp_err res = MP_OKAY; - params = EC_GetNamedCurveParams(name); - if (params == NULL) { - res = MP_UNDEF; - goto CLEANUP; - } + params = EC_GetNamedCurveParams(name); + if (params == NULL) { + res = MP_UNDEF; + goto CLEANUP; + } - /* construct actual group */ - group = ecgroup_fromNameAndHex(name, params); - if (group == NULL) { - res = MP_UNDEF; - goto CLEANUP; - } + /* construct actual group */ + group = ecgroup_fromNameAndHex(name, params); + if (group == NULL) { + res = MP_UNDEF; + goto CLEANUP; + } - CLEANUP: - EC_FreeCurveParams(params); - if (res != MP_OKAY) { - ECGroup_free(group); - return NULL; - } - return group; +CLEANUP: + EC_FreeCurveParams(params); + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; } /* Validates an EC public key as described in Section 5.2.2 of X9.62. */ -mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const - mp_int *py) +mp_err +ECPoint_validate(const ECGroup *group, const mp_int *px, const mp_int *py) { /* 1: Verify that publicValue is not the point at infinity */ - /* 2: Verify that the coordinates of publicValue are elements + /* 2: Verify that the coordinates of publicValue are elements * of the field. */ /* 3: Verify that publicValue is on the curve. */ /* 4: Verify that the order of the curve times the publicValue * is the point at infinity. */ - return group->validate_point(px, py, group); + return group->validate_point(px, py, group); } /* Free the memory allocated (if any) to an ECGroup object. */ void ECGroup_free(ECGroup *group) { - if (group == NULL) - return; - GFMethod_free(group->meth); - if (group->constructed == MP_NO) - return; - mp_clear(&group->curvea); - mp_clear(&group->curveb); - mp_clear(&group->genx); - mp_clear(&group->geny); - mp_clear(&group->order); - if (group->text != NULL) - free(group->text); - if (group->extra_free != NULL) - group->extra_free(group); - free(group); + if (group == NULL) + return; + GFMethod_free(group->meth); + if (group->constructed == MP_NO) + return; + mp_clear(&group->curvea); + mp_clear(&group->curveb); + mp_clear(&group->genx); + mp_clear(&group->geny); + mp_clear(&group->order); + if (group->text != NULL) + free(group->text); + if (group->extra_free != NULL) + group->extra_free(group); + free(group); } diff --git a/nss/lib/freebl/ecl/ecl.h b/nss/lib/freebl/ecl/ecl.h index 3e44803..ddcbb1f 100644 --- a/nss/lib/freebl/ecl/ecl.h +++ b/nss/lib/freebl/ecl/ecl.h @@ -8,6 +8,7 @@ #ifndef __ecl_h_ #define __ecl_h_ +#include "blapi.h" #include "ecl-exp.h" #include "mpi.h" @@ -15,7 +16,7 @@ struct ECGroupStr; typedef struct ECGroupStr ECGroup; /* Construct ECGroup from hexadecimal representations of parameters. */ -ECGroup *ECGroup_fromHex(const ECCurveParams * params); +ECGroup *ECGroup_fromHex(const ECCurveParams *params); /* Construct ECGroup from named parameters. */ ECGroup *ECGroup_fromName(const ECCurveName name); @@ -27,31 +28,33 @@ void ECGroup_free(ECGroup *group); ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name); /* Duplicates an ECCurveParams */ -ECCurveParams *ECCurveParams_dup(const ECCurveParams * params); +ECCurveParams *ECCurveParams_dup(const ECCurveParams *params); /* Free an allocated ECCurveParams */ -void EC_FreeCurveParams(ECCurveParams * params); +void EC_FreeCurveParams(ECCurveParams *params); -/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x, - * y). If x, y = NULL, then P is assumed to be the generator (base point) +/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x, + * y). If x, y = NULL, then P is assumed to be the generator (base point) * of the group of points on the elliptic curve. Input and output values * are assumed to be NOT field-encoded. */ mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, - const mp_int *py, mp_int *qx, mp_int *qy); + const mp_int *py, mp_int *qx, mp_int *qy); -/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G + +/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k1 * G + * k2 * P(x, y), where G is the generator (base point) of the group of * points on the elliptic curve. Input and output values are assumed to * be NOT field-encoded. */ mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1, - const mp_int *k2, const mp_int *px, const mp_int *py, - mp_int *qx, mp_int *qy); + const mp_int *k2, const mp_int *px, const mp_int *py, + mp_int *qx, mp_int *qy); /* Validates an EC public key as described in Section 5.2.2 of X9.62. * Returns MP_YES if the public key is valid, MP_NO if the public key * is invalid, or an error code if the validation could not be * performed. */ -mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const - mp_int *py); +mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const mp_int *py); -#endif /* __ecl_h_ */ +SECStatus ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P); +SECStatus ec_Curve25519_pt_validate(const SECItem *px); + +#endif /* __ecl_h_ */ diff --git a/nss/lib/freebl/ecl/ecl_curve.c b/nss/lib/freebl/ecl/ecl_curve.c index 192dab1..cf090cf 100644 --- a/nss/lib/freebl/ecl/ecl_curve.c +++ b/nss/lib/freebl/ecl/ecl_curve.c @@ -8,47 +8,51 @@ #include <stdlib.h> #include <string.h> -#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; } +#define CHECK(func) \ + if ((func) == NULL) { \ + res = 0; \ + goto CLEANUP; \ + } /* Duplicates an ECCurveParams */ ECCurveParams * -ECCurveParams_dup(const ECCurveParams * params) +ECCurveParams_dup(const ECCurveParams *params) { - int res = 1; - ECCurveParams *ret = NULL; + int res = 1; + ECCurveParams *ret = NULL; - CHECK(ret = (ECCurveParams *) calloc(1, sizeof(ECCurveParams))); - if (params->text != NULL) { - CHECK(ret->text = strdup(params->text)); - } - ret->field = params->field; - ret->size = params->size; - if (params->irr != NULL) { - CHECK(ret->irr = strdup(params->irr)); - } - if (params->curvea != NULL) { - CHECK(ret->curvea = strdup(params->curvea)); - } - if (params->curveb != NULL) { - CHECK(ret->curveb = strdup(params->curveb)); - } - if (params->genx != NULL) { - CHECK(ret->genx = strdup(params->genx)); - } - if (params->geny != NULL) { - CHECK(ret->geny = strdup(params->geny)); - } - if (params->order != NULL) { - CHECK(ret->order = strdup(params->order)); - } - ret->cofactor = params->cofactor; + CHECK(ret = (ECCurveParams *)calloc(1, sizeof(ECCurveParams))); + if (params->text != NULL) { + CHECK(ret->text = strdup(params->text)); + } + ret->field = params->field; + ret->size = params->size; + if (params->irr != NULL) { + CHECK(ret->irr = strdup(params->irr)); + } + if (params->curvea != NULL) { + CHECK(ret->curvea = strdup(params->curvea)); + } + if (params->curveb != NULL) { + CHECK(ret->curveb = strdup(params->curveb)); + } + if (params->genx != NULL) { + CHECK(ret->genx = strdup(params->genx)); + } + if (params->geny != NULL) { + CHECK(ret->geny = strdup(params->geny)); + } + if (params->order != NULL) { + CHECK(ret->order = strdup(params->order)); + } + ret->cofactor = params->cofactor; - CLEANUP: - if (res != 1) { - EC_FreeCurveParams(ret); - return NULL; - } - return ret; +CLEANUP: + if (res != 1) { + EC_FreeCurveParams(ret); + return NULL; + } + return ret; } #undef CHECK @@ -57,33 +61,33 @@ ECCurveParams_dup(const ECCurveParams * params) ECCurveParams * EC_GetNamedCurveParams(const ECCurveName name) { - if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) || - (ecCurve_map[name] == NULL)) { - return NULL; - } else { - return ECCurveParams_dup(ecCurve_map[name]); - } + if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) || + (ecCurve_map[name] == NULL)) { + return NULL; + } else { + return ECCurveParams_dup(ecCurve_map[name]); + } } /* Free the memory allocated (if any) to an ECCurveParams object. */ void -EC_FreeCurveParams(ECCurveParams * params) +EC_FreeCurveParams(ECCurveParams *params) { - if (params == NULL) - return; - if (params->text != NULL) - free(params->text); - if (params->irr != NULL) - free(params->irr); - if (params->curvea != NULL) - free(params->curvea); - if (params->curveb != NULL) - free(params->curveb); - if (params->genx != NULL) - free(params->genx); - if (params->geny != NULL) - free(params->geny); - if (params->order != NULL) - free(params->order); - free(params); + if (params == NULL) + return; + if (params->text != NULL) + free(params->text); + if (params->irr != NULL) + free(params->irr); + if (params->curvea != NULL) + free(params->curvea); + if (params->curveb != NULL) + free(params->curveb); + if (params->genx != NULL) + free(params->genx); + if (params->geny != NULL) + free(params->geny); + if (params->order != NULL) + free(params->order); + free(params); } diff --git a/nss/lib/freebl/ecl/ecl_gf.c b/nss/lib/freebl/ecl/ecl_gf.c index d250d78..81b0077 100644 --- a/nss/lib/freebl/ecl/ecl_gf.c +++ b/nss/lib/freebl/ecl/ecl_gf.c @@ -12,22 +12,22 @@ GFMethod * GFMethod_new() { - mp_err res = MP_OKAY; - GFMethod *meth; - meth = (GFMethod *) malloc(sizeof(GFMethod)); - if (meth == NULL) - return NULL; - meth->constructed = MP_YES; - MP_DIGITS(&meth->irr) = 0; - meth->extra_free = NULL; - MP_CHECKOK(mp_init(&meth->irr)); - - CLEANUP: - if (res != MP_OKAY) { - GFMethod_free(meth); - return NULL; - } - return meth; + mp_err res = MP_OKAY; + GFMethod *meth; + meth = (GFMethod *)malloc(sizeof(GFMethod)); + if (meth == NULL) + return NULL; + meth->constructed = MP_YES; + MP_DIGITS(&meth->irr) = 0; + meth->extra_free = NULL; + MP_CHECKOK(mp_init(&meth->irr)); + +CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; } /* Construct a generic GFMethod for arithmetic over prime fields with @@ -35,126 +35,70 @@ GFMethod_new() GFMethod * GFMethod_consGFp(const mp_int *irr) { - mp_err res = MP_OKAY; - GFMethod *meth = NULL; - - meth = GFMethod_new(); - if (meth == NULL) - return NULL; - - MP_CHECKOK(mp_copy(irr, &meth->irr)); - meth->irr_arr[0] = mpl_significant_bits(irr); - meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] = - meth->irr_arr[4] = 0; - switch(MP_USED(&meth->irr)) { - /* maybe we need 1 and 2 words here as well?*/ - case 3: - meth->field_add = &ec_GFp_add_3; - meth->field_sub = &ec_GFp_sub_3; - break; - case 4: - meth->field_add = &ec_GFp_add_4; - meth->field_sub = &ec_GFp_sub_4; - break; - case 5: - meth->field_add = &ec_GFp_add_5; - meth->field_sub = &ec_GFp_sub_5; - break; - case 6: - meth->field_add = &ec_GFp_add_6; - meth->field_sub = &ec_GFp_sub_6; - break; - default: - meth->field_add = &ec_GFp_add; - meth->field_sub = &ec_GFp_sub; - } - meth->field_neg = &ec_GFp_neg; - meth->field_mod = &ec_GFp_mod; - meth->field_mul = &ec_GFp_mul; - meth->field_sqr = &ec_GFp_sqr; - meth->field_div = &ec_GFp_div; - meth->field_enc = NULL; - meth->field_dec = NULL; - meth->extra1 = NULL; - meth->extra2 = NULL; - meth->extra_free = NULL; - - CLEANUP: - if (res != MP_OKAY) { - GFMethod_free(meth); - return NULL; - } - return meth; -} - -/* Construct a generic GFMethod for arithmetic over binary polynomial - * fields with irreducible irr that has array representation irr_arr (see - * ecl-priv.h for description of the representation). If irr_arr is NULL, - * then it is constructed from the bitstring representation. */ -GFMethod * -GFMethod_consGF2m(const mp_int *irr, const unsigned int irr_arr[5]) -{ - mp_err res = MP_OKAY; - int ret; - GFMethod *meth = NULL; - - meth = GFMethod_new(); - if (meth == NULL) - return NULL; - - MP_CHECKOK(mp_copy(irr, &meth->irr)); - if (irr_arr != NULL) { - /* Irreducible polynomials are either trinomials or pentanomials. */ - meth->irr_arr[0] = irr_arr[0]; - meth->irr_arr[1] = irr_arr[1]; - meth->irr_arr[2] = irr_arr[2]; - if (irr_arr[2] > 0) { - meth->irr_arr[3] = irr_arr[3]; - meth->irr_arr[4] = irr_arr[4]; - } else { - meth->irr_arr[3] = meth->irr_arr[4] = 0; - } - } else { - ret = mp_bpoly2arr(irr, meth->irr_arr, 5); - /* Irreducible polynomials are either trinomials or pentanomials. */ - if ((ret != 5) && (ret != 3)) { - res = MP_UNDEF; - goto CLEANUP; - } - } - meth->field_add = &ec_GF2m_add; - meth->field_neg = &ec_GF2m_neg; - meth->field_sub = &ec_GF2m_add; - meth->field_mod = &ec_GF2m_mod; - meth->field_mul = &ec_GF2m_mul; - meth->field_sqr = &ec_GF2m_sqr; - meth->field_div = &ec_GF2m_div; - meth->field_enc = NULL; - meth->field_dec = NULL; - meth->extra1 = NULL; - meth->extra2 = NULL; - meth->extra_free = NULL; - - CLEANUP: - if (res != MP_OKAY) { - GFMethod_free(meth); - return NULL; - } - return meth; + mp_err res = MP_OKAY; + GFMethod *meth = NULL; + + meth = GFMethod_new(); + if (meth == NULL) + return NULL; + + MP_CHECKOK(mp_copy(irr, &meth->irr)); + meth->irr_arr[0] = mpl_significant_bits(irr); + meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] = + meth->irr_arr[4] = 0; + switch (MP_USED(&meth->irr)) { + /* maybe we need 1 and 2 words here as well?*/ + case 3: + meth->field_add = &ec_GFp_add_3; + meth->field_sub = &ec_GFp_sub_3; + break; + case 4: + meth->field_add = &ec_GFp_add_4; + meth->field_sub = &ec_GFp_sub_4; + break; + case 5: + meth->field_add = &ec_GFp_add_5; + meth->field_sub = &ec_GFp_sub_5; + break; + case 6: + meth->field_add = &ec_GFp_add_6; + meth->field_sub = &ec_GFp_sub_6; + break; + default: + meth->field_add = &ec_GFp_add; + meth->field_sub = &ec_GFp_sub; + } + meth->field_neg = &ec_GFp_neg; + meth->field_mod = &ec_GFp_mod; + meth->field_mul = &ec_GFp_mul; + meth->field_sqr = &ec_GFp_sqr; + meth->field_div = &ec_GFp_div; + meth->field_enc = NULL; + meth->field_dec = NULL; + meth->extra1 = NULL; + meth->extra2 = NULL; + meth->extra_free = NULL; + +CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; } /* Free the memory allocated (if any) to a GFMethod object. */ void GFMethod_free(GFMethod *meth) { - if (meth == NULL) - return; - if (meth->constructed == MP_NO) - return; - mp_clear(&meth->irr); - if (meth->extra_free != NULL) - meth->extra_free(meth); - free(meth); + if (meth == NULL) + return; + if (meth->constructed == MP_NO) + return; + mp_clear(&meth->irr); + if (meth->extra_free != NULL) + meth->extra_free(meth); + free(meth); } /* Wrapper functions for generic prime field arithmetic. */ @@ -162,404 +106,404 @@ GFMethod_free(GFMethod *meth) /* Add two field elements. Assumes that 0 <= a, b < meth->irr */ mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */ - mp_err res; - - if ((res = mp_add(a, b, r)) != MP_OKAY) { - return res; - } - if (mp_cmp(r, &meth->irr) >= 0) { - return mp_sub(r, &meth->irr, r); - } - return res; + /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a + b (mod p) */ + mp_err res; + + if ((res = mp_add(a, b, r)) != MP_OKAY) { + return res; + } + if (mp_cmp(r, &meth->irr) >= 0) { + return mp_sub(r, &meth->irr, r); + } + return res; } /* Negates a field element. Assumes that 0 <= a < meth->irr */ mp_err ec_GFp_neg(const mp_int *a, mp_int *r, const GFMethod *meth) { - /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */ + /* PRE: 0 <= a < p = meth->irr POST: 0 <= r < p, r = -a (mod p) */ - if (mp_cmp_z(a) == 0) { - mp_zero(r); - return MP_OKAY; - } - return mp_sub(&meth->irr, a, r); + if (mp_cmp_z(a) == 0) { + mp_zero(r); + return MP_OKAY; + } + return mp_sub(&meth->irr, a, r); } /* Subtracts two field elements. Assumes that 0 <= a, b < meth->irr */ mp_err ec_GFp_sub(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; - - /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */ - res = mp_sub(a, b, r); - if (res == MP_RANGE) { - MP_CHECKOK(mp_sub(b, a, r)); - if (mp_cmp_z(r) < 0) { - MP_CHECKOK(mp_add(r, &meth->irr, r)); - } - MP_CHECKOK(ec_GFp_neg(r, r, meth)); - } - if (mp_cmp_z(r) < 0) { - MP_CHECKOK(mp_add(r, &meth->irr, r)); - } - CLEANUP: - return res; + mp_err res = MP_OKAY; + + /* PRE: 0 <= a, b < p = meth->irr POST: 0 <= r < p, r = a - b (mod p) */ + res = mp_sub(a, b, r); + if (res == MP_RANGE) { + MP_CHECKOK(mp_sub(b, a, r)); + if (mp_cmp_z(r) < 0) { + MP_CHECKOK(mp_add(r, &meth->irr, r)); + } + MP_CHECKOK(ec_GFp_neg(r, r, meth)); + } + if (mp_cmp_z(r) < 0) { + MP_CHECKOK(mp_add(r, &meth->irr, r)); + } +CLEANUP: + return res; } -/* +/* * Inline adds for small curve lengths. */ /* 3 words */ mp_err -ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit a0 = 0, a1 = 0, a2 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0; - mp_digit carry; - - switch(MP_USED(a)) { - case 3: - a2 = MP_DIGIT(a,2); - case 2: - a1 = MP_DIGIT(a,1); - case 1: - a0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 3: - r2 = MP_DIGIT(b,2); - case 2: - r1 = MP_DIGIT(b,1); - case 1: - r0 = MP_DIGIT(b,0); - } + mp_err res = MP_OKAY; + mp_digit a0 = 0, a1 = 0, a2 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0; + mp_digit carry; + + switch (MP_USED(a)) { + case 3: + a2 = MP_DIGIT(a, 2); + case 2: + a1 = MP_DIGIT(a, 1); + case 1: + a0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 3: + r2 = MP_DIGIT(b, 2); + case 2: + r1 = MP_DIGIT(b, 1); + case 1: + r0 = MP_DIGIT(b, 0); + } #ifndef MPI_AMD64_ADD - carry = 0; - MP_ADD_CARRY(a0, r0, r0, carry); - MP_ADD_CARRY(a1, r1, r1, carry); - MP_ADD_CARRY(a2, r2, r2, carry); + carry = 0; + MP_ADD_CARRY(a0, r0, r0, carry); + MP_ADD_CARRY(a1, r1, r1, carry); + MP_ADD_CARRY(a2, r2, r2, carry); #else - __asm__ ( - "xorq %3,%3 \n\t" - "addq %4,%0 \n\t" - "adcq %5,%1 \n\t" - "adcq %6,%2 \n\t" - "adcq $0,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry) - : "r" (a0), "r" (a1), "r" (a2), - "0" (r0), "1" (r1), "2" (r2) - : "%cc" ); + __asm__( + "xorq %3,%3 \n\t" + "addq %4,%0 \n\t" + "adcq %5,%1 \n\t" + "adcq %6,%2 \n\t" + "adcq $0,%3 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry) + : "r"(a0), "r"(a1), "r"(a2), + "0"(r0), "1"(r1), "2"(r2) + : "%cc"); #endif - MP_CHECKOK(s_mp_pad(r, 3)); - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 3; - - /* Do quick 'subract' if we've gone over - * (add the 2's complement of the curve field) */ - a2 = MP_DIGIT(&meth->irr,2); - if (carry || r2 > a2 || - ((r2 == a2) && mp_cmp(r,&meth->irr) != MP_LT)) { - a1 = MP_DIGIT(&meth->irr,1); - a0 = MP_DIGIT(&meth->irr,0); + MP_CHECKOK(s_mp_pad(r, 3)); + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 3; + + /* Do quick 'subract' if we've gone over + * (add the 2's complement of the curve field) */ + a2 = MP_DIGIT(&meth->irr, 2); + if (carry || r2 > a2 || + ((r2 == a2) && mp_cmp(r, &meth->irr) != MP_LT)) { + a1 = MP_DIGIT(&meth->irr, 1); + a0 = MP_DIGIT(&meth->irr, 0); #ifndef MPI_AMD64_ADD - carry = 0; - MP_SUB_BORROW(r0, a0, r0, carry); - MP_SUB_BORROW(r1, a1, r1, carry); - MP_SUB_BORROW(r2, a2, r2, carry); + carry = 0; + MP_SUB_BORROW(r0, a0, r0, carry); + MP_SUB_BORROW(r1, a1, r1, carry); + MP_SUB_BORROW(r2, a2, r2, carry); #else - __asm__ ( - "subq %3,%0 \n\t" - "sbbq %4,%1 \n\t" - "sbbq %5,%2 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2) - : "r" (a0), "r" (a1), "r" (a2), - "0" (r0), "1" (r1), "2" (r2) - : "%cc" ); + __asm__( + "subq %3,%0 \n\t" + "sbbq %4,%1 \n\t" + "sbbq %5,%2 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2) + : "r"(a0), "r"(a1), "r"(a2), + "0"(r0), "1"(r1), "2"(r2) + : "%cc"); #endif - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - } - - s_mp_clamp(r); - - CLEANUP: - return res; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + } + + s_mp_clamp(r); + +CLEANUP: + return res; } /* 4 words */ mp_err -ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0; - mp_digit carry; - - switch(MP_USED(a)) { - case 4: - a3 = MP_DIGIT(a,3); - case 3: - a2 = MP_DIGIT(a,2); - case 2: - a1 = MP_DIGIT(a,1); - case 1: - a0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 4: - r3 = MP_DIGIT(b,3); - case 3: - r2 = MP_DIGIT(b,2); - case 2: - r1 = MP_DIGIT(b,1); - case 1: - r0 = MP_DIGIT(b,0); - } + mp_err res = MP_OKAY; + mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0; + mp_digit carry; + + switch (MP_USED(a)) { + case 4: + a3 = MP_DIGIT(a, 3); + case 3: + a2 = MP_DIGIT(a, 2); + case 2: + a1 = MP_DIGIT(a, 1); + case 1: + a0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 4: + r3 = MP_DIGIT(b, 3); + case 3: + r2 = MP_DIGIT(b, 2); + case 2: + r1 = MP_DIGIT(b, 1); + case 1: + r0 = MP_DIGIT(b, 0); + } #ifndef MPI_AMD64_ADD - carry = 0; - MP_ADD_CARRY(a0, r0, r0, carry); - MP_ADD_CARRY(a1, r1, r1, carry); - MP_ADD_CARRY(a2, r2, r2, carry); - MP_ADD_CARRY(a3, r3, r3, carry); + carry = 0; + MP_ADD_CARRY(a0, r0, r0, carry); + MP_ADD_CARRY(a1, r1, r1, carry); + MP_ADD_CARRY(a2, r2, r2, carry); + MP_ADD_CARRY(a3, r3, r3, carry); #else - __asm__ ( - "xorq %4,%4 \n\t" - "addq %5,%0 \n\t" - "adcq %6,%1 \n\t" - "adcq %7,%2 \n\t" - "adcq %8,%3 \n\t" - "adcq $0,%4 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry) - : "r" (a0), "r" (a1), "r" (a2), "r" (a3), - "0" (r0), "1" (r1), "2" (r2), "3" (r3) - : "%cc" ); + __asm__( + "xorq %4,%4 \n\t" + "addq %5,%0 \n\t" + "adcq %6,%1 \n\t" + "adcq %7,%2 \n\t" + "adcq %8,%3 \n\t" + "adcq $0,%4 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry) + : "r"(a0), "r"(a1), "r"(a2), "r"(a3), + "0"(r0), "1"(r1), "2"(r2), "3"(r3) + : "%cc"); #endif - MP_CHECKOK(s_mp_pad(r, 4)); - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 4; - - /* Do quick 'subract' if we've gone over - * (add the 2's complement of the curve field) */ - a3 = MP_DIGIT(&meth->irr,3); - if (carry || r3 > a3 || - ((r3 == a3) && mp_cmp(r,&meth->irr) != MP_LT)) { - a2 = MP_DIGIT(&meth->irr,2); - a1 = MP_DIGIT(&meth->irr,1); - a0 = MP_DIGIT(&meth->irr,0); + MP_CHECKOK(s_mp_pad(r, 4)); + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 4; + + /* Do quick 'subract' if we've gone over + * (add the 2's complement of the curve field) */ + a3 = MP_DIGIT(&meth->irr, 3); + if (carry || r3 > a3 || + ((r3 == a3) && mp_cmp(r, &meth->irr) != MP_LT)) { + a2 = MP_DIGIT(&meth->irr, 2); + a1 = MP_DIGIT(&meth->irr, 1); + a0 = MP_DIGIT(&meth->irr, 0); #ifndef MPI_AMD64_ADD - carry = 0; - MP_SUB_BORROW(r0, a0, r0, carry); - MP_SUB_BORROW(r1, a1, r1, carry); - MP_SUB_BORROW(r2, a2, r2, carry); - MP_SUB_BORROW(r3, a3, r3, carry); + carry = 0; + MP_SUB_BORROW(r0, a0, r0, carry); + MP_SUB_BORROW(r1, a1, r1, carry); + MP_SUB_BORROW(r2, a2, r2, carry); + MP_SUB_BORROW(r3, a3, r3, carry); #else - __asm__ ( - "subq %4,%0 \n\t" - "sbbq %5,%1 \n\t" - "sbbq %6,%2 \n\t" - "sbbq %7,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3) - : "r" (a0), "r" (a1), "r" (a2), "r" (a3), - "0" (r0), "1" (r1), "2" (r2), "3" (r3) - : "%cc" ); + __asm__( + "subq %4,%0 \n\t" + "sbbq %5,%1 \n\t" + "sbbq %6,%2 \n\t" + "sbbq %7,%3 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3) + : "r"(a0), "r"(a1), "r"(a2), "r"(a3), + "0"(r0), "1"(r1), "2"(r2), "3"(r3) + : "%cc"); #endif - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - } - - s_mp_clamp(r); - - CLEANUP: - return res; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + } + + s_mp_clamp(r); + +CLEANUP: + return res; } /* 5 words */ mp_err -ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0; - mp_digit carry; - - switch(MP_USED(a)) { - case 5: - a4 = MP_DIGIT(a,4); - case 4: - a3 = MP_DIGIT(a,3); - case 3: - a2 = MP_DIGIT(a,2); - case 2: - a1 = MP_DIGIT(a,1); - case 1: - a0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 5: - r4 = MP_DIGIT(b,4); - case 4: - r3 = MP_DIGIT(b,3); - case 3: - r2 = MP_DIGIT(b,2); - case 2: - r1 = MP_DIGIT(b,1); - case 1: - r0 = MP_DIGIT(b,0); - } - + mp_err res = MP_OKAY; + mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0; + mp_digit carry; + + switch (MP_USED(a)) { + case 5: + a4 = MP_DIGIT(a, 4); + case 4: + a3 = MP_DIGIT(a, 3); + case 3: + a2 = MP_DIGIT(a, 2); + case 2: + a1 = MP_DIGIT(a, 1); + case 1: + a0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 5: + r4 = MP_DIGIT(b, 4); + case 4: + r3 = MP_DIGIT(b, 3); + case 3: + r2 = MP_DIGIT(b, 2); + case 2: + r1 = MP_DIGIT(b, 1); + case 1: + r0 = MP_DIGIT(b, 0); + } + + carry = 0; + MP_ADD_CARRY(a0, r0, r0, carry); + MP_ADD_CARRY(a1, r1, r1, carry); + MP_ADD_CARRY(a2, r2, r2, carry); + MP_ADD_CARRY(a3, r3, r3, carry); + MP_ADD_CARRY(a4, r4, r4, carry); + + MP_CHECKOK(s_mp_pad(r, 5)); + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 5; + + /* Do quick 'subract' if we've gone over + * (add the 2's complement of the curve field) */ + a4 = MP_DIGIT(&meth->irr, 4); + if (carry || r4 > a4 || + ((r4 == a4) && mp_cmp(r, &meth->irr) != MP_LT)) { + a3 = MP_DIGIT(&meth->irr, 3); + a2 = MP_DIGIT(&meth->irr, 2); + a1 = MP_DIGIT(&meth->irr, 1); + a0 = MP_DIGIT(&meth->irr, 0); carry = 0; - MP_ADD_CARRY(a0, r0, r0, carry); - MP_ADD_CARRY(a1, r1, r1, carry); - MP_ADD_CARRY(a2, r2, r2, carry); - MP_ADD_CARRY(a3, r3, r3, carry); - MP_ADD_CARRY(a4, r4, r4, carry); - - MP_CHECKOK(s_mp_pad(r, 5)); - MP_DIGIT(r, 4) = r4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 5; - - /* Do quick 'subract' if we've gone over - * (add the 2's complement of the curve field) */ - a4 = MP_DIGIT(&meth->irr,4); - if (carry || r4 > a4 || - ((r4 == a4) && mp_cmp(r,&meth->irr) != MP_LT)) { - a3 = MP_DIGIT(&meth->irr,3); - a2 = MP_DIGIT(&meth->irr,2); - a1 = MP_DIGIT(&meth->irr,1); - a0 = MP_DIGIT(&meth->irr,0); - carry = 0; - MP_SUB_BORROW(r0, a0, r0, carry); - MP_SUB_BORROW(r1, a1, r1, carry); - MP_SUB_BORROW(r2, a2, r2, carry); - MP_SUB_BORROW(r3, a3, r3, carry); - MP_SUB_BORROW(r4, a4, r4, carry); - MP_DIGIT(r, 4) = r4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - } - - s_mp_clamp(r); - - CLEANUP: - return res; + MP_SUB_BORROW(r0, a0, r0, carry); + MP_SUB_BORROW(r1, a1, r1, carry); + MP_SUB_BORROW(r2, a2, r2, carry); + MP_SUB_BORROW(r3, a3, r3, carry); + MP_SUB_BORROW(r4, a4, r4, carry); + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + } + + s_mp_clamp(r); + +CLEANUP: + return res; } /* 6 words */ mp_err -ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0; - mp_digit carry; - - switch(MP_USED(a)) { - case 6: - a5 = MP_DIGIT(a,5); - case 5: - a4 = MP_DIGIT(a,4); - case 4: - a3 = MP_DIGIT(a,3); - case 3: - a2 = MP_DIGIT(a,2); - case 2: - a1 = MP_DIGIT(a,1); - case 1: - a0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 6: - r5 = MP_DIGIT(b,5); - case 5: - r4 = MP_DIGIT(b,4); - case 4: - r3 = MP_DIGIT(b,3); - case 3: - r2 = MP_DIGIT(b,2); - case 2: - r1 = MP_DIGIT(b,1); - case 1: - r0 = MP_DIGIT(b,0); - } - + mp_err res = MP_OKAY; + mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0; + mp_digit carry; + + switch (MP_USED(a)) { + case 6: + a5 = MP_DIGIT(a, 5); + case 5: + a4 = MP_DIGIT(a, 4); + case 4: + a3 = MP_DIGIT(a, 3); + case 3: + a2 = MP_DIGIT(a, 2); + case 2: + a1 = MP_DIGIT(a, 1); + case 1: + a0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 6: + r5 = MP_DIGIT(b, 5); + case 5: + r4 = MP_DIGIT(b, 4); + case 4: + r3 = MP_DIGIT(b, 3); + case 3: + r2 = MP_DIGIT(b, 2); + case 2: + r1 = MP_DIGIT(b, 1); + case 1: + r0 = MP_DIGIT(b, 0); + } + + carry = 0; + MP_ADD_CARRY(a0, r0, r0, carry); + MP_ADD_CARRY(a1, r1, r1, carry); + MP_ADD_CARRY(a2, r2, r2, carry); + MP_ADD_CARRY(a3, r3, r3, carry); + MP_ADD_CARRY(a4, r4, r4, carry); + MP_ADD_CARRY(a5, r5, r5, carry); + + MP_CHECKOK(s_mp_pad(r, 6)); + MP_DIGIT(r, 5) = r5; + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 6; + + /* Do quick 'subract' if we've gone over + * (add the 2's complement of the curve field) */ + a5 = MP_DIGIT(&meth->irr, 5); + if (carry || r5 > a5 || + ((r5 == a5) && mp_cmp(r, &meth->irr) != MP_LT)) { + a4 = MP_DIGIT(&meth->irr, 4); + a3 = MP_DIGIT(&meth->irr, 3); + a2 = MP_DIGIT(&meth->irr, 2); + a1 = MP_DIGIT(&meth->irr, 1); + a0 = MP_DIGIT(&meth->irr, 0); carry = 0; - MP_ADD_CARRY(a0, r0, r0, carry); - MP_ADD_CARRY(a1, r1, r1, carry); - MP_ADD_CARRY(a2, r2, r2, carry); - MP_ADD_CARRY(a3, r3, r3, carry); - MP_ADD_CARRY(a4, r4, r4, carry); - MP_ADD_CARRY(a5, r5, r5, carry); - - MP_CHECKOK(s_mp_pad(r, 6)); - MP_DIGIT(r, 5) = r5; - MP_DIGIT(r, 4) = r4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 6; - - /* Do quick 'subract' if we've gone over - * (add the 2's complement of the curve field) */ - a5 = MP_DIGIT(&meth->irr,5); - if (carry || r5 > a5 || - ((r5 == a5) && mp_cmp(r,&meth->irr) != MP_LT)) { - a4 = MP_DIGIT(&meth->irr,4); - a3 = MP_DIGIT(&meth->irr,3); - a2 = MP_DIGIT(&meth->irr,2); - a1 = MP_DIGIT(&meth->irr,1); - a0 = MP_DIGIT(&meth->irr,0); - carry = 0; - MP_SUB_BORROW(r0, a0, r0, carry); - MP_SUB_BORROW(r1, a1, r1, carry); - MP_SUB_BORROW(r2, a2, r2, carry); - MP_SUB_BORROW(r3, a3, r3, carry); - MP_SUB_BORROW(r4, a4, r4, carry); - MP_SUB_BORROW(r5, a5, r5, carry); - MP_DIGIT(r, 5) = r5; - MP_DIGIT(r, 4) = r4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - } - - s_mp_clamp(r); - - CLEANUP: - return res; + MP_SUB_BORROW(r0, a0, r0, carry); + MP_SUB_BORROW(r1, a1, r1, carry); + MP_SUB_BORROW(r2, a2, r2, carry); + MP_SUB_BORROW(r3, a3, r3, carry); + MP_SUB_BORROW(r4, a4, r4, carry); + MP_SUB_BORROW(r5, a5, r5, carry); + MP_DIGIT(r, 5) = r5; + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + } + + s_mp_clamp(r); + +CLEANUP: + return res; } /* @@ -569,379 +513,380 @@ ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r, * ... 3 words */ mp_err -ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit b0 = 0, b1 = 0, b2 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0; - mp_digit borrow; - - switch(MP_USED(a)) { - case 3: - r2 = MP_DIGIT(a,2); - case 2: - r1 = MP_DIGIT(a,1); - case 1: - r0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 3: - b2 = MP_DIGIT(b,2); - case 2: - b1 = MP_DIGIT(b,1); - case 1: - b0 = MP_DIGIT(b,0); - } + mp_err res = MP_OKAY; + mp_digit b0 = 0, b1 = 0, b2 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0; + mp_digit borrow; + + switch (MP_USED(a)) { + case 3: + r2 = MP_DIGIT(a, 2); + case 2: + r1 = MP_DIGIT(a, 1); + case 1: + r0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 3: + b2 = MP_DIGIT(b, 2); + case 2: + b1 = MP_DIGIT(b, 1); + case 1: + b0 = MP_DIGIT(b, 0); + } #ifndef MPI_AMD64_ADD - borrow = 0; - MP_SUB_BORROW(r0, b0, r0, borrow); - MP_SUB_BORROW(r1, b1, r1, borrow); - MP_SUB_BORROW(r2, b2, r2, borrow); + borrow = 0; + MP_SUB_BORROW(r0, b0, r0, borrow); + MP_SUB_BORROW(r1, b1, r1, borrow); + MP_SUB_BORROW(r2, b2, r2, borrow); #else - __asm__ ( - "xorq %3,%3 \n\t" - "subq %4,%0 \n\t" - "sbbq %5,%1 \n\t" - "sbbq %6,%2 \n\t" - "adcq $0,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r" (borrow) - : "r" (b0), "r" (b1), "r" (b2), - "0" (r0), "1" (r1), "2" (r2) - : "%cc" ); + __asm__( + "xorq %3,%3 \n\t" + "subq %4,%0 \n\t" + "sbbq %5,%1 \n\t" + "sbbq %6,%2 \n\t" + "adcq $0,%3 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow) + : "r"(b0), "r"(b1), "r"(b2), + "0"(r0), "1"(r1), "2"(r2) + : "%cc"); #endif - /* Do quick 'add' if we've gone under 0 - * (subtract the 2's complement of the curve field) */ - if (borrow) { - b2 = MP_DIGIT(&meth->irr,2); - b1 = MP_DIGIT(&meth->irr,1); - b0 = MP_DIGIT(&meth->irr,0); + /* Do quick 'add' if we've gone under 0 + * (subtract the 2's complement of the curve field) */ + if (borrow) { + b2 = MP_DIGIT(&meth->irr, 2); + b1 = MP_DIGIT(&meth->irr, 1); + b0 = MP_DIGIT(&meth->irr, 0); #ifndef MPI_AMD64_ADD - borrow = 0; - MP_ADD_CARRY(b0, r0, r0, borrow); - MP_ADD_CARRY(b1, r1, r1, borrow); - MP_ADD_CARRY(b2, r2, r2, borrow); + borrow = 0; + MP_ADD_CARRY(b0, r0, r0, borrow); + MP_ADD_CARRY(b1, r1, r1, borrow); + MP_ADD_CARRY(b2, r2, r2, borrow); #else - __asm__ ( - "addq %3,%0 \n\t" - "adcq %4,%1 \n\t" - "adcq %5,%2 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2) - : "r" (b0), "r" (b1), "r" (b2), - "0" (r0), "1" (r1), "2" (r2) - : "%cc" ); + __asm__( + "addq %3,%0 \n\t" + "adcq %4,%1 \n\t" + "adcq %5,%2 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2) + : "r"(b0), "r"(b1), "r"(b2), + "0"(r0), "1"(r1), "2"(r2) + : "%cc"); #endif - } + } #ifdef MPI_AMD64_ADD - /* compiler fakeout? */ - if ((r2 == b0) && (r1 == b0) && (r0 == b0)) { - MP_CHECKOK(s_mp_pad(r, 4)); - } + /* compiler fakeout? */ + if ((r2 == b0) && (r1 == b0) && (r0 == b0)) { + MP_CHECKOK(s_mp_pad(r, 4)); + } #endif - MP_CHECKOK(s_mp_pad(r, 3)); - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 3; - s_mp_clamp(r); - - CLEANUP: - return res; + MP_CHECKOK(s_mp_pad(r, 3)); + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 3; + s_mp_clamp(r); + +CLEANUP: + return res; } /* 4 words */ mp_err -ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0; - mp_digit borrow; - - switch(MP_USED(a)) { - case 4: - r3 = MP_DIGIT(a,3); - case 3: - r2 = MP_DIGIT(a,2); - case 2: - r1 = MP_DIGIT(a,1); - case 1: - r0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 4: - b3 = MP_DIGIT(b,3); - case 3: - b2 = MP_DIGIT(b,2); - case 2: - b1 = MP_DIGIT(b,1); - case 1: - b0 = MP_DIGIT(b,0); - } + mp_err res = MP_OKAY; + mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0; + mp_digit borrow; + + switch (MP_USED(a)) { + case 4: + r3 = MP_DIGIT(a, 3); + case 3: + r2 = MP_DIGIT(a, 2); + case 2: + r1 = MP_DIGIT(a, 1); + case 1: + r0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 4: + b3 = MP_DIGIT(b, 3); + case 3: + b2 = MP_DIGIT(b, 2); + case 2: + b1 = MP_DIGIT(b, 1); + case 1: + b0 = MP_DIGIT(b, 0); + } #ifndef MPI_AMD64_ADD - borrow = 0; - MP_SUB_BORROW(r0, b0, r0, borrow); - MP_SUB_BORROW(r1, b1, r1, borrow); - MP_SUB_BORROW(r2, b2, r2, borrow); - MP_SUB_BORROW(r3, b3, r3, borrow); + borrow = 0; + MP_SUB_BORROW(r0, b0, r0, borrow); + MP_SUB_BORROW(r1, b1, r1, borrow); + MP_SUB_BORROW(r2, b2, r2, borrow); + MP_SUB_BORROW(r3, b3, r3, borrow); #else - __asm__ ( - "xorq %4,%4 \n\t" - "subq %5,%0 \n\t" - "sbbq %6,%1 \n\t" - "sbbq %7,%2 \n\t" - "sbbq %8,%3 \n\t" - "adcq $0,%4 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r" (borrow) - : "r" (b0), "r" (b1), "r" (b2), "r" (b3), - "0" (r0), "1" (r1), "2" (r2), "3" (r3) - : "%cc" ); + __asm__( + "xorq %4,%4 \n\t" + "subq %5,%0 \n\t" + "sbbq %6,%1 \n\t" + "sbbq %7,%2 \n\t" + "sbbq %8,%3 \n\t" + "adcq $0,%4 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(borrow) + : "r"(b0), "r"(b1), "r"(b2), "r"(b3), + "0"(r0), "1"(r1), "2"(r2), "3"(r3) + : "%cc"); #endif - /* Do quick 'add' if we've gone under 0 - * (subtract the 2's complement of the curve field) */ - if (borrow) { - b3 = MP_DIGIT(&meth->irr,3); - b2 = MP_DIGIT(&meth->irr,2); - b1 = MP_DIGIT(&meth->irr,1); - b0 = MP_DIGIT(&meth->irr,0); + /* Do quick 'add' if we've gone under 0 + * (subtract the 2's complement of the curve field) */ + if (borrow) { + b3 = MP_DIGIT(&meth->irr, 3); + b2 = MP_DIGIT(&meth->irr, 2); + b1 = MP_DIGIT(&meth->irr, 1); + b0 = MP_DIGIT(&meth->irr, 0); #ifndef MPI_AMD64_ADD - borrow = 0; - MP_ADD_CARRY(b0, r0, r0, borrow); - MP_ADD_CARRY(b1, r1, r1, borrow); - MP_ADD_CARRY(b2, r2, r2, borrow); - MP_ADD_CARRY(b3, r3, r3, borrow); + borrow = 0; + MP_ADD_CARRY(b0, r0, r0, borrow); + MP_ADD_CARRY(b1, r1, r1, borrow); + MP_ADD_CARRY(b2, r2, r2, borrow); + MP_ADD_CARRY(b3, r3, r3, borrow); #else - __asm__ ( - "addq %4,%0 \n\t" - "adcq %5,%1 \n\t" - "adcq %6,%2 \n\t" - "adcq %7,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3) - : "r" (b0), "r" (b1), "r" (b2), "r" (b3), - "0" (r0), "1" (r1), "2" (r2), "3" (r3) - : "%cc" ); + __asm__( + "addq %4,%0 \n\t" + "adcq %5,%1 \n\t" + "adcq %6,%2 \n\t" + "adcq %7,%3 \n\t" + : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3) + : "r"(b0), "r"(b1), "r"(b2), "r"(b3), + "0"(r0), "1"(r1), "2"(r2), "3"(r3) + : "%cc"); #endif - } + } #ifdef MPI_AMD64_ADD - /* compiler fakeout? */ - if ((r3 == b0) && (r1 == b0) && (r0 == b0)) { - MP_CHECKOK(s_mp_pad(r, 4)); - } + /* compiler fakeout? */ + if ((r3 == b0) && (r1 == b0) && (r0 == b0)) { + MP_CHECKOK(s_mp_pad(r, 4)); + } #endif - MP_CHECKOK(s_mp_pad(r, 4)); - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 4; - s_mp_clamp(r); - - CLEANUP: - return res; + MP_CHECKOK(s_mp_pad(r, 4)); + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 4; + s_mp_clamp(r); + +CLEANUP: + return res; } /* 5 words */ mp_err -ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0; - mp_digit borrow; - - switch(MP_USED(a)) { - case 5: - r4 = MP_DIGIT(a,4); - case 4: - r3 = MP_DIGIT(a,3); - case 3: - r2 = MP_DIGIT(a,2); - case 2: - r1 = MP_DIGIT(a,1); - case 1: - r0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 5: - b4 = MP_DIGIT(b,4); - case 4: - b3 = MP_DIGIT(b,3); - case 3: - b2 = MP_DIGIT(b,2); - case 2: - b1 = MP_DIGIT(b,1); - case 1: - b0 = MP_DIGIT(b,0); - } - + mp_err res = MP_OKAY; + mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0; + mp_digit borrow; + + switch (MP_USED(a)) { + case 5: + r4 = MP_DIGIT(a, 4); + case 4: + r3 = MP_DIGIT(a, 3); + case 3: + r2 = MP_DIGIT(a, 2); + case 2: + r1 = MP_DIGIT(a, 1); + case 1: + r0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 5: + b4 = MP_DIGIT(b, 4); + case 4: + b3 = MP_DIGIT(b, 3); + case 3: + b2 = MP_DIGIT(b, 2); + case 2: + b1 = MP_DIGIT(b, 1); + case 1: + b0 = MP_DIGIT(b, 0); + } + + borrow = 0; + MP_SUB_BORROW(r0, b0, r0, borrow); + MP_SUB_BORROW(r1, b1, r1, borrow); + MP_SUB_BORROW(r2, b2, r2, borrow); + MP_SUB_BORROW(r3, b3, r3, borrow); + MP_SUB_BORROW(r4, b4, r4, borrow); + + /* Do quick 'add' if we've gone under 0 + * (subtract the 2's complement of the curve field) */ + if (borrow) { + b4 = MP_DIGIT(&meth->irr, 4); + b3 = MP_DIGIT(&meth->irr, 3); + b2 = MP_DIGIT(&meth->irr, 2); + b1 = MP_DIGIT(&meth->irr, 1); + b0 = MP_DIGIT(&meth->irr, 0); borrow = 0; - MP_SUB_BORROW(r0, b0, r0, borrow); - MP_SUB_BORROW(r1, b1, r1, borrow); - MP_SUB_BORROW(r2, b2, r2, borrow); - MP_SUB_BORROW(r3, b3, r3, borrow); - MP_SUB_BORROW(r4, b4, r4, borrow); - - /* Do quick 'add' if we've gone under 0 - * (subtract the 2's complement of the curve field) */ - if (borrow) { - b4 = MP_DIGIT(&meth->irr,4); - b3 = MP_DIGIT(&meth->irr,3); - b2 = MP_DIGIT(&meth->irr,2); - b1 = MP_DIGIT(&meth->irr,1); - b0 = MP_DIGIT(&meth->irr,0); - borrow = 0; - MP_ADD_CARRY(b0, r0, r0, borrow); - MP_ADD_CARRY(b1, r1, r1, borrow); - MP_ADD_CARRY(b2, r2, r2, borrow); - MP_ADD_CARRY(b3, r3, r3, borrow); - } - MP_CHECKOK(s_mp_pad(r, 5)); - MP_DIGIT(r, 4) = r4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 5; - s_mp_clamp(r); - - CLEANUP: - return res; + MP_ADD_CARRY(b0, r0, r0, borrow); + MP_ADD_CARRY(b1, r1, r1, borrow); + MP_ADD_CARRY(b2, r2, r2, borrow); + MP_ADD_CARRY(b3, r3, r3, borrow); + MP_ADD_CARRY(b4, r4, r4, borrow); + } + MP_CHECKOK(s_mp_pad(r, 5)); + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 5; + s_mp_clamp(r); + +CLEANUP: + return res; } /* 6 words */ mp_err -ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) +ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0; - mp_digit borrow; - - switch(MP_USED(a)) { - case 6: - r5 = MP_DIGIT(a,5); - case 5: - r4 = MP_DIGIT(a,4); - case 4: - r3 = MP_DIGIT(a,3); - case 3: - r2 = MP_DIGIT(a,2); - case 2: - r1 = MP_DIGIT(a,1); - case 1: - r0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 6: - b5 = MP_DIGIT(b,5); - case 5: - b4 = MP_DIGIT(b,4); - case 4: - b3 = MP_DIGIT(b,3); - case 3: - b2 = MP_DIGIT(b,2); - case 2: - b1 = MP_DIGIT(b,1); - case 1: - b0 = MP_DIGIT(b,0); - } - + mp_err res = MP_OKAY; + mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0; + mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0; + mp_digit borrow; + + switch (MP_USED(a)) { + case 6: + r5 = MP_DIGIT(a, 5); + case 5: + r4 = MP_DIGIT(a, 4); + case 4: + r3 = MP_DIGIT(a, 3); + case 3: + r2 = MP_DIGIT(a, 2); + case 2: + r1 = MP_DIGIT(a, 1); + case 1: + r0 = MP_DIGIT(a, 0); + } + switch (MP_USED(b)) { + case 6: + b5 = MP_DIGIT(b, 5); + case 5: + b4 = MP_DIGIT(b, 4); + case 4: + b3 = MP_DIGIT(b, 3); + case 3: + b2 = MP_DIGIT(b, 2); + case 2: + b1 = MP_DIGIT(b, 1); + case 1: + b0 = MP_DIGIT(b, 0); + } + + borrow = 0; + MP_SUB_BORROW(r0, b0, r0, borrow); + MP_SUB_BORROW(r1, b1, r1, borrow); + MP_SUB_BORROW(r2, b2, r2, borrow); + MP_SUB_BORROW(r3, b3, r3, borrow); + MP_SUB_BORROW(r4, b4, r4, borrow); + MP_SUB_BORROW(r5, b5, r5, borrow); + + /* Do quick 'add' if we've gone under 0 + * (subtract the 2's complement of the curve field) */ + if (borrow) { + b5 = MP_DIGIT(&meth->irr, 5); + b4 = MP_DIGIT(&meth->irr, 4); + b3 = MP_DIGIT(&meth->irr, 3); + b2 = MP_DIGIT(&meth->irr, 2); + b1 = MP_DIGIT(&meth->irr, 1); + b0 = MP_DIGIT(&meth->irr, 0); borrow = 0; - MP_SUB_BORROW(r0, b0, r0, borrow); - MP_SUB_BORROW(r1, b1, r1, borrow); - MP_SUB_BORROW(r2, b2, r2, borrow); - MP_SUB_BORROW(r3, b3, r3, borrow); - MP_SUB_BORROW(r4, b4, r4, borrow); - MP_SUB_BORROW(r5, b5, r5, borrow); - - /* Do quick 'add' if we've gone under 0 - * (subtract the 2's complement of the curve field) */ - if (borrow) { - b5 = MP_DIGIT(&meth->irr,5); - b4 = MP_DIGIT(&meth->irr,4); - b3 = MP_DIGIT(&meth->irr,3); - b2 = MP_DIGIT(&meth->irr,2); - b1 = MP_DIGIT(&meth->irr,1); - b0 = MP_DIGIT(&meth->irr,0); - borrow = 0; - MP_ADD_CARRY(b0, r0, r0, borrow); - MP_ADD_CARRY(b1, r1, r1, borrow); - MP_ADD_CARRY(b2, r2, r2, borrow); - MP_ADD_CARRY(b3, r3, r3, borrow); - MP_ADD_CARRY(b4, r4, r4, borrow); - } - - MP_CHECKOK(s_mp_pad(r, 6)); - MP_DIGIT(r, 5) = r5; - MP_DIGIT(r, 4) = r4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 6; - s_mp_clamp(r); - - CLEANUP: - return res; + MP_ADD_CARRY(b0, r0, r0, borrow); + MP_ADD_CARRY(b1, r1, r1, borrow); + MP_ADD_CARRY(b2, r2, r2, borrow); + MP_ADD_CARRY(b3, r3, r3, borrow); + MP_ADD_CARRY(b4, r4, r4, borrow); + MP_ADD_CARRY(b5, r5, r5, borrow); + } + + MP_CHECKOK(s_mp_pad(r, 6)); + MP_DIGIT(r, 5) = r5; + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 6; + s_mp_clamp(r); + +CLEANUP: + return res; } - /* Reduces an integer to a field element. */ mp_err ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth) { - return mp_mod(a, &meth->irr, r); + return mp_mod(a, &meth->irr, r); } /* Multiplies two field elements. */ mp_err ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - return mp_mulmod(a, b, &meth->irr, r); + return mp_mulmod(a, b, &meth->irr, r); } /* Squares a field element. */ mp_err ec_GFp_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) { - return mp_sqrmod(a, &meth->irr, r); + return mp_sqrmod(a, &meth->irr, r); } /* Divides two field elements. If a is NULL, then returns the inverse of * b. */ mp_err ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_int t; - - /* If a is NULL, then return the inverse of b, otherwise return a/b. */ - if (a == NULL) { - return mp_invmod(b, &meth->irr, r); - } else { - /* MPI doesn't support divmod, so we implement it using invmod and - * mulmod. */ - MP_CHECKOK(mp_init(&t)); - MP_CHECKOK(mp_invmod(b, &meth->irr, &t)); - MP_CHECKOK(mp_mulmod(a, &t, &meth->irr, r)); - CLEANUP: - mp_clear(&t); - return res; - } + mp_err res = MP_OKAY; + mp_int t; + + /* If a is NULL, then return the inverse of b, otherwise return a/b. */ + if (a == NULL) { + return mp_invmod(b, &meth->irr, r); + } else { + /* MPI doesn't support divmod, so we implement it using invmod and + * mulmod. */ + MP_CHECKOK(mp_init(&t)); + MP_CHECKOK(mp_invmod(b, &meth->irr, &t)); + MP_CHECKOK(mp_mulmod(a, &t, &meth->irr, r)); + CLEANUP: + mp_clear(&t); + return res; + } } /* Wrapper functions for generic binary polynomial field arithmetic. */ @@ -949,9 +894,9 @@ ec_GFp_div(const mp_int *a, const mp_int *b, mp_int *r, /* Adds two field elements. */ mp_err ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - return mp_badd(a, b, r); + return mp_badd(a, b, r); } /* Negates a field element. Note that for binary polynomial fields, the @@ -959,55 +904,55 @@ ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r, mp_err ec_GF2m_neg(const mp_int *a, mp_int *r, const GFMethod *meth) { - if (a == r) { - return MP_OKAY; - } else { - return mp_copy(a, r); - } + if (a == r) { + return MP_OKAY; + } else { + return mp_copy(a, r); + } } /* Reduces a binary polynomial to a field element. */ mp_err ec_GF2m_mod(const mp_int *a, mp_int *r, const GFMethod *meth) { - return mp_bmod(a, meth->irr_arr, r); + return mp_bmod(a, meth->irr_arr, r); } /* Multiplies two field elements. */ mp_err ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - return mp_bmulmod(a, b, meth->irr_arr, r); + return mp_bmulmod(a, b, meth->irr_arr, r); } /* Squares a field element. */ mp_err ec_GF2m_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) { - return mp_bsqrmod(a, meth->irr_arr, r); + return mp_bsqrmod(a, meth->irr_arr, r); } /* Divides two field elements. If a is NULL, then returns the inverse of * b. */ mp_err ec_GF2m_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_int t; - - /* If a is NULL, then return the inverse of b, otherwise return a/b. */ - if (a == NULL) { - /* The GF(2^m) portion of MPI doesn't support invmod, so we - * compute 1/b. */ - MP_CHECKOK(mp_init(&t)); - MP_CHECKOK(mp_set_int(&t, 1)); - MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r)); - CLEANUP: - mp_clear(&t); - return res; - } else { - return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r); - } + mp_err res = MP_OKAY; + mp_int t; + + /* If a is NULL, then return the inverse of b, otherwise return a/b. */ + if (a == NULL) { + /* The GF(2^m) portion of MPI doesn't support invmod, so we + * compute 1/b. */ + MP_CHECKOK(mp_init(&t)); + MP_CHECKOK(mp_set_int(&t, 1)); + MP_CHECKOK(mp_bdivmod(&t, b, &meth->irr, meth->irr_arr, r)); + CLEANUP: + mp_clear(&t); + return res; + } else { + return mp_bdivmod(a, b, &meth->irr, meth->irr_arr, r); + } } diff --git a/nss/lib/freebl/ecl/ecl_mult.c b/nss/lib/freebl/ecl/ecl_mult.c index 5932828..ffbcbf1 100644 --- a/nss/lib/freebl/ecl/ecl_mult.c +++ b/nss/lib/freebl/ecl/ecl_mult.c @@ -8,113 +8,110 @@ #include "ecl-priv.h" #include <stdlib.h> -/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x, - * y). If x, y = NULL, then P is assumed to be the generator (base point) +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k * P(x, + * y). If x, y = NULL, then P is assumed to be the generator (base point) * of the group of points on the elliptic curve. Input and output values * are assumed to be NOT field-encoded. */ mp_err ECPoint_mul(const ECGroup *group, const mp_int *k, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry) + const mp_int *py, mp_int *rx, mp_int *ry) { - mp_err res = MP_OKAY; - mp_int kt; + mp_err res = MP_OKAY; + mp_int kt; - ARGCHK((k != NULL) && (group != NULL), MP_BADARG); - MP_DIGITS(&kt) = 0; + ARGCHK((k != NULL) && (group != NULL), MP_BADARG); + MP_DIGITS(&kt) = 0; - /* want scalar to be less than or equal to group order */ - if (mp_cmp(k, &group->order) > 0) { - MP_CHECKOK(mp_init(&kt)); - MP_CHECKOK(mp_mod(k, &group->order, &kt)); - } else { - MP_SIGN(&kt) = MP_ZPOS; - MP_USED(&kt) = MP_USED(k); - MP_ALLOC(&kt) = MP_ALLOC(k); - MP_DIGITS(&kt) = MP_DIGITS(k); - } + /* want scalar to be less than or equal to group order */ + if (mp_cmp(k, &group->order) > 0) { + MP_CHECKOK(mp_init(&kt)); + MP_CHECKOK(mp_mod(k, &group->order, &kt)); + } else { + MP_SIGN(&kt) = MP_ZPOS; + MP_USED(&kt) = MP_USED(k); + MP_ALLOC(&kt) = MP_ALLOC(k); + MP_DIGITS(&kt) = MP_DIGITS(k); + } - if ((px == NULL) || (py == NULL)) { - if (group->base_point_mul) { - MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group)); - } else { - MP_CHECKOK(group-> - point_mul(&kt, &group->genx, &group->geny, rx, ry, - group)); - } - } else { - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(px, rx, group->meth)); - MP_CHECKOK(group->meth->field_enc(py, ry, group->meth)); - MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group)); - } else { - MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group)); - } - } - if (group->meth->field_dec) { - MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); - } + if ((px == NULL) || (py == NULL)) { + if (group->base_point_mul) { + MP_CHECKOK(group->base_point_mul(&kt, rx, ry, group)); + } else { + MP_CHECKOK(group->point_mul(&kt, &group->genx, &group->geny, rx, ry, + group)); + } + } else { + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(px, rx, group->meth)); + MP_CHECKOK(group->meth->field_enc(py, ry, group->meth)); + MP_CHECKOK(group->point_mul(&kt, rx, ry, rx, ry, group)); + } else { + MP_CHECKOK(group->point_mul(&kt, px, py, rx, ry, group)); + } + } + if (group->meth->field_dec) { + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); + } - CLEANUP: - if (MP_DIGITS(&kt) != MP_DIGITS(k)) { - mp_clear(&kt); - } - return res; +CLEANUP: + if (MP_DIGITS(&kt) != MP_DIGITS(k)) { + mp_clear(&kt); + } + return res; } -/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + * k2 * P(x, y), where G is the generator (base point) of the group of * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. * Input and output values are assumed to be NOT field-encoded. */ mp_err ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group) + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int sx, sy; + mp_err res = MP_OKAY; + mp_int sx, sy; - ARGCHK(group != NULL, MP_BADARG); - ARGCHK(!((k1 == NULL) - && ((k2 == NULL) || (px == NULL) - || (py == NULL))), MP_BADARG); + ARGCHK(group != NULL, MP_BADARG); + ARGCHK(!((k1 == NULL) && ((k2 == NULL) || (px == NULL) || (py == NULL))), MP_BADARG); - /* if some arguments are not defined used ECPoint_mul */ - if (k1 == NULL) { - return ECPoint_mul(group, k2, px, py, rx, ry); - } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { - return ECPoint_mul(group, k1, NULL, NULL, rx, ry); - } + /* if some arguments are not defined used ECPoint_mul */ + if (k1 == NULL) { + return ECPoint_mul(group, k2, px, py, rx, ry); + } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { + return ECPoint_mul(group, k1, NULL, NULL, rx, ry); + } - MP_DIGITS(&sx) = 0; - MP_DIGITS(&sy) = 0; - MP_CHECKOK(mp_init(&sx)); - MP_CHECKOK(mp_init(&sy)); + MP_DIGITS(&sx) = 0; + MP_DIGITS(&sy) = 0; + MP_CHECKOK(mp_init(&sx)); + MP_CHECKOK(mp_init(&sy)); - MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy)); - MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry)); + MP_CHECKOK(ECPoint_mul(group, k1, NULL, NULL, &sx, &sy)); + MP_CHECKOK(ECPoint_mul(group, k2, px, py, rx, ry)); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth)); - MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth)); - MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth)); - } + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(&sx, &sx, group->meth)); + MP_CHECKOK(group->meth->field_enc(&sy, &sy, group->meth)); + MP_CHECKOK(group->meth->field_enc(rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_enc(ry, ry, group->meth)); + } - MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group)); + MP_CHECKOK(group->point_add(&sx, &sy, rx, ry, rx, ry, group)); - if (group->meth->field_dec) { - MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); - } + if (group->meth->field_dec) { + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); + } - CLEANUP: - mp_clear(&sx); - mp_clear(&sy); - return res; +CLEANUP: + mp_clear(&sx); + mp_clear(&sy); + return res; } -/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + * k2 * P(x, y), where G is the generator (base point) of the group of * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. * Input and output values are assumed to be NOT field-encoded. Uses @@ -123,200 +120,186 @@ ec_pts_mul_basic(const mp_int *k1, const mp_int *k2, const mp_int *px, * Elliptic Curves over Prime Fields. */ mp_err ec_pts_mul_simul_w2(const mp_int *k1, const mp_int *k2, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group) + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int precomp[4][4][2]; - const mp_int *a, *b; - unsigned int i, j; - int ai, bi, d; + mp_err res = MP_OKAY; + mp_int precomp[4][4][2]; + const mp_int *a, *b; + unsigned int i, j; + int ai, bi, d; - ARGCHK(group != NULL, MP_BADARG); - ARGCHK(!((k1 == NULL) - && ((k2 == NULL) || (px == NULL) - || (py == NULL))), MP_BADARG); + ARGCHK(group != NULL, MP_BADARG); + ARGCHK(!((k1 == NULL) && ((k2 == NULL) || (px == NULL) || (py == NULL))), MP_BADARG); - /* if some arguments are not defined used ECPoint_mul */ - if (k1 == NULL) { - return ECPoint_mul(group, k2, px, py, rx, ry); - } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { - return ECPoint_mul(group, k1, NULL, NULL, rx, ry); - } + /* if some arguments are not defined used ECPoint_mul */ + if (k1 == NULL) { + return ECPoint_mul(group, k2, px, py, rx, ry); + } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { + return ECPoint_mul(group, k1, NULL, NULL, rx, ry); + } - /* initialize precomputation table */ - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - MP_DIGITS(&precomp[i][j][0]) = 0; - MP_DIGITS(&precomp[i][j][1]) = 0; - } - } - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - MP_CHECKOK( mp_init_size(&precomp[i][j][0], - ECL_MAX_FIELD_SIZE_DIGITS) ); - MP_CHECKOK( mp_init_size(&precomp[i][j][1], - ECL_MAX_FIELD_SIZE_DIGITS) ); - } - } + /* initialize precomputation table */ + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + MP_DIGITS(&precomp[i][j][0]) = 0; + MP_DIGITS(&precomp[i][j][1]) = 0; + } + } + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + MP_CHECKOK(mp_init_size(&precomp[i][j][0], + ECL_MAX_FIELD_SIZE_DIGITS)); + MP_CHECKOK(mp_init_size(&precomp[i][j][1], + ECL_MAX_FIELD_SIZE_DIGITS)); + } + } - /* fill precomputation table */ - /* assign {k1, k2} = {a, b} such that len(a) >= len(b) */ - if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) { - a = k2; - b = k1; - if (group->meth->field_enc) { - MP_CHECKOK(group->meth-> - field_enc(px, &precomp[1][0][0], group->meth)); - MP_CHECKOK(group->meth-> - field_enc(py, &precomp[1][0][1], group->meth)); - } else { - MP_CHECKOK(mp_copy(px, &precomp[1][0][0])); - MP_CHECKOK(mp_copy(py, &precomp[1][0][1])); - } - MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0])); - MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1])); - } else { - a = k1; - b = k2; - MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0])); - MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1])); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth-> - field_enc(px, &precomp[0][1][0], group->meth)); - MP_CHECKOK(group->meth-> - field_enc(py, &precomp[0][1][1], group->meth)); - } else { - MP_CHECKOK(mp_copy(px, &precomp[0][1][0])); - MP_CHECKOK(mp_copy(py, &precomp[0][1][1])); - } - } - /* precompute [*][0][*] */ - mp_zero(&precomp[0][0][0]); - mp_zero(&precomp[0][0][1]); - MP_CHECKOK(group-> - point_dbl(&precomp[1][0][0], &precomp[1][0][1], - &precomp[2][0][0], &precomp[2][0][1], group)); - MP_CHECKOK(group-> - point_add(&precomp[1][0][0], &precomp[1][0][1], - &precomp[2][0][0], &precomp[2][0][1], - &precomp[3][0][0], &precomp[3][0][1], group)); - /* precompute [*][1][*] */ - for (i = 1; i < 4; i++) { - MP_CHECKOK(group-> - point_add(&precomp[0][1][0], &precomp[0][1][1], - &precomp[i][0][0], &precomp[i][0][1], - &precomp[i][1][0], &precomp[i][1][1], group)); - } - /* precompute [*][2][*] */ - MP_CHECKOK(group-> - point_dbl(&precomp[0][1][0], &precomp[0][1][1], - &precomp[0][2][0], &precomp[0][2][1], group)); - for (i = 1; i < 4; i++) { - MP_CHECKOK(group-> - point_add(&precomp[0][2][0], &precomp[0][2][1], - &precomp[i][0][0], &precomp[i][0][1], - &precomp[i][2][0], &precomp[i][2][1], group)); - } - /* precompute [*][3][*] */ - MP_CHECKOK(group-> - point_add(&precomp[0][1][0], &precomp[0][1][1], - &precomp[0][2][0], &precomp[0][2][1], - &precomp[0][3][0], &precomp[0][3][1], group)); - for (i = 1; i < 4; i++) { - MP_CHECKOK(group-> - point_add(&precomp[0][3][0], &precomp[0][3][1], - &precomp[i][0][0], &precomp[i][0][1], - &precomp[i][3][0], &precomp[i][3][1], group)); - } + /* fill precomputation table */ + /* assign {k1, k2} = {a, b} such that len(a) >= len(b) */ + if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) { + a = k2; + b = k1; + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(px, &precomp[1][0][0], group->meth)); + MP_CHECKOK(group->meth->field_enc(py, &precomp[1][0][1], group->meth)); + } else { + MP_CHECKOK(mp_copy(px, &precomp[1][0][0])); + MP_CHECKOK(mp_copy(py, &precomp[1][0][1])); + } + MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0])); + MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1])); + } else { + a = k1; + b = k2; + MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0])); + MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1])); + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(px, &precomp[0][1][0], group->meth)); + MP_CHECKOK(group->meth->field_enc(py, &precomp[0][1][1], group->meth)); + } else { + MP_CHECKOK(mp_copy(px, &precomp[0][1][0])); + MP_CHECKOK(mp_copy(py, &precomp[0][1][1])); + } + } + /* precompute [*][0][*] */ + mp_zero(&precomp[0][0][0]); + mp_zero(&precomp[0][0][1]); + MP_CHECKOK(group->point_dbl(&precomp[1][0][0], &precomp[1][0][1], + &precomp[2][0][0], &precomp[2][0][1], group)); + MP_CHECKOK(group->point_add(&precomp[1][0][0], &precomp[1][0][1], + &precomp[2][0][0], &precomp[2][0][1], + &precomp[3][0][0], &precomp[3][0][1], group)); + /* precompute [*][1][*] */ + for (i = 1; i < 4; i++) { + MP_CHECKOK(group->point_add(&precomp[0][1][0], &precomp[0][1][1], + &precomp[i][0][0], &precomp[i][0][1], + &precomp[i][1][0], &precomp[i][1][1], group)); + } + /* precompute [*][2][*] */ + MP_CHECKOK(group->point_dbl(&precomp[0][1][0], &precomp[0][1][1], + &precomp[0][2][0], &precomp[0][2][1], group)); + for (i = 1; i < 4; i++) { + MP_CHECKOK(group->point_add(&precomp[0][2][0], &precomp[0][2][1], + &precomp[i][0][0], &precomp[i][0][1], + &precomp[i][2][0], &precomp[i][2][1], group)); + } + /* precompute [*][3][*] */ + MP_CHECKOK(group->point_add(&precomp[0][1][0], &precomp[0][1][1], + &precomp[0][2][0], &precomp[0][2][1], + &precomp[0][3][0], &precomp[0][3][1], group)); + for (i = 1; i < 4; i++) { + MP_CHECKOK(group->point_add(&precomp[0][3][0], &precomp[0][3][1], + &precomp[i][0][0], &precomp[i][0][1], + &precomp[i][3][0], &precomp[i][3][1], group)); + } - d = (mpl_significant_bits(a) + 1) / 2; + d = (mpl_significant_bits(a) + 1) / 2; - /* R = inf */ - mp_zero(rx); - mp_zero(ry); + /* R = inf */ + mp_zero(rx); + mp_zero(ry); - for (i = d; i-- > 0;) { - ai = MP_GET_BIT(a, 2 * i + 1); - ai <<= 1; - ai |= MP_GET_BIT(a, 2 * i); - bi = MP_GET_BIT(b, 2 * i + 1); - bi <<= 1; - bi |= MP_GET_BIT(b, 2 * i); - /* R = 2^2 * R */ - MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); - MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); - /* R = R + (ai * A + bi * B) */ - MP_CHECKOK(group-> - point_add(rx, ry, &precomp[ai][bi][0], - &precomp[ai][bi][1], rx, ry, group)); - } + for (i = d; i-- > 0;) { + ai = MP_GET_BIT(a, 2 * i + 1); + ai <<= 1; + ai |= MP_GET_BIT(a, 2 * i); + bi = MP_GET_BIT(b, 2 * i + 1); + bi <<= 1; + bi |= MP_GET_BIT(b, 2 * i); + /* R = 2^2 * R */ + MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); + MP_CHECKOK(group->point_dbl(rx, ry, rx, ry, group)); + /* R = R + (ai * A + bi * B) */ + MP_CHECKOK(group->point_add(rx, ry, &precomp[ai][bi][0], + &precomp[ai][bi][1], rx, ry, group)); + } - if (group->meth->field_dec) { - MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); - } + if (group->meth->field_dec) { + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); + } - CLEANUP: - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - mp_clear(&precomp[i][j][0]); - mp_clear(&precomp[i][j][1]); - } - } - return res; +CLEANUP: + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + mp_clear(&precomp[i][j][0]); + mp_clear(&precomp[i][j][1]); + } + } + return res; } -/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + * k2 * P(x, y), where G is the generator (base point) of the group of * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. * Input and output values are assumed to be NOT field-encoded. */ mp_err ECPoints_mul(const ECGroup *group, const mp_int *k1, const mp_int *k2, - const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry) + const mp_int *px, const mp_int *py, mp_int *rx, mp_int *ry) { - mp_err res = MP_OKAY; - mp_int k1t, k2t; - const mp_int *k1p, *k2p; + mp_err res = MP_OKAY; + mp_int k1t, k2t; + const mp_int *k1p, *k2p; - MP_DIGITS(&k1t) = 0; - MP_DIGITS(&k2t) = 0; + MP_DIGITS(&k1t) = 0; + MP_DIGITS(&k2t) = 0; - ARGCHK(group != NULL, MP_BADARG); + ARGCHK(group != NULL, MP_BADARG); - /* want scalar to be less than or equal to group order */ - if (k1 != NULL) { - if (mp_cmp(k1, &group->order) >= 0) { - MP_CHECKOK(mp_init(&k1t)); - MP_CHECKOK(mp_mod(k1, &group->order, &k1t)); - k1p = &k1t; - } else { - k1p = k1; - } - } else { - k1p = k1; - } - if (k2 != NULL) { - if (mp_cmp(k2, &group->order) >= 0) { - MP_CHECKOK(mp_init(&k2t)); - MP_CHECKOK(mp_mod(k2, &group->order, &k2t)); - k2p = &k2t; - } else { - k2p = k2; - } - } else { - k2p = k2; - } + /* want scalar to be less than or equal to group order */ + if (k1 != NULL) { + if (mp_cmp(k1, &group->order) >= 0) { + MP_CHECKOK(mp_init(&k1t)); + MP_CHECKOK(mp_mod(k1, &group->order, &k1t)); + k1p = &k1t; + } else { + k1p = k1; + } + } else { + k1p = k1; + } + if (k2 != NULL) { + if (mp_cmp(k2, &group->order) >= 0) { + MP_CHECKOK(mp_init(&k2t)); + MP_CHECKOK(mp_mod(k2, &group->order, &k2t)); + k2p = &k2t; + } else { + k2p = k2; + } + } else { + k2p = k2; + } - /* if points_mul is defined, then use it */ - if (group->points_mul) { - res = group->points_mul(k1p, k2p, px, py, rx, ry, group); - } else { - res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); - } + /* if points_mul is defined, then use it */ + if (group->points_mul) { + res = group->points_mul(k1p, k2p, px, py, rx, ry, group); + } else { + res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); + } - CLEANUP: - mp_clear(&k1t); - mp_clear(&k2t); - return res; +CLEANUP: + mp_clear(&k1t); + mp_clear(&k2t); + return res; } diff --git a/nss/lib/freebl/ecl/ecp.h b/nss/lib/freebl/ecl/ecp.h index 4784b02..7e54e4e 100644 --- a/nss/lib/freebl/ecl/ecp.h +++ b/nss/lib/freebl/ecl/ecp.h @@ -16,17 +16,17 @@ mp_err ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py); /* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx, * qy). Uses affine coordinates. */ mp_err ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, const ECGroup *group); + const mp_int *qx, const mp_int *qy, mp_int *rx, + mp_int *ry, const ECGroup *group); /* Computes R = P - Q. Uses affine coordinates. */ mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, const ECGroup *group); + const mp_int *qx, const mp_int *qy, mp_int *rx, + mp_int *ry, const ECGroup *group); /* Computes R = 2P. Uses affine coordinates. */ mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group); + mp_int *ry, const ECGroup *group); /* Validates a point on a GFp curve. */ mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group); @@ -36,25 +36,25 @@ mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup * * a, b and p are the elliptic curve coefficients and the prime that * determines the field GFp. Uses affine coordinates. */ mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group); #endif /* Converts a point P(px, py) from affine coordinates to Jacobian * projective coordinates R(rx, ry, rz). */ mp_err ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, mp_int *rz, const ECGroup *group); + mp_int *ry, mp_int *rz, const ECGroup *group); /* Converts a point P(px, py, pz) from Jacobian projective coordinates to * affine coordinates R(rx, ry). */ mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, - const mp_int *pz, mp_int *rx, mp_int *ry, - const ECGroup *group); + const mp_int *pz, mp_int *rx, mp_int *ry, + const ECGroup *group); /* Checks if point P(px, py, pz) is at infinity. Uses Jacobian * coordinates. */ mp_err ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, - const mp_int *pz); + const mp_int *pz); /* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian * coordinates. */ @@ -63,22 +63,22 @@ mp_err ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz); /* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is * (qx, qy, qz). Uses Jacobian coordinates. */ mp_err ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, - const mp_int *pz, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, - mp_int *rz, const ECGroup *group); + const mp_int *pz, const mp_int *qx, + const mp_int *qy, mp_int *rx, mp_int *ry, + mp_int *rz, const ECGroup *group); /* Computes R = 2P. Uses Jacobian coordinates. */ mp_err ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, - const mp_int *pz, mp_int *rx, mp_int *ry, - mp_int *rz, const ECGroup *group); + const mp_int *pz, mp_int *rx, mp_int *ry, + mp_int *rz, const ECGroup *group); #ifdef ECL_ENABLE_GFP_PT_MUL_JAC /* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters * a, b and p are the elliptic curve coefficients and the prime that * determines the field GFp. Uses Jacobian coordinates. */ mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group); #endif /* Computes R(x, y) = k1 * G + k2 * P(x, y), where G is the generator @@ -87,9 +87,9 @@ mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, * coordinates. Input and output values are assumed to be NOT * field-encoded and are in affine form. */ mp_err - ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group); +ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group); /* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic * curve points P and R can be identical. Uses mixed Modified-Jacobian @@ -97,10 +97,10 @@ mp_err * additions. Assumes input is already field-encoded using field_enc, and * returns output that is still field-encoded. Uses 5-bit window NAF * method (algorithm 11) for scalar-point multiplication from Brown, - * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic + * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic * Curves Over Prime Fields. */ mp_err - ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group); +ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, + mp_int *rx, mp_int *ry, const ECGroup *group); -#endif /* __ecp_h_ */ +#endif /* __ecp_h_ */ diff --git a/nss/lib/freebl/ecl/ecp_192.c b/nss/lib/freebl/ecl/ecp_192.c deleted file mode 100644 index 0bfd95e..0000000 --- a/nss/lib/freebl/ecl/ecp_192.c +++ /dev/null @@ -1,493 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp.h" -#include "mpi.h" -#include "mplogic.h" -#include "mpi-priv.h" - -#define ECP192_DIGITS ECL_CURVE_DIGITS(192) - -/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses - * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software - * Implementation of the NIST Elliptic Curves over Prime Fields. */ -static mp_err -ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_size a_used = MP_USED(a); - mp_digit r3; -#ifndef MPI_AMD64_ADD - mp_digit carry; -#endif -#ifdef ECL_THIRTY_TWO_BIT - mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0; - mp_digit r0a, r0b, r1a, r1b, r2a, r2b; -#else - mp_digit a5 = 0, a4 = 0, a3 = 0; - mp_digit r0, r1, r2; -#endif - - /* reduction not needed if a is not larger than field size */ - if (a_used < ECP192_DIGITS) { - if (a == r) { - return MP_OKAY; - } - return mp_copy(a, r); - } - - /* for polynomials larger than twice the field size, use regular - * reduction */ - if (a_used > ECP192_DIGITS*2) { - MP_CHECKOK(mp_mod(a, &meth->irr, r)); - } else { - /* copy out upper words of a */ - -#ifdef ECL_THIRTY_TWO_BIT - - /* in all the math below, - * nXb is most signifiant, nXa is least significant */ - switch (a_used) { - case 12: - a5b = MP_DIGIT(a, 11); - case 11: - a5a = MP_DIGIT(a, 10); - case 10: - a4b = MP_DIGIT(a, 9); - case 9: - a4a = MP_DIGIT(a, 8); - case 8: - a3b = MP_DIGIT(a, 7); - case 7: - a3a = MP_DIGIT(a, 6); - } - - - r2b= MP_DIGIT(a, 5); - r2a= MP_DIGIT(a, 4); - r1b = MP_DIGIT(a, 3); - r1a = MP_DIGIT(a, 2); - r0b = MP_DIGIT(a, 1); - r0a = MP_DIGIT(a, 0); - - /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */ - carry = 0; - MP_ADD_CARRY(r0a, a3a, r0a, carry); - MP_ADD_CARRY(r0b, a3b, r0b, carry); - MP_ADD_CARRY(r1a, a3a, r1a, carry); - MP_ADD_CARRY(r1b, a3b, r1b, carry); - MP_ADD_CARRY(r2a, a4a, r2a, carry); - MP_ADD_CARRY(r2b, a4b, r2b, carry); - r3 = carry; carry = 0; - MP_ADD_CARRY(r0a, a5a, r0a, carry); - MP_ADD_CARRY(r0b, a5b, r0b, carry); - MP_ADD_CARRY(r1a, a5a, r1a, carry); - MP_ADD_CARRY(r1b, a5b, r1b, carry); - MP_ADD_CARRY(r2a, a5a, r2a, carry); - MP_ADD_CARRY(r2b, a5b, r2b, carry); - r3 += carry; carry = 0; - MP_ADD_CARRY(r1a, a4a, r1a, carry); - MP_ADD_CARRY(r1b, a4b, r1b, carry); - MP_ADD_CARRY(r2a, 0, r2a, carry); - MP_ADD_CARRY(r2b, 0, r2b, carry); - r3 += carry; - - /* reduce out the carry */ - while (r3) { - carry = 0; - MP_ADD_CARRY(r0a, r3, r0a, carry); - MP_ADD_CARRY(r0b, 0, r0b, carry); - MP_ADD_CARRY(r1a, r3, r1a, carry); - MP_ADD_CARRY(r1b, 0, r1b, carry); - MP_ADD_CARRY(r2a, 0, r2a, carry); - MP_ADD_CARRY(r2b, 0, r2b, carry); - r3 = carry; - } - - /* check for final reduction */ - /* - * our field is 0xffffffffffffffff, 0xfffffffffffffffe, - * 0xffffffffffffffff. That means we can only be over and need - * one more reduction - * if r2 == 0xffffffffffffffffff (same as r2+1 == 0) - * and - * r1 == 0xffffffffffffffffff or - * r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff - * In all cases, we subtract the field (or add the 2's - * complement value (1,1,0)). (r0, r1, r2) - */ - if (((r2b == 0xffffffff) && (r2a == 0xffffffff) - && (r1b == 0xffffffff) ) && - ((r1a == 0xffffffff) || - ((r1a == 0xfffffffe) && (r0a == 0xffffffff) && - (r0b == 0xffffffff))) ) { - /* do a quick subtract */ - carry = 0; - MP_ADD_CARRY(r0a, 1, r0a, carry); - MP_ADD_CARRY(r0b, carry, r0a, carry); - r1a += 1+carry; - r1b = r2a = r2b = 0; - } - - /* set the lower words of r */ - if (a != r) { - MP_CHECKOK(s_mp_pad(r, 6)); - } - MP_DIGIT(r, 5) = r2b; - MP_DIGIT(r, 4) = r2a; - MP_DIGIT(r, 3) = r1b; - MP_DIGIT(r, 2) = r1a; - MP_DIGIT(r, 1) = r0b; - MP_DIGIT(r, 0) = r0a; - MP_USED(r) = 6; -#else - switch (a_used) { - case 6: - a5 = MP_DIGIT(a, 5); - case 5: - a4 = MP_DIGIT(a, 4); - case 4: - a3 = MP_DIGIT(a, 3); - } - - r2 = MP_DIGIT(a, 2); - r1 = MP_DIGIT(a, 1); - r0 = MP_DIGIT(a, 0); - - /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */ -#ifndef MPI_AMD64_ADD - carry = 0; - MP_ADD_CARRY(r0, a3, r0, carry); - MP_ADD_CARRY(r1, a3, r1, carry); - MP_ADD_CARRY(r2, a4, r2, carry); - r3 = carry; carry = 0; - MP_ADD_CARRY(r0, a5, r0, carry); - MP_ADD_CARRY(r1, a5, r1, carry); - MP_ADD_CARRY(r2, a5, r2, carry); - r3 += carry; carry = 0; - MP_ADD_CARRY(r1, a4, r1, carry); - MP_ADD_CARRY(r2, 0, r2, carry); - r3 += carry; - -#else - r2 = MP_DIGIT(a, 2); - r1 = MP_DIGIT(a, 1); - r0 = MP_DIGIT(a, 0); - - /* set the lower words of r */ - __asm__ ( - "xorq %3,%3 \n\t" - "addq %4,%0 \n\t" - "adcq %4,%1 \n\t" - "adcq %5,%2 \n\t" - "adcq $0,%3 \n\t" - "addq %6,%0 \n\t" - "adcq %6,%1 \n\t" - "adcq %6,%2 \n\t" - "adcq $0,%3 \n\t" - "addq %5,%1 \n\t" - "adcq $0,%2 \n\t" - "adcq $0,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3), - "=r"(a4), "=r"(a5) - : "0" (r0), "1" (r1), "2" (r2), "3" (r3), - "4" (a3), "5" (a4), "6"(a5) - : "%cc" ); -#endif - - /* reduce out the carry */ - while (r3) { -#ifndef MPI_AMD64_ADD - carry = 0; - MP_ADD_CARRY(r0, r3, r0, carry); - MP_ADD_CARRY(r1, r3, r1, carry); - MP_ADD_CARRY(r2, 0, r2, carry); - r3 = carry; -#else - a3=r3; - __asm__ ( - "xorq %3,%3 \n\t" - "addq %4,%0 \n\t" - "adcq %4,%1 \n\t" - "adcq $0,%2 \n\t" - "adcq $0,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3) - : "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3) - : "%cc" ); -#endif - } - - /* check for final reduction */ - /* - * our field is 0xffffffffffffffff, 0xfffffffffffffffe, - * 0xffffffffffffffff. That means we can only be over and need - * one more reduction - * if r2 == 0xffffffffffffffffff (same as r2+1 == 0) - * and - * r1 == 0xffffffffffffffffff or - * r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff - * In all cases, we subtract the field (or add the 2's - * complement value (1,1,0)). (r0, r1, r2) - */ - if (r3 || ((r2 == MP_DIGIT_MAX) && - ((r1 == MP_DIGIT_MAX) || - ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) { - /* do a quick subtract */ - carry = 0; - MP_ADD_CARRY(r0, 1, r0, carry); - r1 += 1+carry; - r2 = 0; - } - /* set the lower words of r */ - if (a != r) { - MP_CHECKOK(s_mp_pad(r, 3)); - } - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_USED(r) = 3; -#endif - } - s_mp_clamp(r); - CLEANUP: - return res; -} - -#ifndef ECL_THIRTY_TWO_BIT -/* Compute the sum of 192 bit curves. Do the work in-line since the - * number of words are so small, we don't want to overhead of mp function - * calls. Uses optimized modular reduction for p192. - */ -static mp_err -ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit a0 = 0, a1 = 0, a2 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0; - mp_digit carry; - - switch(MP_USED(a)) { - case 3: - a2 = MP_DIGIT(a,2); - case 2: - a1 = MP_DIGIT(a,1); - case 1: - a0 = MP_DIGIT(a,0); - } - switch(MP_USED(b)) { - case 3: - r2 = MP_DIGIT(b,2); - case 2: - r1 = MP_DIGIT(b,1); - case 1: - r0 = MP_DIGIT(b,0); - } - -#ifndef MPI_AMD64_ADD - carry = 0; - MP_ADD_CARRY(a0, r0, r0, carry); - MP_ADD_CARRY(a1, r1, r1, carry); - MP_ADD_CARRY(a2, r2, r2, carry); -#else - __asm__ ( - "xorq %3,%3 \n\t" - "addq %4,%0 \n\t" - "adcq %5,%1 \n\t" - "adcq %6,%2 \n\t" - "adcq $0,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry) - : "r" (a0), "r" (a1), "r" (a2), "0" (r0), - "1" (r1), "2" (r2) - : "%cc" ); -#endif - - /* Do quick 'subract' if we've gone over - * (add the 2's complement of the curve field) */ - if (carry || ((r2 == MP_DIGIT_MAX) && - ((r1 == MP_DIGIT_MAX) || - ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) { -#ifndef MPI_AMD64_ADD - carry = 0; - MP_ADD_CARRY(r0, 1, r0, carry); - MP_ADD_CARRY(r1, 1, r1, carry); - MP_ADD_CARRY(r2, 0, r2, carry); -#else - __asm__ ( - "addq $1,%0 \n\t" - "adcq $1,%1 \n\t" - "adcq $0,%2 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2) - : "0" (r0), "1" (r1), "2" (r2) - : "%cc" ); -#endif - } - - - MP_CHECKOK(s_mp_pad(r, 3)); - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 3; - s_mp_clamp(r); - - - CLEANUP: - return res; -} - -/* Compute the diff of 192 bit curves. Do the work in-line since the - * number of words are so small, we don't want to overhead of mp function - * calls. Uses optimized modular reduction for p192. - */ -static mp_err -ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_digit b0 = 0, b1 = 0, b2 = 0; - mp_digit r0 = 0, r1 = 0, r2 = 0; - mp_digit borrow; - - switch(MP_USED(a)) { - case 3: - r2 = MP_DIGIT(a,2); - case 2: - r1 = MP_DIGIT(a,1); - case 1: - r0 = MP_DIGIT(a,0); - } - - switch(MP_USED(b)) { - case 3: - b2 = MP_DIGIT(b,2); - case 2: - b1 = MP_DIGIT(b,1); - case 1: - b0 = MP_DIGIT(b,0); - } - -#ifndef MPI_AMD64_ADD - borrow = 0; - MP_SUB_BORROW(r0, b0, r0, borrow); - MP_SUB_BORROW(r1, b1, r1, borrow); - MP_SUB_BORROW(r2, b2, r2, borrow); -#else - __asm__ ( - "xorq %3,%3 \n\t" - "subq %4,%0 \n\t" - "sbbq %5,%1 \n\t" - "sbbq %6,%2 \n\t" - "adcq $0,%3 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow) - : "r" (b0), "r" (b1), "r" (b2), "0" (r0), - "1" (r1), "2" (r2) - : "%cc" ); -#endif - - /* Do quick 'add' if we've gone under 0 - * (subtract the 2's complement of the curve field) */ - if (borrow) { -#ifndef MPI_AMD64_ADD - borrow = 0; - MP_SUB_BORROW(r0, 1, r0, borrow); - MP_SUB_BORROW(r1, 1, r1, borrow); - MP_SUB_BORROW(r2, 0, r2, borrow); -#else - __asm__ ( - "subq $1,%0 \n\t" - "sbbq $1,%1 \n\t" - "sbbq $0,%2 \n\t" - : "=r"(r0), "=r"(r1), "=r"(r2) - : "0" (r0), "1" (r1), "2" (r2) - : "%cc" ); -#endif - } - - MP_CHECKOK(s_mp_pad(r, 3)); - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 3; - s_mp_clamp(r); - - CLEANUP: - return res; -} - -#endif - -/* Compute the square of polynomial a, reduce modulo p192. Store the - * result in r. r could be a. Uses optimized modular reduction for p192. - */ -static mp_err -ec_GFp_nistp192_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - - MP_CHECKOK(mp_sqr(a, r)); - MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth)); - CLEANUP: - return res; -} - -/* Compute the product of two polynomials a and b, reduce modulo p192. - * Store the result in r. r could be a or b; a could be b. Uses - * optimized modular reduction for p192. */ -static mp_err -ec_GFp_nistp192_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - - MP_CHECKOK(mp_mul(a, b, r)); - MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth)); - CLEANUP: - return res; -} - -/* Divides two field elements. If a is NULL, then returns the inverse of - * b. */ -static mp_err -ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_int t; - - /* If a is NULL, then return the inverse of b, otherwise return a/b. */ - if (a == NULL) { - return mp_invmod(b, &meth->irr, r); - } else { - /* MPI doesn't support divmod, so we implement it using invmod and - * mulmod. */ - MP_CHECKOK(mp_init(&t)); - MP_CHECKOK(mp_invmod(b, &meth->irr, &t)); - MP_CHECKOK(mp_mul(a, &t, r)); - MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth)); - CLEANUP: - mp_clear(&t); - return res; - } -} - -/* Wire in fast field arithmetic and precomputation of base point for - * named curves. */ -mp_err -ec_group_set_gfp192(ECGroup *group, ECCurveName name) -{ - if (name == ECCurve_NIST_P192) { - group->meth->field_mod = &ec_GFp_nistp192_mod; - group->meth->field_mul = &ec_GFp_nistp192_mul; - group->meth->field_sqr = &ec_GFp_nistp192_sqr; - group->meth->field_div = &ec_GFp_nistp192_div; -#ifndef ECL_THIRTY_TWO_BIT - group->meth->field_add = &ec_GFp_nistp192_add; - group->meth->field_sub = &ec_GFp_nistp192_sub; -#endif - } - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ecp_224.c b/nss/lib/freebl/ecl/ecp_224.c deleted file mode 100644 index 142f255..0000000 --- a/nss/lib/freebl/ecl/ecp_224.c +++ /dev/null @@ -1,352 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp.h" -#include "mpi.h" -#include "mplogic.h" -#include "mpi-priv.h" - -#define ECP224_DIGITS ECL_CURVE_DIGITS(224) - -/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses - * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software - * Implementation of the NIST Elliptic Curves over Prime Fields. */ -static mp_err -ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_size a_used = MP_USED(a); - - int r3b; - mp_digit carry; -#ifdef ECL_THIRTY_TWO_BIT - mp_digit a6a = 0, a6b = 0, - a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3b = 0; - mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a; -#else - mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0; - mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0; - mp_digit r0, r1, r2, r3; -#endif - - /* reduction not needed if a is not larger than field size */ - if (a_used < ECP224_DIGITS) { - if (a == r) return MP_OKAY; - return mp_copy(a, r); - } - /* for polynomials larger than twice the field size, use regular - * reduction */ - if (a_used > ECL_CURVE_DIGITS(224*2)) { - MP_CHECKOK(mp_mod(a, &meth->irr, r)); - } else { -#ifdef ECL_THIRTY_TWO_BIT - /* copy out upper words of a */ - switch (a_used) { - case 14: - a6b = MP_DIGIT(a, 13); - case 13: - a6a = MP_DIGIT(a, 12); - case 12: - a5b = MP_DIGIT(a, 11); - case 11: - a5a = MP_DIGIT(a, 10); - case 10: - a4b = MP_DIGIT(a, 9); - case 9: - a4a = MP_DIGIT(a, 8); - case 8: - a3b = MP_DIGIT(a, 7); - } - r3a = MP_DIGIT(a, 6); - r2b= MP_DIGIT(a, 5); - r2a= MP_DIGIT(a, 4); - r1b = MP_DIGIT(a, 3); - r1a = MP_DIGIT(a, 2); - r0b = MP_DIGIT(a, 1); - r0a = MP_DIGIT(a, 0); - - - /* implement r = (a3a,a2,a1,a0) - +(a5a, a4,a3b, 0) - +( 0, a6,a5b, 0) - -( 0 0, 0|a6b, a6a|a5b ) - -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */ - carry = 0; - MP_ADD_CARRY (r1b, a3b, r1b, carry); - MP_ADD_CARRY (r2a, a4a, r2a, carry); - MP_ADD_CARRY (r2b, a4b, r2b, carry); - MP_ADD_CARRY (r3a, a5a, r3a, carry); - r3b = carry; carry = 0; - MP_ADD_CARRY (r1b, a5b, r1b, carry); - MP_ADD_CARRY (r2a, a6a, r2a, carry); - MP_ADD_CARRY (r2b, a6b, r2b, carry); - MP_ADD_CARRY (r3a, 0, r3a, carry); - r3b += carry; carry = 0; - MP_SUB_BORROW(r0a, a3b, r0a, carry); - MP_SUB_BORROW(r0b, a4a, r0b, carry); - MP_SUB_BORROW(r1a, a4b, r1a, carry); - MP_SUB_BORROW(r1b, a5a, r1b, carry); - MP_SUB_BORROW(r2a, a5b, r2a, carry); - MP_SUB_BORROW(r2b, a6a, r2b, carry); - MP_SUB_BORROW(r3a, a6b, r3a, carry); - r3b -= carry; carry = 0; - MP_SUB_BORROW(r0a, a5b, r0a, carry); - MP_SUB_BORROW(r0b, a6a, r0b, carry); - MP_SUB_BORROW(r1a, a6b, r1a, carry); - if (carry) { - MP_SUB_BORROW(r1b, 0, r1b, carry); - MP_SUB_BORROW(r2a, 0, r2a, carry); - MP_SUB_BORROW(r2b, 0, r2b, carry); - MP_SUB_BORROW(r3a, 0, r3a, carry); - r3b -= carry; - } - - while (r3b > 0) { - int tmp; - carry = 0; - MP_ADD_CARRY(r1b, r3b, r1b, carry); - if (carry) { - MP_ADD_CARRY(r2a, 0, r2a, carry); - MP_ADD_CARRY(r2b, 0, r2b, carry); - MP_ADD_CARRY(r3a, 0, r3a, carry); - } - tmp = carry; carry = 0; - MP_SUB_BORROW(r0a, r3b, r0a, carry); - if (carry) { - MP_SUB_BORROW(r0b, 0, r0b, carry); - MP_SUB_BORROW(r1a, 0, r1a, carry); - MP_SUB_BORROW(r1b, 0, r1b, carry); - MP_SUB_BORROW(r2a, 0, r2a, carry); - MP_SUB_BORROW(r2b, 0, r2b, carry); - MP_SUB_BORROW(r3a, 0, r3a, carry); - tmp -= carry; - } - r3b = tmp; - } - - while (r3b < 0) { - mp_digit maxInt = MP_DIGIT_MAX; - carry = 0; - MP_ADD_CARRY (r0a, 1, r0a, carry); - MP_ADD_CARRY (r0b, 0, r0b, carry); - MP_ADD_CARRY (r1a, 0, r1a, carry); - MP_ADD_CARRY (r1b, maxInt, r1b, carry); - MP_ADD_CARRY (r2a, maxInt, r2a, carry); - MP_ADD_CARRY (r2b, maxInt, r2b, carry); - MP_ADD_CARRY (r3a, maxInt, r3a, carry); - r3b += carry; - } - /* check for final reduction */ - /* now the only way we are over is if the top 4 words are all ones */ - if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX) - && (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) && - ((r1a != 0) || (r0b != 0) || (r0a != 0)) ) { - /* one last subraction */ - carry = 0; - MP_SUB_BORROW(r0a, 1, r0a, carry); - MP_SUB_BORROW(r0b, 0, r0b, carry); - MP_SUB_BORROW(r1a, 0, r1a, carry); - r1b = r2a = r2b = r3a = 0; - } - - - if (a != r) { - MP_CHECKOK(s_mp_pad(r, 7)); - } - /* set the lower words of r */ - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 7; - MP_DIGIT(r, 6) = r3a; - MP_DIGIT(r, 5) = r2b; - MP_DIGIT(r, 4) = r2a; - MP_DIGIT(r, 3) = r1b; - MP_DIGIT(r, 2) = r1a; - MP_DIGIT(r, 1) = r0b; - MP_DIGIT(r, 0) = r0a; -#else - /* copy out upper words of a */ - switch (a_used) { - case 7: - a6 = MP_DIGIT(a, 6); - a6b = a6 >> 32; - a6a_a5b = a6 << 32; - case 6: - a5 = MP_DIGIT(a, 5); - a5b = a5 >> 32; - a6a_a5b |= a5b; - a5b = a5b << 32; - a5a_a4b = a5 << 32; - a5a = a5 & 0xffffffff; - case 5: - a4 = MP_DIGIT(a, 4); - a5a_a4b |= a4 >> 32; - a4a_a3b = a4 << 32; - case 4: - a3b = MP_DIGIT(a, 3) >> 32; - a4a_a3b |= a3b; - a3b = a3b << 32; - } - - r3 = MP_DIGIT(a, 3) & 0xffffffff; - r2 = MP_DIGIT(a, 2); - r1 = MP_DIGIT(a, 1); - r0 = MP_DIGIT(a, 0); - - /* implement r = (a3a,a2,a1,a0) - +(a5a, a4,a3b, 0) - +( 0, a6,a5b, 0) - -( 0 0, 0|a6b, a6a|a5b ) - -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */ - carry = 0; - MP_ADD_CARRY (r1, a3b, r1, carry); - MP_ADD_CARRY (r2, a4 , r2, carry); - MP_ADD_CARRY (r3, a5a, r3, carry); - carry = 0; - MP_ADD_CARRY (r1, a5b, r1, carry); - MP_ADD_CARRY (r2, a6 , r2, carry); - MP_ADD_CARRY (r3, 0, r3, carry); - - carry = 0; - MP_SUB_BORROW(r0, a4a_a3b, r0, carry); - MP_SUB_BORROW(r1, a5a_a4b, r1, carry); - MP_SUB_BORROW(r2, a6a_a5b, r2, carry); - MP_SUB_BORROW(r3, a6b , r3, carry); - carry = 0; - MP_SUB_BORROW(r0, a6a_a5b, r0, carry); - MP_SUB_BORROW(r1, a6b , r1, carry); - if (carry) { - MP_SUB_BORROW(r2, 0, r2, carry); - MP_SUB_BORROW(r3, 0, r3, carry); - } - - - /* if the value is negative, r3 has a 2's complement - * high value */ - r3b = (int)(r3 >>32); - while (r3b > 0) { - r3 &= 0xffffffff; - carry = 0; - MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, carry); - if (carry) { - MP_ADD_CARRY(r2, 0, r2, carry); - MP_ADD_CARRY(r3, 0, r3, carry); - } - carry = 0; - MP_SUB_BORROW(r0, r3b, r0, carry); - if (carry) { - MP_SUB_BORROW(r1, 0, r1, carry); - MP_SUB_BORROW(r2, 0, r2, carry); - MP_SUB_BORROW(r3, 0, r3, carry); - } - r3b = (int)(r3 >>32); - } - - while (r3b < 0) { - carry = 0; - MP_ADD_CARRY (r0, 1, r0, carry); - MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry); - MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry); - MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry); - r3b = (int)(r3 >>32); - } - /* check for final reduction */ - /* now the only way we are over is if the top 4 words are - * all ones. Subtract the curve. (curve is 2^224 - 2^96 +1) - */ - if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX) - && ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) && - ((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) { - /* one last subraction */ - carry = 0; - MP_SUB_BORROW(r0, 1, r0, carry); - MP_SUB_BORROW(r1, MP_DIGIT_MAX << 32, r1, carry); - r2 = r3 = 0; - } - - - if (a != r) { - MP_CHECKOK(s_mp_pad(r, 4)); - } - /* set the lower words of r */ - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 4; - MP_DIGIT(r, 3) = r3; - MP_DIGIT(r, 2) = r2; - MP_DIGIT(r, 1) = r1; - MP_DIGIT(r, 0) = r0; -#endif - } - s_mp_clamp(r); - - CLEANUP: - return res; -} - -/* Compute the square of polynomial a, reduce modulo p224. Store the - * result in r. r could be a. Uses optimized modular reduction for p224. - */ -static mp_err -ec_GFp_nistp224_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) -{ - mp_err res = MP_OKAY; - - MP_CHECKOK(mp_sqr(a, r)); - MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth)); - CLEANUP: - return res; -} - -/* Compute the product of two polynomials a and b, reduce modulo p224. - * Store the result in r. r could be a or b; a could be b. Uses - * optimized modular reduction for p224. */ -static mp_err -ec_GFp_nistp224_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - - MP_CHECKOK(mp_mul(a, b, r)); - MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth)); - CLEANUP: - return res; -} - -/* Divides two field elements. If a is NULL, then returns the inverse of - * b. */ -static mp_err -ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) -{ - mp_err res = MP_OKAY; - mp_int t; - - /* If a is NULL, then return the inverse of b, otherwise return a/b. */ - if (a == NULL) { - return mp_invmod(b, &meth->irr, r); - } else { - /* MPI doesn't support divmod, so we implement it using invmod and - * mulmod. */ - MP_CHECKOK(mp_init(&t)); - MP_CHECKOK(mp_invmod(b, &meth->irr, &t)); - MP_CHECKOK(mp_mul(a, &t, r)); - MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth)); - CLEANUP: - mp_clear(&t); - return res; - } -} - -/* Wire in fast field arithmetic and precomputation of base point for - * named curves. */ -mp_err -ec_group_set_gfp224(ECGroup *group, ECCurveName name) -{ - if (name == ECCurve_NIST_P224) { - group->meth->field_mod = &ec_GFp_nistp224_mod; - group->meth->field_mul = &ec_GFp_nistp224_mul; - group->meth->field_sqr = &ec_GFp_nistp224_sqr; - group->meth->field_div = &ec_GFp_nistp224_div; - } - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ecp_25519.c b/nss/lib/freebl/ecl/ecp_25519.c new file mode 100644 index 0000000..a8d4152 --- /dev/null +++ b/nss/lib/freebl/ecl/ecp_25519.c @@ -0,0 +1,120 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* curve 25519 https://www.rfc-editor.org/rfc/rfc7748.txt */ + +#ifdef FREEBL_NO_DEPEND +#include "../stubs.h" +#endif + +#include "ecl-priv.h" +#include "ecp.h" +#include "mpi.h" +#include "mplogic.h" +#include "mpi-priv.h" +#include "secmpi.h" +#include "secitem.h" +#include "secport.h" +#include <stdlib.h> +#include <stdio.h> + +/* + * point validation is not necessary in general. But this checks a point (px) + * against some known bad values. + */ +SECStatus +ec_Curve25519_pt_validate(const SECItem *px) +{ + PRUint8 *p; + int i; + PRUint8 forbiddenValues[12][32] = { + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, + 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, + 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, + 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x00 }, + { 0x5f, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, + 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, + 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, + 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0x57 }, + { 0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + { 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + { 0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f }, + { 0xcd, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, + 0x16, 0x56, 0xe3, 0xfa, 0xf1, 0x9f, 0xc4, 0x6a, + 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32, 0xb1, 0xfd, + 0x86, 0x62, 0x05, 0x16, 0x5f, 0x49, 0xb8, 0x80 }, + { 0x4c, 0x9c, 0x95, 0xbc, 0xa3, 0x50, 0x8c, 0x24, + 0xb1, 0xd0, 0xb1, 0x55, 0x9c, 0x83, 0xef, 0x5b, + 0x04, 0x44, 0x5c, 0xc4, 0x58, 0x1c, 0x8e, 0x86, + 0xd8, 0x22, 0x4e, 0xdd, 0xd0, 0x9f, 0x11, 0xd7 }, + { 0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + { 0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, + }; + + /* The point must not be longer than 32 (it can be smaller). */ + if (px->len <= 32) { + p = px->data; + } else { + return SECFailure; + } + + for (i = 0; i < PR_ARRAY_SIZE(forbiddenValues); ++i) { + if (NSS_SecureMemcmp(p, forbiddenValues[i], px->len) == 0) { + return SECFailure; + } + } + + return SECSuccess; +} + +/* + * Scalar multiplication for Curve25519. + * If P == NULL, the base point is used. + * Returns X = k*P + */ +SECStatus +ec_Curve25519_pt_mul(SECItem *X, SECItem *k, SECItem *P) +{ + PRUint8 *px; + PRUint8 basePoint[32] = { 9 }; + + if (!P) { + px = basePoint; + } else { + PORT_Assert(P->len == 32); + if (P->len != 32) { + return SECFailure; + } + px = P->data; + } + + return ec_Curve25519_mul(X->data, k->data, px); +} diff --git a/nss/lib/freebl/ecl/ecp_256.c b/nss/lib/freebl/ecl/ecp_256.c index 936ee6d..ad4e630 100644 --- a/nss/lib/freebl/ecl/ecp_256.c +++ b/nss/lib/freebl/ecl/ecp_256.c @@ -7,362 +7,369 @@ #include "mplogic.h" #include "mpi-priv.h" -/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r. - * Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to +/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r. + * Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to * Elliptic Curve Cryptography. */ static mp_err ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_size a_used = MP_USED(a); - int a_bits = mpl_significant_bits(a); - mp_digit carry; + mp_err res = MP_OKAY; + mp_size a_used = MP_USED(a); + int a_bits = mpl_significant_bits(a); + mp_digit carry; #ifdef ECL_THIRTY_TWO_BIT - mp_digit a8=0, a9=0, a10=0, a11=0, a12=0, a13=0, a14=0, a15=0; - mp_digit r0, r1, r2, r3, r4, r5, r6, r7; - int r8; /* must be a signed value ! */ + mp_digit a8 = 0, a9 = 0, a10 = 0, a11 = 0, a12 = 0, a13 = 0, a14 = 0, a15 = 0; + mp_digit r0, r1, r2, r3, r4, r5, r6, r7; + int r8; /* must be a signed value ! */ #else - mp_digit a4=0, a5=0, a6=0, a7=0; - mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l; - mp_digit r0, r1, r2, r3; - int r4; /* must be a signed value ! */ + mp_digit a4 = 0, a5 = 0, a6 = 0, a7 = 0; + mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l; + mp_digit r0, r1, r2, r3; + int r4; /* must be a signed value ! */ #endif - /* for polynomials larger than twice the field size - * use regular reduction */ - if (a_bits < 256) { - if (a == r) return MP_OKAY; - return mp_copy(a,r); - } - if (a_bits > 512) { - MP_CHECKOK(mp_mod(a, &meth->irr, r)); - } else { + /* for polynomials larger than twice the field size + * use regular reduction */ + if (a_bits < 256) { + if (a == r) + return MP_OKAY; + return mp_copy(a, r); + } + if (a_bits > 512) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { #ifdef ECL_THIRTY_TWO_BIT - switch (a_used) { - case 16: - a15 = MP_DIGIT(a,15); - case 15: - a14 = MP_DIGIT(a,14); - case 14: - a13 = MP_DIGIT(a,13); - case 13: - a12 = MP_DIGIT(a,12); - case 12: - a11 = MP_DIGIT(a,11); - case 11: - a10 = MP_DIGIT(a,10); - case 10: - a9 = MP_DIGIT(a,9); - case 9: - a8 = MP_DIGIT(a,8); - } + switch (a_used) { + case 16: + a15 = MP_DIGIT(a, 15); + case 15: + a14 = MP_DIGIT(a, 14); + case 14: + a13 = MP_DIGIT(a, 13); + case 13: + a12 = MP_DIGIT(a, 12); + case 12: + a11 = MP_DIGIT(a, 11); + case 11: + a10 = MP_DIGIT(a, 10); + case 10: + a9 = MP_DIGIT(a, 9); + case 9: + a8 = MP_DIGIT(a, 8); + } - r0 = MP_DIGIT(a,0); - r1 = MP_DIGIT(a,1); - r2 = MP_DIGIT(a,2); - r3 = MP_DIGIT(a,3); - r4 = MP_DIGIT(a,4); - r5 = MP_DIGIT(a,5); - r6 = MP_DIGIT(a,6); - r7 = MP_DIGIT(a,7); + r0 = MP_DIGIT(a, 0); + r1 = MP_DIGIT(a, 1); + r2 = MP_DIGIT(a, 2); + r3 = MP_DIGIT(a, 3); + r4 = MP_DIGIT(a, 4); + r5 = MP_DIGIT(a, 5); + r6 = MP_DIGIT(a, 6); + r7 = MP_DIGIT(a, 7); - /* sum 1 */ - carry = 0; - MP_ADD_CARRY(r3, a11, r3, carry); - MP_ADD_CARRY(r4, a12, r4, carry); - MP_ADD_CARRY(r5, a13, r5, carry); - MP_ADD_CARRY(r6, a14, r6, carry); - MP_ADD_CARRY(r7, a15, r7, carry); - r8 = carry; carry = 0; - MP_ADD_CARRY(r3, a11, r3, carry); - MP_ADD_CARRY(r4, a12, r4, carry); - MP_ADD_CARRY(r5, a13, r5, carry); - MP_ADD_CARRY(r6, a14, r6, carry); - MP_ADD_CARRY(r7, a15, r7, carry); - r8 += carry; carry = 0; - /* sum 2 */ - MP_ADD_CARRY(r3, a12, r3, carry); - MP_ADD_CARRY(r4, a13, r4, carry); - MP_ADD_CARRY(r5, a14, r5, carry); - MP_ADD_CARRY(r6, a15, r6, carry); - MP_ADD_CARRY(r7, 0, r7, carry); - r8 += carry; carry = 0; - /* combine last bottom of sum 3 with second sum 2 */ - MP_ADD_CARRY(r0, a8, r0, carry); - MP_ADD_CARRY(r1, a9, r1, carry); - MP_ADD_CARRY(r2, a10, r2, carry); - MP_ADD_CARRY(r3, a12, r3, carry); - MP_ADD_CARRY(r4, a13, r4, carry); - MP_ADD_CARRY(r5, a14, r5, carry); - MP_ADD_CARRY(r6, a15, r6, carry); - MP_ADD_CARRY(r7, a15, r7, carry); /* from sum 3 */ - r8 += carry; carry = 0; - /* sum 3 (rest of it)*/ - MP_ADD_CARRY(r6, a14, r6, carry); - MP_ADD_CARRY(r7, 0, r7, carry); - r8 += carry; carry = 0; - /* sum 4 (rest of it)*/ - MP_ADD_CARRY(r0, a9, r0, carry); - MP_ADD_CARRY(r1, a10, r1, carry); - MP_ADD_CARRY(r2, a11, r2, carry); - MP_ADD_CARRY(r3, a13, r3, carry); - MP_ADD_CARRY(r4, a14, r4, carry); - MP_ADD_CARRY(r5, a15, r5, carry); - MP_ADD_CARRY(r6, a13, r6, carry); - MP_ADD_CARRY(r7, a8, r7, carry); - r8 += carry; carry = 0; - /* diff 5 */ - MP_SUB_BORROW(r0, a11, r0, carry); - MP_SUB_BORROW(r1, a12, r1, carry); - MP_SUB_BORROW(r2, a13, r2, carry); - MP_SUB_BORROW(r3, 0, r3, carry); - MP_SUB_BORROW(r4, 0, r4, carry); - MP_SUB_BORROW(r5, 0, r5, carry); - MP_SUB_BORROW(r6, a8, r6, carry); - MP_SUB_BORROW(r7, a10, r7, carry); - r8 -= carry; carry = 0; - /* diff 6 */ - MP_SUB_BORROW(r0, a12, r0, carry); - MP_SUB_BORROW(r1, a13, r1, carry); - MP_SUB_BORROW(r2, a14, r2, carry); - MP_SUB_BORROW(r3, a15, r3, carry); - MP_SUB_BORROW(r4, 0, r4, carry); - MP_SUB_BORROW(r5, 0, r5, carry); - MP_SUB_BORROW(r6, a9, r6, carry); - MP_SUB_BORROW(r7, a11, r7, carry); - r8 -= carry; carry = 0; - /* diff 7 */ - MP_SUB_BORROW(r0, a13, r0, carry); - MP_SUB_BORROW(r1, a14, r1, carry); - MP_SUB_BORROW(r2, a15, r2, carry); - MP_SUB_BORROW(r3, a8, r3, carry); - MP_SUB_BORROW(r4, a9, r4, carry); - MP_SUB_BORROW(r5, a10, r5, carry); - MP_SUB_BORROW(r6, 0, r6, carry); - MP_SUB_BORROW(r7, a12, r7, carry); - r8 -= carry; carry = 0; - /* diff 8 */ - MP_SUB_BORROW(r0, a14, r0, carry); - MP_SUB_BORROW(r1, a15, r1, carry); - MP_SUB_BORROW(r2, 0, r2, carry); - MP_SUB_BORROW(r3, a9, r3, carry); - MP_SUB_BORROW(r4, a10, r4, carry); - MP_SUB_BORROW(r5, a11, r5, carry); - MP_SUB_BORROW(r6, 0, r6, carry); - MP_SUB_BORROW(r7, a13, r7, carry); - r8 -= carry; + /* sum 1 */ + carry = 0; + MP_ADD_CARRY(r3, a11, r3, carry); + MP_ADD_CARRY(r4, a12, r4, carry); + MP_ADD_CARRY(r5, a13, r5, carry); + MP_ADD_CARRY(r6, a14, r6, carry); + MP_ADD_CARRY(r7, a15, r7, carry); + r8 = carry; + carry = 0; + MP_ADD_CARRY(r3, a11, r3, carry); + MP_ADD_CARRY(r4, a12, r4, carry); + MP_ADD_CARRY(r5, a13, r5, carry); + MP_ADD_CARRY(r6, a14, r6, carry); + MP_ADD_CARRY(r7, a15, r7, carry); + r8 += carry; + carry = 0; + /* sum 2 */ + MP_ADD_CARRY(r3, a12, r3, carry); + MP_ADD_CARRY(r4, a13, r4, carry); + MP_ADD_CARRY(r5, a14, r5, carry); + MP_ADD_CARRY(r6, a15, r6, carry); + MP_ADD_CARRY(r7, 0, r7, carry); + r8 += carry; + carry = 0; + /* combine last bottom of sum 3 with second sum 2 */ + MP_ADD_CARRY(r0, a8, r0, carry); + MP_ADD_CARRY(r1, a9, r1, carry); + MP_ADD_CARRY(r2, a10, r2, carry); + MP_ADD_CARRY(r3, a12, r3, carry); + MP_ADD_CARRY(r4, a13, r4, carry); + MP_ADD_CARRY(r5, a14, r5, carry); + MP_ADD_CARRY(r6, a15, r6, carry); + MP_ADD_CARRY(r7, a15, r7, carry); /* from sum 3 */ + r8 += carry; + carry = 0; + /* sum 3 (rest of it)*/ + MP_ADD_CARRY(r6, a14, r6, carry); + MP_ADD_CARRY(r7, 0, r7, carry); + r8 += carry; + carry = 0; + /* sum 4 (rest of it)*/ + MP_ADD_CARRY(r0, a9, r0, carry); + MP_ADD_CARRY(r1, a10, r1, carry); + MP_ADD_CARRY(r2, a11, r2, carry); + MP_ADD_CARRY(r3, a13, r3, carry); + MP_ADD_CARRY(r4, a14, r4, carry); + MP_ADD_CARRY(r5, a15, r5, carry); + MP_ADD_CARRY(r6, a13, r6, carry); + MP_ADD_CARRY(r7, a8, r7, carry); + r8 += carry; + carry = 0; + /* diff 5 */ + MP_SUB_BORROW(r0, a11, r0, carry); + MP_SUB_BORROW(r1, a12, r1, carry); + MP_SUB_BORROW(r2, a13, r2, carry); + MP_SUB_BORROW(r3, 0, r3, carry); + MP_SUB_BORROW(r4, 0, r4, carry); + MP_SUB_BORROW(r5, 0, r5, carry); + MP_SUB_BORROW(r6, a8, r6, carry); + MP_SUB_BORROW(r7, a10, r7, carry); + r8 -= carry; + carry = 0; + /* diff 6 */ + MP_SUB_BORROW(r0, a12, r0, carry); + MP_SUB_BORROW(r1, a13, r1, carry); + MP_SUB_BORROW(r2, a14, r2, carry); + MP_SUB_BORROW(r3, a15, r3, carry); + MP_SUB_BORROW(r4, 0, r4, carry); + MP_SUB_BORROW(r5, 0, r5, carry); + MP_SUB_BORROW(r6, a9, r6, carry); + MP_SUB_BORROW(r7, a11, r7, carry); + r8 -= carry; + carry = 0; + /* diff 7 */ + MP_SUB_BORROW(r0, a13, r0, carry); + MP_SUB_BORROW(r1, a14, r1, carry); + MP_SUB_BORROW(r2, a15, r2, carry); + MP_SUB_BORROW(r3, a8, r3, carry); + MP_SUB_BORROW(r4, a9, r4, carry); + MP_SUB_BORROW(r5, a10, r5, carry); + MP_SUB_BORROW(r6, 0, r6, carry); + MP_SUB_BORROW(r7, a12, r7, carry); + r8 -= carry; + carry = 0; + /* diff 8 */ + MP_SUB_BORROW(r0, a14, r0, carry); + MP_SUB_BORROW(r1, a15, r1, carry); + MP_SUB_BORROW(r2, 0, r2, carry); + MP_SUB_BORROW(r3, a9, r3, carry); + MP_SUB_BORROW(r4, a10, r4, carry); + MP_SUB_BORROW(r5, a11, r5, carry); + MP_SUB_BORROW(r6, 0, r6, carry); + MP_SUB_BORROW(r7, a13, r7, carry); + r8 -= carry; - /* reduce the overflows */ - while (r8 > 0) { - mp_digit r8_d = r8; carry = 0; - carry = 0; - MP_ADD_CARRY(r0, r8_d, r0, carry); - MP_ADD_CARRY(r1, 0, r1, carry); - MP_ADD_CARRY(r2, 0, r2, carry); - MP_ADD_CARRY(r3, 0-r8_d, r3, carry); - MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry); - MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry); - MP_ADD_CARRY(r6, 0-(r8_d+1), r6, carry); - MP_ADD_CARRY(r7, (r8_d-1), r7, carry); - r8 = carry; - } + /* reduce the overflows */ + while (r8 > 0) { + mp_digit r8_d = r8; + carry = 0; + MP_ADD_CARRY(r0, r8_d, r0, carry); + MP_ADD_CARRY(r1, 0, r1, carry); + MP_ADD_CARRY(r2, 0, r2, carry); + MP_ADD_CARRY(r3, 0 - r8_d, r3, carry); + MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry); + MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry); + MP_ADD_CARRY(r6, 0 - (r8_d + 1), r6, carry); + MP_ADD_CARRY(r7, (r8_d - 1), r7, carry); + r8 = carry; + } - /* reduce the underflows */ - while (r8 < 0) { - mp_digit r8_d = -r8; - carry = 0; - MP_SUB_BORROW(r0, r8_d, r0, carry); - MP_SUB_BORROW(r1, 0, r1, carry); - MP_SUB_BORROW(r2, 0, r2, carry); - MP_SUB_BORROW(r3, 0-r8_d, r3, carry); - MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry); - MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry); - MP_SUB_BORROW(r6, 0-(r8_d+1), r6, carry); - MP_SUB_BORROW(r7, (r8_d-1), r7, carry); - r8 = 0-carry; - } - if (a != r) { - MP_CHECKOK(s_mp_pad(r,8)); - } - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 8; + /* reduce the underflows */ + while (r8 < 0) { + mp_digit r8_d = -r8; + carry = 0; + MP_SUB_BORROW(r0, r8_d, r0, carry); + MP_SUB_BORROW(r1, 0, r1, carry); + MP_SUB_BORROW(r2, 0, r2, carry); + MP_SUB_BORROW(r3, 0 - r8_d, r3, carry); + MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry); + MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry); + MP_SUB_BORROW(r6, 0 - (r8_d + 1), r6, carry); + MP_SUB_BORROW(r7, (r8_d - 1), r7, carry); + r8 = 0 - carry; + } + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 8)); + } + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 8; - MP_DIGIT(r,7) = r7; - MP_DIGIT(r,6) = r6; - MP_DIGIT(r,5) = r5; - MP_DIGIT(r,4) = r4; - MP_DIGIT(r,3) = r3; - MP_DIGIT(r,2) = r2; - MP_DIGIT(r,1) = r1; - MP_DIGIT(r,0) = r0; + MP_DIGIT(r, 7) = r7; + MP_DIGIT(r, 6) = r6; + MP_DIGIT(r, 5) = r5; + MP_DIGIT(r, 4) = r4; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; - /* final reduction if necessary */ - if ((r7 == MP_DIGIT_MAX) && - ((r6 > 1) || ((r6 == 1) && - (r5 || r4 || r3 || - ((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX) - && (r0 == MP_DIGIT_MAX)))))) { - MP_CHECKOK(mp_sub(r, &meth->irr, r)); - } + /* final reduction if necessary */ + if ((r7 == MP_DIGIT_MAX) && + ((r6 > 1) || ((r6 == 1) && + (r5 || r4 || r3 || + ((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX) && (r0 == MP_DIGIT_MAX)))))) { + MP_CHECKOK(mp_sub(r, &meth->irr, r)); + } - s_mp_clamp(r); + s_mp_clamp(r); #else - switch (a_used) { - case 8: - a7 = MP_DIGIT(a,7); - case 7: - a6 = MP_DIGIT(a,6); - case 6: - a5 = MP_DIGIT(a,5); - case 5: - a4 = MP_DIGIT(a,4); - } - a7l = a7 << 32; - a7h = a7 >> 32; - a6l = a6 << 32; - a6h = a6 >> 32; - a5l = a5 << 32; - a5h = a5 >> 32; - a4l = a4 << 32; - a4h = a4 >> 32; - r3 = MP_DIGIT(a,3); - r2 = MP_DIGIT(a,2); - r1 = MP_DIGIT(a,1); - r0 = MP_DIGIT(a,0); + switch (a_used) { + case 8: + a7 = MP_DIGIT(a, 7); + case 7: + a6 = MP_DIGIT(a, 6); + case 6: + a5 = MP_DIGIT(a, 5); + case 5: + a4 = MP_DIGIT(a, 4); + } + a7l = a7 << 32; + a7h = a7 >> 32; + a6l = a6 << 32; + a6h = a6 >> 32; + a5l = a5 << 32; + a5h = a5 >> 32; + a4l = a4 << 32; + a4h = a4 >> 32; + r3 = MP_DIGIT(a, 3); + r2 = MP_DIGIT(a, 2); + r1 = MP_DIGIT(a, 1); + r0 = MP_DIGIT(a, 0); - /* sum 1 */ - carry = 0; - carry = 0; - MP_ADD_CARRY(r1, a5h << 32, r1, carry); - MP_ADD_CARRY(r2, a6, r2, carry); - MP_ADD_CARRY(r3, a7, r3, carry); - r4 = carry; carry = 0; - carry = 0; - MP_ADD_CARRY(r1, a5h << 32, r1, carry); - MP_ADD_CARRY(r2, a6, r2, carry); - MP_ADD_CARRY(r3, a7, r3, carry); - r4 += carry; carry = 0; - /* sum 2 */ - carry = 0; - MP_ADD_CARRY(r1, a6l, r1, carry); - MP_ADD_CARRY(r2, a6h | a7l, r2, carry); - MP_ADD_CARRY(r3, a7h, r3, carry); - r4 += carry; carry = 0; - carry = 0; - MP_ADD_CARRY(r1, a6l, r1, carry); - MP_ADD_CARRY(r2, a6h | a7l, r2, carry); - MP_ADD_CARRY(r3, a7h, r3, carry); - r4 += carry; carry = 0; + /* sum 1 */ + carry = 0; + MP_ADD_CARRY(r1, a5h << 32, r1, carry); + MP_ADD_CARRY(r2, a6, r2, carry); + MP_ADD_CARRY(r3, a7, r3, carry); + r4 = carry; + carry = 0; + MP_ADD_CARRY(r1, a5h << 32, r1, carry); + MP_ADD_CARRY(r2, a6, r2, carry); + MP_ADD_CARRY(r3, a7, r3, carry); + r4 += carry; + /* sum 2 */ + carry = 0; + MP_ADD_CARRY(r1, a6l, r1, carry); + MP_ADD_CARRY(r2, a6h | a7l, r2, carry); + MP_ADD_CARRY(r3, a7h, r3, carry); + r4 += carry; + carry = 0; + MP_ADD_CARRY(r1, a6l, r1, carry); + MP_ADD_CARRY(r2, a6h | a7l, r2, carry); + MP_ADD_CARRY(r3, a7h, r3, carry); + r4 += carry; - /* sum 3 */ - carry = 0; - MP_ADD_CARRY(r0, a4, r0, carry); - MP_ADD_CARRY(r1, a5l >> 32, r1, carry); - MP_ADD_CARRY(r2, 0, r2, carry); - MP_ADD_CARRY(r3, a7, r3, carry); - r4 += carry; carry = 0; - /* sum 4 */ - carry = 0; - MP_ADD_CARRY(r0, a4h | a5l, r0, carry); - MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry); - MP_ADD_CARRY(r2, a7, r2, carry); - MP_ADD_CARRY(r3, a6h | a4l, r3, carry); - r4 += carry; - /* diff 5 */ - carry = 0; - MP_SUB_BORROW(r0, a5h | a6l, r0, carry); - MP_SUB_BORROW(r1, a6h, r1, carry); - MP_SUB_BORROW(r2, 0, r2, carry); - MP_SUB_BORROW(r3, (a4l>>32)|a5l,r3, carry); - r4 -= carry; - /* diff 6 */ - carry = 0; - MP_SUB_BORROW(r0, a6, r0, carry); - MP_SUB_BORROW(r1, a7, r1, carry); - MP_SUB_BORROW(r2, 0, r2, carry); - MP_SUB_BORROW(r3, a4h|(a5h<<32),r3, carry); - r4 -= carry; - /* diff 7 */ - carry = 0; - MP_SUB_BORROW(r0, a6h|a7l, r0, carry); - MP_SUB_BORROW(r1, a7h|a4l, r1, carry); - MP_SUB_BORROW(r2, a4h|a5l, r2, carry); - MP_SUB_BORROW(r3, a6l, r3, carry); - r4 -= carry; - /* diff 8 */ - carry = 0; - MP_SUB_BORROW(r0, a7, r0, carry); - MP_SUB_BORROW(r1, a4h<<32, r1, carry); - MP_SUB_BORROW(r2, a5, r2, carry); - MP_SUB_BORROW(r3, a6h<<32, r3, carry); - r4 -= carry; + /* sum 3 */ + carry = 0; + MP_ADD_CARRY(r0, a4, r0, carry); + MP_ADD_CARRY(r1, a5l >> 32, r1, carry); + MP_ADD_CARRY(r2, 0, r2, carry); + MP_ADD_CARRY(r3, a7, r3, carry); + r4 += carry; + /* sum 4 */ + carry = 0; + MP_ADD_CARRY(r0, a4h | a5l, r0, carry); + MP_ADD_CARRY(r1, a5h | (a6h << 32), r1, carry); + MP_ADD_CARRY(r2, a7, r2, carry); + MP_ADD_CARRY(r3, a6h | a4l, r3, carry); + r4 += carry; + /* diff 5 */ + carry = 0; + MP_SUB_BORROW(r0, a5h | a6l, r0, carry); + MP_SUB_BORROW(r1, a6h, r1, carry); + MP_SUB_BORROW(r2, 0, r2, carry); + MP_SUB_BORROW(r3, (a4l >> 32) | a5l, r3, carry); + r4 -= carry; + /* diff 6 */ + carry = 0; + MP_SUB_BORROW(r0, a6, r0, carry); + MP_SUB_BORROW(r1, a7, r1, carry); + MP_SUB_BORROW(r2, 0, r2, carry); + MP_SUB_BORROW(r3, a4h | (a5h << 32), r3, carry); + r4 -= carry; + /* diff 7 */ + carry = 0; + MP_SUB_BORROW(r0, a6h | a7l, r0, carry); + MP_SUB_BORROW(r1, a7h | a4l, r1, carry); + MP_SUB_BORROW(r2, a4h | a5l, r2, carry); + MP_SUB_BORROW(r3, a6l, r3, carry); + r4 -= carry; + /* diff 8 */ + carry = 0; + MP_SUB_BORROW(r0, a7, r0, carry); + MP_SUB_BORROW(r1, a4h << 32, r1, carry); + MP_SUB_BORROW(r2, a5, r2, carry); + MP_SUB_BORROW(r3, a6h << 32, r3, carry); + r4 -= carry; - /* reduce the overflows */ - while (r4 > 0) { - mp_digit r4_long = r4; - mp_digit r4l = (r4_long << 32); - carry = 0; - carry = 0; - MP_ADD_CARRY(r0, r4_long, r0, carry); - MP_ADD_CARRY(r1, 0-r4l, r1, carry); - MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry); - MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry); - r4 = carry; - } + /* reduce the overflows */ + while (r4 > 0) { + mp_digit r4_long = r4; + mp_digit r4l = (r4_long << 32); + carry = 0; + MP_ADD_CARRY(r0, r4_long, r0, carry); + MP_ADD_CARRY(r1, 0 - r4l, r1, carry); + MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry); + MP_ADD_CARRY(r3, r4l - r4_long - 1, r3, carry); + r4 = carry; + } - /* reduce the underflows */ - while (r4 < 0) { - mp_digit r4_long = -r4; - mp_digit r4l = (r4_long << 32); - carry = 0; - MP_SUB_BORROW(r0, r4_long, r0, carry); - MP_SUB_BORROW(r1, 0-r4l, r1, carry); - MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry); - MP_SUB_BORROW(r3, r4l-r4_long-1,r3, carry); - r4 = 0-carry; - } + /* reduce the underflows */ + while (r4 < 0) { + mp_digit r4_long = -r4; + mp_digit r4l = (r4_long << 32); + carry = 0; + MP_SUB_BORROW(r0, r4_long, r0, carry); + MP_SUB_BORROW(r1, 0 - r4l, r1, carry); + MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry); + MP_SUB_BORROW(r3, r4l - r4_long - 1, r3, carry); + r4 = 0 - carry; + } - if (a != r) { - MP_CHECKOK(s_mp_pad(r,4)); - } - MP_SIGN(r) = MP_ZPOS; - MP_USED(r) = 4; + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 4)); + } + MP_SIGN(r) = MP_ZPOS; + MP_USED(r) = 4; - MP_DIGIT(r,3) = r3; - MP_DIGIT(r,2) = r2; - MP_DIGIT(r,1) = r1; - MP_DIGIT(r,0) = r0; + MP_DIGIT(r, 3) = r3; + MP_DIGIT(r, 2) = r2; + MP_DIGIT(r, 1) = r1; + MP_DIGIT(r, 0) = r0; - /* final reduction if necessary */ - if ((r3 > 0xFFFFFFFF00000001ULL) || - ((r3 == 0xFFFFFFFF00000001ULL) && - (r2 || (r1 >> 32)|| - (r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) { - /* very rare, just use mp_sub */ - MP_CHECKOK(mp_sub(r, &meth->irr, r)); - } - - s_mp_clamp(r); + /* final reduction if necessary */ + if ((r3 > 0xFFFFFFFF00000001ULL) || + ((r3 == 0xFFFFFFFF00000001ULL) && + (r2 || (r1 >> 32) || + (r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) { + /* very rare, just use mp_sub */ + MP_CHECKOK(mp_sub(r, &meth->irr, r)); + } + + s_mp_clamp(r); #endif - } + } - CLEANUP: - return res; +CLEANUP: + return res; } /* Compute the square of polynomial a, reduce modulo p256. Store the - * result in r. r could be a. Uses optimized modular reduction for p256. + * result in r. r could be a. Uses optimized modular reduction for p256. */ static mp_err ec_GFp_nistp256_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; - MP_CHECKOK(mp_sqr(a, r)); - MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth)); - CLEANUP: - return res; + MP_CHECKOK(mp_sqr(a, r)); + MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth)); +CLEANUP: + return res; } /* Compute the product of two polynomials a and b, reduce modulo p256. @@ -370,14 +377,14 @@ ec_GFp_nistp256_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) * optimized modular reduction for p256. */ static mp_err ec_GFp_nistp256_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; - MP_CHECKOK(mp_mul(a, b, r)); - MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth)); - CLEANUP: - return res; + MP_CHECKOK(mp_mul(a, b, r)); + MP_CHECKOK(ec_GFp_nistp256_mod(r, r, meth)); +CLEANUP: + return res; } /* Wire in fast field arithmetic and precomputation of base point for @@ -385,10 +392,10 @@ ec_GFp_nistp256_mul(const mp_int *a, const mp_int *b, mp_int *r, mp_err ec_group_set_gfp256(ECGroup *group, ECCurveName name) { - if (name == ECCurve_NIST_P256) { - group->meth->field_mod = &ec_GFp_nistp256_mod; - group->meth->field_mul = &ec_GFp_nistp256_mul; - group->meth->field_sqr = &ec_GFp_nistp256_sqr; - } - return MP_OKAY; + if (name == ECCurve_NIST_P256) { + group->meth->field_mod = &ec_GFp_nistp256_mod; + group->meth->field_mul = &ec_GFp_nistp256_mul; + group->meth->field_sqr = &ec_GFp_nistp256_sqr; + } + return MP_OKAY; } diff --git a/nss/lib/freebl/ecl/ecp_256_32.c b/nss/lib/freebl/ecl/ecp_256_32.c index cd8cd23..515f6f7 100644 --- a/nss/lib/freebl/ecl/ecp_256_32.c +++ b/nss/lib/freebl/ecl/ecp_256_32.c @@ -48,7 +48,7 @@ static const felem kOne = { 0x1fffffff, 0xfffffff, 0x1fbfffff, 0x1ffffff, 0 }; -static const felem kZero = {0}; +static const felem kZero = { 0 }; static const felem kP = { 0x1fffffff, 0xfffffff, 0x1fffffff, 0x3ff, 0, 0, 0x200000, 0xf000000, @@ -162,7 +162,7 @@ static const limb kPrecomputed[NLIMBS * 2 * 15 * 2] = { * * x must be a u32 or an equivalent type such as limb. */ -#define NON_ZERO_TO_ALL_ONES(x) ((((u32)(x) - 1) >> 31) - 1) +#define NON_ZERO_TO_ALL_ONES(x) ((((u32)(x)-1) >> 31) - 1) /* felem_reduce_carry adds a multiple of p in order to cancel |carry|, * which is a term at 2**257. @@ -170,7 +170,8 @@ static const limb kPrecomputed[NLIMBS * 2 * 15 * 2] = { * On entry: carry < 2**3, inout[0,2,...] < 2**29, inout[1,3,...] < 2**28. * On exit: inout[0,2,..] < 2**30, inout[1,3,...] < 2**29. */ -static void felem_reduce_carry(felem inout, limb carry) +static void +felem_reduce_carry(felem inout, limb carry) { const u32 carry_mask = NON_ZERO_TO_ALL_ONES(carry); @@ -196,24 +197,25 @@ static void felem_reduce_carry(felem inout, limb carry) * On entry, in[i]+in2[i] must not overflow a 32-bit word. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29 */ -static void felem_sum(felem out, const felem in, const felem in2) +static void +felem_sum(felem out, const felem in, const felem in2) { limb carry = 0; unsigned int i; for (i = 0;; i++) { - out[i] = in[i] + in2[i]; - out[i] += carry; - carry = out[i] >> 29; - out[i] &= kBottom29Bits; - - i++; - if (i == NLIMBS) - break; - - out[i] = in[i] + in2[i]; - out[i] += carry; - carry = out[i] >> 28; - out[i] &= kBottom28Bits; + out[i] = in[i] + in2[i]; + out[i] += carry; + carry = out[i] >> 29; + out[i] &= kBottom29Bits; + + i++; + if (i == NLIMBS) + break; + + out[i] = in[i] + in2[i]; + out[i] += carry; + carry = out[i] >> 28; + out[i] &= kBottom28Bits; } felem_reduce_carry(out, carry); @@ -240,27 +242,28 @@ static const felem zero31 = { * in2[0,2,...] < 2**30, in2[1,3,...] < 2**29. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ -static void felem_diff(felem out, const felem in, const felem in2) +static void +felem_diff(felem out, const felem in, const felem in2) { limb carry = 0; unsigned int i; for (i = 0;; i++) { - out[i] = in[i] - in2[i]; - out[i] += zero31[i]; - out[i] += carry; - carry = out[i] >> 29; - out[i] &= kBottom29Bits; - - i++; - if (i == NLIMBS) - break; - - out[i] = in[i] - in2[i]; - out[i] += zero31[i]; - out[i] += carry; - carry = out[i] >> 28; - out[i] &= kBottom28Bits; + out[i] = in[i] - in2[i]; + out[i] += zero31[i]; + out[i] += carry; + carry = out[i] >> 29; + out[i] &= kBottom29Bits; + + i++; + if (i == NLIMBS) + break; + + out[i] = in[i] - in2[i]; + out[i] += zero31[i]; + out[i] += carry; + carry = out[i] >> 28; + out[i] &= kBottom28Bits; } felem_reduce_carry(out, carry); @@ -277,7 +280,8 @@ static void felem_diff(felem out, const felem in, const felem in2) * On entry: tmp[i] < 2**64 * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29 */ -static void felem_reduce_degree(felem out, u64 tmp[17]) +static void +felem_reduce_degree(felem out, u64 tmp[17]) { /* The following table may be helpful when reading this code: * @@ -301,36 +305,36 @@ static void felem_reduce_degree(felem out, u64 tmp[17]) * the right register rather than doing a double-word shift and truncating * afterwards. */ - tmp2[1] = ((limb) tmp[0]) >> 29; - tmp2[1] |= (((limb) (tmp[0] >> 32)) << 3) & kBottom28Bits; - tmp2[1] += ((limb) tmp[1]) & kBottom28Bits; + tmp2[1] = ((limb)tmp[0]) >> 29; + tmp2[1] |= (((limb)(tmp[0] >> 32)) << 3) & kBottom28Bits; + tmp2[1] += ((limb)tmp[1]) & kBottom28Bits; carry = tmp2[1] >> 28; tmp2[1] &= kBottom28Bits; for (i = 2; i < 17; i++) { - tmp2[i] = ((limb) (tmp[i - 2] >> 32)) >> 25; - tmp2[i] += ((limb) (tmp[i - 1])) >> 28; - tmp2[i] += (((limb) (tmp[i - 1] >> 32)) << 4) & kBottom29Bits; - tmp2[i] += ((limb) tmp[i]) & kBottom29Bits; - tmp2[i] += carry; - carry = tmp2[i] >> 29; - tmp2[i] &= kBottom29Bits; - - i++; - if (i == 17) - break; - tmp2[i] = ((limb) (tmp[i - 2] >> 32)) >> 25; - tmp2[i] += ((limb) (tmp[i - 1])) >> 29; - tmp2[i] += (((limb) (tmp[i - 1] >> 32)) << 3) & kBottom28Bits; - tmp2[i] += ((limb) tmp[i]) & kBottom28Bits; - tmp2[i] += carry; - carry = tmp2[i] >> 28; - tmp2[i] &= kBottom28Bits; + tmp2[i] = ((limb)(tmp[i - 2] >> 32)) >> 25; + tmp2[i] += ((limb)(tmp[i - 1])) >> 28; + tmp2[i] += (((limb)(tmp[i - 1] >> 32)) << 4) & kBottom29Bits; + tmp2[i] += ((limb)tmp[i]) & kBottom29Bits; + tmp2[i] += carry; + carry = tmp2[i] >> 29; + tmp2[i] &= kBottom29Bits; + + i++; + if (i == 17) + break; + tmp2[i] = ((limb)(tmp[i - 2] >> 32)) >> 25; + tmp2[i] += ((limb)(tmp[i - 1])) >> 29; + tmp2[i] += (((limb)(tmp[i - 1] >> 32)) << 3) & kBottom28Bits; + tmp2[i] += ((limb)tmp[i]) & kBottom28Bits; + tmp2[i] += carry; + carry = tmp2[i] >> 28; + tmp2[i] &= kBottom28Bits; } - tmp2[17] = ((limb) (tmp[15] >> 32)) >> 25; - tmp2[17] += ((limb) (tmp[16])) >> 29; - tmp2[17] += (((limb) (tmp[16] >> 32)) << 3); + tmp2[17] = ((limb)(tmp[15] >> 32)) >> 25; + tmp2[17] += ((limb)(tmp[16])) >> 29; + tmp2[17] += (((limb)(tmp[16] >> 32)) << 3); tmp2[17] += carry; /* Montgomery elimination of terms: @@ -345,101 +349,101 @@ static void felem_reduce_degree(felem out, u64 tmp[17]) * extra factor of R. */ for (i = 0;; i += 2) { - tmp2[i + 1] += tmp2[i] >> 29; - x = tmp2[i] & kBottom29Bits; - xMask = NON_ZERO_TO_ALL_ONES(x); - tmp2[i] = 0; - - /* The bounds calculations for this loop are tricky. Each iteration of - * the loop eliminates two words by adding values to words to their - * right. - * - * The following table contains the amounts added to each word (as an - * offset from the value of i at the top of the loop). The amounts are - * accounted for from the first and second half of the loop separately - * and are written as, for example, 28 to mean a value <2**28. - * - * Word: 3 4 5 6 7 8 9 10 - * Added in top half: 28 11 29 21 29 28 - * 28 29 - * 29 - * Added in bottom half: 29 10 28 21 28 28 - * 29 - * - * The value that is currently offset 7 will be offset 5 for the next - * iteration and then offset 3 for the iteration after that. Therefore - * the total value added will be the values added at 7, 5 and 3. - * - * The following table accumulates these values. The sums at the bottom - * are written as, for example, 29+28, to mean a value < 2**29+2**28. - * - * Word: 3 4 5 6 7 8 9 10 11 12 13 - * 28 11 10 29 21 29 28 28 28 28 28 - * 29 28 11 28 29 28 29 28 29 28 - * 29 28 21 21 29 21 29 21 - * 10 29 28 21 28 21 28 - * 28 29 28 29 28 29 28 - * 11 10 29 10 29 10 - * 29 28 11 28 11 - * 29 29 - * -------------------------------------------- - * 30+ 31+ 30+ 31+ 30+ - * 28+ 29+ 28+ 29+ 21+ - * 21+ 28+ 21+ 28+ 10 - * 10 21+ 10 21+ - * 11 11 - * - * So the greatest amount is added to tmp2[10] and tmp2[12]. If - * tmp2[10/12] has an initial value of <2**29, then the maximum value - * will be < 2**31 + 2**30 + 2**28 + 2**21 + 2**11, which is < 2**32, - * as required. + tmp2[i + 1] += tmp2[i] >> 29; + x = tmp2[i] & kBottom29Bits; + xMask = NON_ZERO_TO_ALL_ONES(x); + tmp2[i] = 0; + + /* The bounds calculations for this loop are tricky. Each iteration of + * the loop eliminates two words by adding values to words to their + * right. + * + * The following table contains the amounts added to each word (as an + * offset from the value of i at the top of the loop). The amounts are + * accounted for from the first and second half of the loop separately + * and are written as, for example, 28 to mean a value <2**28. + * + * Word: 3 4 5 6 7 8 9 10 + * Added in top half: 28 11 29 21 29 28 + * 28 29 + * 29 + * Added in bottom half: 29 10 28 21 28 28 + * 29 + * + * The value that is currently offset 7 will be offset 5 for the next + * iteration and then offset 3 for the iteration after that. Therefore + * the total value added will be the values added at 7, 5 and 3. + * + * The following table accumulates these values. The sums at the bottom + * are written as, for example, 29+28, to mean a value < 2**29+2**28. + * + * Word: 3 4 5 6 7 8 9 10 11 12 13 + * 28 11 10 29 21 29 28 28 28 28 28 + * 29 28 11 28 29 28 29 28 29 28 + * 29 28 21 21 29 21 29 21 + * 10 29 28 21 28 21 28 + * 28 29 28 29 28 29 28 + * 11 10 29 10 29 10 + * 29 28 11 28 11 + * 29 29 + * -------------------------------------------- + * 30+ 31+ 30+ 31+ 30+ + * 28+ 29+ 28+ 29+ 21+ + * 21+ 28+ 21+ 28+ 10 + * 10 21+ 10 21+ + * 11 11 + * + * So the greatest amount is added to tmp2[10] and tmp2[12]. If + * tmp2[10/12] has an initial value of <2**29, then the maximum value + * will be < 2**31 + 2**30 + 2**28 + 2**21 + 2**11, which is < 2**32, + * as required. */ - tmp2[i + 3] += (x << 10) & kBottom28Bits; - tmp2[i + 4] += (x >> 18); - - tmp2[i + 6] += (x << 21) & kBottom29Bits; - tmp2[i + 7] += x >> 8; - - /* At position 200, which is the starting bit position for word 7, we - * have a factor of 0xf000000 = 2**28 - 2**24. - */ - tmp2[i + 7] += 0x10000000 & xMask; - /* Word 7 is 28 bits wide, so the 2**28 term exactly hits word 8. */ - tmp2[i + 8] += (x - 1) & xMask; - tmp2[i + 7] -= (x << 24) & kBottom28Bits; - tmp2[i + 8] -= x >> 4; - - tmp2[i + 8] += 0x20000000 & xMask; - tmp2[i + 8] -= x; - tmp2[i + 8] += (x << 28) & kBottom29Bits; - tmp2[i + 9] += ((x >> 1) - 1) & xMask; - - if (i+1 == NLIMBS) - break; - tmp2[i + 2] += tmp2[i + 1] >> 28; - x = tmp2[i + 1] & kBottom28Bits; - xMask = NON_ZERO_TO_ALL_ONES(x); - tmp2[i + 1] = 0; - - tmp2[i + 4] += (x << 11) & kBottom29Bits; - tmp2[i + 5] += (x >> 18); - - tmp2[i + 7] += (x << 21) & kBottom28Bits; - tmp2[i + 8] += x >> 7; - - /* At position 199, which is the starting bit of the 8th word when - * dealing with a context starting on an odd word, we have a factor of - * 0x1e000000 = 2**29 - 2**25. Since we have not updated i, the 8th - * word from i+1 is i+8. - */ - tmp2[i + 8] += 0x20000000 & xMask; - tmp2[i + 9] += (x - 1) & xMask; - tmp2[i + 8] -= (x << 25) & kBottom29Bits; - tmp2[i + 9] -= x >> 4; - - tmp2[i + 9] += 0x10000000 & xMask; - tmp2[i + 9] -= x; - tmp2[i + 10] += (x - 1) & xMask; + tmp2[i + 3] += (x << 10) & kBottom28Bits; + tmp2[i + 4] += (x >> 18); + + tmp2[i + 6] += (x << 21) & kBottom29Bits; + tmp2[i + 7] += x >> 8; + + /* At position 200, which is the starting bit position for word 7, we + * have a factor of 0xf000000 = 2**28 - 2**24. + */ + tmp2[i + 7] += 0x10000000 & xMask; + /* Word 7 is 28 bits wide, so the 2**28 term exactly hits word 8. */ + tmp2[i + 8] += (x - 1) & xMask; + tmp2[i + 7] -= (x << 24) & kBottom28Bits; + tmp2[i + 8] -= x >> 4; + + tmp2[i + 8] += 0x20000000 & xMask; + tmp2[i + 8] -= x; + tmp2[i + 8] += (x << 28) & kBottom29Bits; + tmp2[i + 9] += ((x >> 1) - 1) & xMask; + + if (i + 1 == NLIMBS) + break; + tmp2[i + 2] += tmp2[i + 1] >> 28; + x = tmp2[i + 1] & kBottom28Bits; + xMask = NON_ZERO_TO_ALL_ONES(x); + tmp2[i + 1] = 0; + + tmp2[i + 4] += (x << 11) & kBottom29Bits; + tmp2[i + 5] += (x >> 18); + + tmp2[i + 7] += (x << 21) & kBottom28Bits; + tmp2[i + 8] += x >> 7; + + /* At position 199, which is the starting bit of the 8th word when + * dealing with a context starting on an odd word, we have a factor of + * 0x1e000000 = 2**29 - 2**25. Since we have not updated i, the 8th + * word from i+1 is i+8. + */ + tmp2[i + 8] += 0x20000000 & xMask; + tmp2[i + 9] += (x - 1) & xMask; + tmp2[i + 8] -= (x << 25) & kBottom29Bits; + tmp2[i + 9] -= x >> 4; + + tmp2[i + 9] += 0x10000000 & xMask; + tmp2[i + 9] -= x; + tmp2[i + 10] += (x - 1) & xMask; } /* We merge the right shift with a carry chain. The words above 2**257 have @@ -447,21 +451,21 @@ static void felem_reduce_degree(felem out, u64 tmp[17]) */ carry = 0; for (i = 0; i < 8; i++) { - /* The maximum value of tmp2[i + 9] occurs on the first iteration and - * is < 2**30+2**29+2**28. Adding 2**29 (from tmp2[i + 10]) is - * therefore safe. - */ - out[i] = tmp2[i + 9]; - out[i] += carry; - out[i] += (tmp2[i + 10] << 28) & kBottom29Bits; - carry = out[i] >> 29; - out[i] &= kBottom29Bits; - - i++; - out[i] = tmp2[i + 9] >> 1; - out[i] += carry; - carry = out[i] >> 28; - out[i] &= kBottom28Bits; + /* The maximum value of tmp2[i + 9] occurs on the first iteration and + * is < 2**30+2**29+2**28. Adding 2**29 (from tmp2[i + 10]) is + * therefore safe. + */ + out[i] = tmp2[i + 9]; + out[i] += carry; + out[i] += (tmp2[i + 10] << 28) & kBottom29Bits; + carry = out[i] >> 29; + out[i] &= kBottom29Bits; + + i++; + out[i] = tmp2[i + 9] >> 1; + out[i] += carry; + carry = out[i] >> 28; + out[i] &= kBottom28Bits; } out[8] = tmp2[17]; @@ -477,58 +481,59 @@ static void felem_reduce_degree(felem out, u64 tmp[17]) * On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ -static void felem_square(felem out, const felem in) +static void +felem_square(felem out, const felem in) { u64 tmp[17]; - tmp[0] = ((u64) in[0]) * in[0]; - tmp[1] = ((u64) in[0]) * (in[1] << 1); - tmp[2] = ((u64) in[0]) * (in[2] << 1) + - ((u64) in[1]) * (in[1] << 1); - tmp[3] = ((u64) in[0]) * (in[3] << 1) + - ((u64) in[1]) * (in[2] << 1); - tmp[4] = ((u64) in[0]) * (in[4] << 1) + - ((u64) in[1]) * (in[3] << 2) + - ((u64) in[2]) * in[2]; - tmp[5] = ((u64) in[0]) * (in[5] << 1) + - ((u64) in[1]) * (in[4] << 1) + - ((u64) in[2]) * (in[3] << 1); - tmp[6] = ((u64) in[0]) * (in[6] << 1) + - ((u64) in[1]) * (in[5] << 2) + - ((u64) in[2]) * (in[4] << 1) + - ((u64) in[3]) * (in[3] << 1); - tmp[7] = ((u64) in[0]) * (in[7] << 1) + - ((u64) in[1]) * (in[6] << 1) + - ((u64) in[2]) * (in[5] << 1) + - ((u64) in[3]) * (in[4] << 1); + tmp[0] = ((u64)in[0]) * in[0]; + tmp[1] = ((u64)in[0]) * (in[1] << 1); + tmp[2] = ((u64)in[0]) * (in[2] << 1) + + ((u64)in[1]) * (in[1] << 1); + tmp[3] = ((u64)in[0]) * (in[3] << 1) + + ((u64)in[1]) * (in[2] << 1); + tmp[4] = ((u64)in[0]) * (in[4] << 1) + + ((u64)in[1]) * (in[3] << 2) + + ((u64)in[2]) * in[2]; + tmp[5] = ((u64)in[0]) * (in[5] << 1) + + ((u64)in[1]) * (in[4] << 1) + + ((u64)in[2]) * (in[3] << 1); + tmp[6] = ((u64)in[0]) * (in[6] << 1) + + ((u64)in[1]) * (in[5] << 2) + + ((u64)in[2]) * (in[4] << 1) + + ((u64)in[3]) * (in[3] << 1); + tmp[7] = ((u64)in[0]) * (in[7] << 1) + + ((u64)in[1]) * (in[6] << 1) + + ((u64)in[2]) * (in[5] << 1) + + ((u64)in[3]) * (in[4] << 1); /* tmp[8] has the greatest value of 2**61 + 2**60 + 2**61 + 2**60 + 2**60, * which is < 2**64 as required. */ - tmp[8] = ((u64) in[0]) * (in[8] << 1) + - ((u64) in[1]) * (in[7] << 2) + - ((u64) in[2]) * (in[6] << 1) + - ((u64) in[3]) * (in[5] << 2) + - ((u64) in[4]) * in[4]; - tmp[9] = ((u64) in[1]) * (in[8] << 1) + - ((u64) in[2]) * (in[7] << 1) + - ((u64) in[3]) * (in[6] << 1) + - ((u64) in[4]) * (in[5] << 1); - tmp[10] = ((u64) in[2]) * (in[8] << 1) + - ((u64) in[3]) * (in[7] << 2) + - ((u64) in[4]) * (in[6] << 1) + - ((u64) in[5]) * (in[5] << 1); - tmp[11] = ((u64) in[3]) * (in[8] << 1) + - ((u64) in[4]) * (in[7] << 1) + - ((u64) in[5]) * (in[6] << 1); - tmp[12] = ((u64) in[4]) * (in[8] << 1) + - ((u64) in[5]) * (in[7] << 2) + - ((u64) in[6]) * in[6]; - tmp[13] = ((u64) in[5]) * (in[8] << 1) + - ((u64) in[6]) * (in[7] << 1); - tmp[14] = ((u64) in[6]) * (in[8] << 1) + - ((u64) in[7]) * (in[7] << 1); - tmp[15] = ((u64) in[7]) * (in[8] << 1); - tmp[16] = ((u64) in[8]) * in[8]; + tmp[8] = ((u64)in[0]) * (in[8] << 1) + + ((u64)in[1]) * (in[7] << 2) + + ((u64)in[2]) * (in[6] << 1) + + ((u64)in[3]) * (in[5] << 2) + + ((u64)in[4]) * in[4]; + tmp[9] = ((u64)in[1]) * (in[8] << 1) + + ((u64)in[2]) * (in[7] << 1) + + ((u64)in[3]) * (in[6] << 1) + + ((u64)in[4]) * (in[5] << 1); + tmp[10] = ((u64)in[2]) * (in[8] << 1) + + ((u64)in[3]) * (in[7] << 2) + + ((u64)in[4]) * (in[6] << 1) + + ((u64)in[5]) * (in[5] << 1); + tmp[11] = ((u64)in[3]) * (in[8] << 1) + + ((u64)in[4]) * (in[7] << 1) + + ((u64)in[5]) * (in[6] << 1); + tmp[12] = ((u64)in[4]) * (in[8] << 1) + + ((u64)in[5]) * (in[7] << 2) + + ((u64)in[6]) * in[6]; + tmp[13] = ((u64)in[5]) * (in[8] << 1) + + ((u64)in[6]) * (in[7] << 1); + tmp[14] = ((u64)in[6]) * (in[8] << 1) + + ((u64)in[7]) * (in[7] << 1); + tmp[15] = ((u64)in[7]) * (in[8] << 1); + tmp[16] = ((u64)in[8]) * in[8]; felem_reduce_degree(out, tmp); } @@ -539,99 +544,101 @@ static void felem_square(felem out, const felem in) * in2[0,2,...] < 2**30, in2[1,3,...] < 2**29. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ -static void felem_mul(felem out, const felem in, const felem in2) +static void +felem_mul(felem out, const felem in, const felem in2) { u64 tmp[17]; - tmp[0] = ((u64) in[0]) * in2[0]; - tmp[1] = ((u64) in[0]) * (in2[1] << 0) + - ((u64) in[1]) * (in2[0] << 0); - tmp[2] = ((u64) in[0]) * (in2[2] << 0) + - ((u64) in[1]) * (in2[1] << 1) + - ((u64) in[2]) * (in2[0] << 0); - tmp[3] = ((u64) in[0]) * (in2[3] << 0) + - ((u64) in[1]) * (in2[2] << 0) + - ((u64) in[2]) * (in2[1] << 0) + - ((u64) in[3]) * (in2[0] << 0); - tmp[4] = ((u64) in[0]) * (in2[4] << 0) + - ((u64) in[1]) * (in2[3] << 1) + - ((u64) in[2]) * (in2[2] << 0) + - ((u64) in[3]) * (in2[1] << 1) + - ((u64) in[4]) * (in2[0] << 0); - tmp[5] = ((u64) in[0]) * (in2[5] << 0) + - ((u64) in[1]) * (in2[4] << 0) + - ((u64) in[2]) * (in2[3] << 0) + - ((u64) in[3]) * (in2[2] << 0) + - ((u64) in[4]) * (in2[1] << 0) + - ((u64) in[5]) * (in2[0] << 0); - tmp[6] = ((u64) in[0]) * (in2[6] << 0) + - ((u64) in[1]) * (in2[5] << 1) + - ((u64) in[2]) * (in2[4] << 0) + - ((u64) in[3]) * (in2[3] << 1) + - ((u64) in[4]) * (in2[2] << 0) + - ((u64) in[5]) * (in2[1] << 1) + - ((u64) in[6]) * (in2[0] << 0); - tmp[7] = ((u64) in[0]) * (in2[7] << 0) + - ((u64) in[1]) * (in2[6] << 0) + - ((u64) in[2]) * (in2[5] << 0) + - ((u64) in[3]) * (in2[4] << 0) + - ((u64) in[4]) * (in2[3] << 0) + - ((u64) in[5]) * (in2[2] << 0) + - ((u64) in[6]) * (in2[1] << 0) + - ((u64) in[7]) * (in2[0] << 0); + tmp[0] = ((u64)in[0]) * in2[0]; + tmp[1] = ((u64)in[0]) * (in2[1] << 0) + + ((u64)in[1]) * (in2[0] << 0); + tmp[2] = ((u64)in[0]) * (in2[2] << 0) + + ((u64)in[1]) * (in2[1] << 1) + + ((u64)in[2]) * (in2[0] << 0); + tmp[3] = ((u64)in[0]) * (in2[3] << 0) + + ((u64)in[1]) * (in2[2] << 0) + + ((u64)in[2]) * (in2[1] << 0) + + ((u64)in[3]) * (in2[0] << 0); + tmp[4] = ((u64)in[0]) * (in2[4] << 0) + + ((u64)in[1]) * (in2[3] << 1) + + ((u64)in[2]) * (in2[2] << 0) + + ((u64)in[3]) * (in2[1] << 1) + + ((u64)in[4]) * (in2[0] << 0); + tmp[5] = ((u64)in[0]) * (in2[5] << 0) + + ((u64)in[1]) * (in2[4] << 0) + + ((u64)in[2]) * (in2[3] << 0) + + ((u64)in[3]) * (in2[2] << 0) + + ((u64)in[4]) * (in2[1] << 0) + + ((u64)in[5]) * (in2[0] << 0); + tmp[6] = ((u64)in[0]) * (in2[6] << 0) + + ((u64)in[1]) * (in2[5] << 1) + + ((u64)in[2]) * (in2[4] << 0) + + ((u64)in[3]) * (in2[3] << 1) + + ((u64)in[4]) * (in2[2] << 0) + + ((u64)in[5]) * (in2[1] << 1) + + ((u64)in[6]) * (in2[0] << 0); + tmp[7] = ((u64)in[0]) * (in2[7] << 0) + + ((u64)in[1]) * (in2[6] << 0) + + ((u64)in[2]) * (in2[5] << 0) + + ((u64)in[3]) * (in2[4] << 0) + + ((u64)in[4]) * (in2[3] << 0) + + ((u64)in[5]) * (in2[2] << 0) + + ((u64)in[6]) * (in2[1] << 0) + + ((u64)in[7]) * (in2[0] << 0); /* tmp[8] has the greatest value but doesn't overflow. See logic in * felem_square. */ - tmp[8] = ((u64) in[0]) * (in2[8] << 0) + - ((u64) in[1]) * (in2[7] << 1) + - ((u64) in[2]) * (in2[6] << 0) + - ((u64) in[3]) * (in2[5] << 1) + - ((u64) in[4]) * (in2[4] << 0) + - ((u64) in[5]) * (in2[3] << 1) + - ((u64) in[6]) * (in2[2] << 0) + - ((u64) in[7]) * (in2[1] << 1) + - ((u64) in[8]) * (in2[0] << 0); - tmp[9] = ((u64) in[1]) * (in2[8] << 0) + - ((u64) in[2]) * (in2[7] << 0) + - ((u64) in[3]) * (in2[6] << 0) + - ((u64) in[4]) * (in2[5] << 0) + - ((u64) in[5]) * (in2[4] << 0) + - ((u64) in[6]) * (in2[3] << 0) + - ((u64) in[7]) * (in2[2] << 0) + - ((u64) in[8]) * (in2[1] << 0); - tmp[10] = ((u64) in[2]) * (in2[8] << 0) + - ((u64) in[3]) * (in2[7] << 1) + - ((u64) in[4]) * (in2[6] << 0) + - ((u64) in[5]) * (in2[5] << 1) + - ((u64) in[6]) * (in2[4] << 0) + - ((u64) in[7]) * (in2[3] << 1) + - ((u64) in[8]) * (in2[2] << 0); - tmp[11] = ((u64) in[3]) * (in2[8] << 0) + - ((u64) in[4]) * (in2[7] << 0) + - ((u64) in[5]) * (in2[6] << 0) + - ((u64) in[6]) * (in2[5] << 0) + - ((u64) in[7]) * (in2[4] << 0) + - ((u64) in[8]) * (in2[3] << 0); - tmp[12] = ((u64) in[4]) * (in2[8] << 0) + - ((u64) in[5]) * (in2[7] << 1) + - ((u64) in[6]) * (in2[6] << 0) + - ((u64) in[7]) * (in2[5] << 1) + - ((u64) in[8]) * (in2[4] << 0); - tmp[13] = ((u64) in[5]) * (in2[8] << 0) + - ((u64) in[6]) * (in2[7] << 0) + - ((u64) in[7]) * (in2[6] << 0) + - ((u64) in[8]) * (in2[5] << 0); - tmp[14] = ((u64) in[6]) * (in2[8] << 0) + - ((u64) in[7]) * (in2[7] << 1) + - ((u64) in[8]) * (in2[6] << 0); - tmp[15] = ((u64) in[7]) * (in2[8] << 0) + - ((u64) in[8]) * (in2[7] << 0); - tmp[16] = ((u64) in[8]) * (in2[8] << 0); + tmp[8] = ((u64)in[0]) * (in2[8] << 0) + + ((u64)in[1]) * (in2[7] << 1) + + ((u64)in[2]) * (in2[6] << 0) + + ((u64)in[3]) * (in2[5] << 1) + + ((u64)in[4]) * (in2[4] << 0) + + ((u64)in[5]) * (in2[3] << 1) + + ((u64)in[6]) * (in2[2] << 0) + + ((u64)in[7]) * (in2[1] << 1) + + ((u64)in[8]) * (in2[0] << 0); + tmp[9] = ((u64)in[1]) * (in2[8] << 0) + + ((u64)in[2]) * (in2[7] << 0) + + ((u64)in[3]) * (in2[6] << 0) + + ((u64)in[4]) * (in2[5] << 0) + + ((u64)in[5]) * (in2[4] << 0) + + ((u64)in[6]) * (in2[3] << 0) + + ((u64)in[7]) * (in2[2] << 0) + + ((u64)in[8]) * (in2[1] << 0); + tmp[10] = ((u64)in[2]) * (in2[8] << 0) + + ((u64)in[3]) * (in2[7] << 1) + + ((u64)in[4]) * (in2[6] << 0) + + ((u64)in[5]) * (in2[5] << 1) + + ((u64)in[6]) * (in2[4] << 0) + + ((u64)in[7]) * (in2[3] << 1) + + ((u64)in[8]) * (in2[2] << 0); + tmp[11] = ((u64)in[3]) * (in2[8] << 0) + + ((u64)in[4]) * (in2[7] << 0) + + ((u64)in[5]) * (in2[6] << 0) + + ((u64)in[6]) * (in2[5] << 0) + + ((u64)in[7]) * (in2[4] << 0) + + ((u64)in[8]) * (in2[3] << 0); + tmp[12] = ((u64)in[4]) * (in2[8] << 0) + + ((u64)in[5]) * (in2[7] << 1) + + ((u64)in[6]) * (in2[6] << 0) + + ((u64)in[7]) * (in2[5] << 1) + + ((u64)in[8]) * (in2[4] << 0); + tmp[13] = ((u64)in[5]) * (in2[8] << 0) + + ((u64)in[6]) * (in2[7] << 0) + + ((u64)in[7]) * (in2[6] << 0) + + ((u64)in[8]) * (in2[5] << 0); + tmp[14] = ((u64)in[6]) * (in2[8] << 0) + + ((u64)in[7]) * (in2[7] << 1) + + ((u64)in[8]) * (in2[6] << 0); + tmp[15] = ((u64)in[7]) * (in2[8] << 0) + + ((u64)in[8]) * (in2[7] << 0); + tmp[16] = ((u64)in[8]) * (in2[8] << 0); felem_reduce_degree(out, tmp); } -static void felem_assign(felem out, const felem in) +static void +felem_assign(felem out, const felem in) { memcpy(out, in, sizeof(felem)); } @@ -643,66 +650,67 @@ static void felem_assign(felem out, const felem in) * a^{p-1} = 1 (mod p) * a^{p-2} = a^{-1} (mod p) */ -static void felem_inv(felem out, const felem in) +static void +felem_inv(felem out, const felem in) { felem ftmp, ftmp2; /* each e_I will hold |in|^{2^I - 1} */ felem e2, e4, e8, e16, e32, e64; unsigned int i; - felem_square(ftmp, in); /* 2^1 */ - felem_mul(ftmp, in, ftmp); /* 2^2 - 2^0 */ + felem_square(ftmp, in); /* 2^1 */ + felem_mul(ftmp, in, ftmp); /* 2^2 - 2^0 */ felem_assign(e2, ftmp); - felem_square(ftmp, ftmp); /* 2^3 - 2^1 */ - felem_square(ftmp, ftmp); /* 2^4 - 2^2 */ - felem_mul(ftmp, ftmp, e2); /* 2^4 - 2^0 */ + felem_square(ftmp, ftmp); /* 2^3 - 2^1 */ + felem_square(ftmp, ftmp); /* 2^4 - 2^2 */ + felem_mul(ftmp, ftmp, e2); /* 2^4 - 2^0 */ felem_assign(e4, ftmp); - felem_square(ftmp, ftmp); /* 2^5 - 2^1 */ - felem_square(ftmp, ftmp); /* 2^6 - 2^2 */ - felem_square(ftmp, ftmp); /* 2^7 - 2^3 */ - felem_square(ftmp, ftmp); /* 2^8 - 2^4 */ - felem_mul(ftmp, ftmp, e4); /* 2^8 - 2^0 */ + felem_square(ftmp, ftmp); /* 2^5 - 2^1 */ + felem_square(ftmp, ftmp); /* 2^6 - 2^2 */ + felem_square(ftmp, ftmp); /* 2^7 - 2^3 */ + felem_square(ftmp, ftmp); /* 2^8 - 2^4 */ + felem_mul(ftmp, ftmp, e4); /* 2^8 - 2^0 */ felem_assign(e8, ftmp); for (i = 0; i < 8; i++) { - felem_square(ftmp, ftmp); - } /* 2^16 - 2^8 */ - felem_mul(ftmp, ftmp, e8); /* 2^16 - 2^0 */ + felem_square(ftmp, ftmp); + } /* 2^16 - 2^8 */ + felem_mul(ftmp, ftmp, e8); /* 2^16 - 2^0 */ felem_assign(e16, ftmp); for (i = 0; i < 16; i++) { - felem_square(ftmp, ftmp); - } /* 2^32 - 2^16 */ - felem_mul(ftmp, ftmp, e16); /* 2^32 - 2^0 */ + felem_square(ftmp, ftmp); + } /* 2^32 - 2^16 */ + felem_mul(ftmp, ftmp, e16); /* 2^32 - 2^0 */ felem_assign(e32, ftmp); for (i = 0; i < 32; i++) { - felem_square(ftmp, ftmp); - } /* 2^64 - 2^32 */ + felem_square(ftmp, ftmp); + } /* 2^64 - 2^32 */ felem_assign(e64, ftmp); - felem_mul(ftmp, ftmp, in); /* 2^64 - 2^32 + 2^0 */ + felem_mul(ftmp, ftmp, in); /* 2^64 - 2^32 + 2^0 */ for (i = 0; i < 192; i++) { - felem_square(ftmp, ftmp); - } /* 2^256 - 2^224 + 2^192 */ + felem_square(ftmp, ftmp); + } /* 2^256 - 2^224 + 2^192 */ - felem_mul(ftmp2, e64, e32); /* 2^64 - 2^0 */ + felem_mul(ftmp2, e64, e32); /* 2^64 - 2^0 */ for (i = 0; i < 16; i++) { - felem_square(ftmp2, ftmp2); - } /* 2^80 - 2^16 */ - felem_mul(ftmp2, ftmp2, e16); /* 2^80 - 2^0 */ + felem_square(ftmp2, ftmp2); + } /* 2^80 - 2^16 */ + felem_mul(ftmp2, ftmp2, e16); /* 2^80 - 2^0 */ for (i = 0; i < 8; i++) { - felem_square(ftmp2, ftmp2); - } /* 2^88 - 2^8 */ - felem_mul(ftmp2, ftmp2, e8); /* 2^88 - 2^0 */ + felem_square(ftmp2, ftmp2); + } /* 2^88 - 2^8 */ + felem_mul(ftmp2, ftmp2, e8); /* 2^88 - 2^0 */ for (i = 0; i < 4; i++) { - felem_square(ftmp2, ftmp2); - } /* 2^92 - 2^4 */ - felem_mul(ftmp2, ftmp2, e4); /* 2^92 - 2^0 */ - felem_square(ftmp2, ftmp2); /* 2^93 - 2^1 */ - felem_square(ftmp2, ftmp2); /* 2^94 - 2^2 */ - felem_mul(ftmp2, ftmp2, e2); /* 2^94 - 2^0 */ - felem_square(ftmp2, ftmp2); /* 2^95 - 2^1 */ - felem_square(ftmp2, ftmp2); /* 2^96 - 2^2 */ - felem_mul(ftmp2, ftmp2, in); /* 2^96 - 3 */ - - felem_mul(out, ftmp2, ftmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ + felem_square(ftmp2, ftmp2); + } /* 2^92 - 2^4 */ + felem_mul(ftmp2, ftmp2, e4); /* 2^92 - 2^0 */ + felem_square(ftmp2, ftmp2); /* 2^93 - 2^1 */ + felem_square(ftmp2, ftmp2); /* 2^94 - 2^2 */ + felem_mul(ftmp2, ftmp2, e2); /* 2^94 - 2^0 */ + felem_square(ftmp2, ftmp2); /* 2^95 - 2^1 */ + felem_square(ftmp2, ftmp2); /* 2^96 - 2^2 */ + felem_mul(ftmp2, ftmp2, in); /* 2^96 - 3 */ + + felem_mul(out, ftmp2, ftmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ } /* felem_scalar_3 sets out=3*out. @@ -710,25 +718,26 @@ static void felem_inv(felem out, const felem in) * On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ -static void felem_scalar_3(felem out) +static void +felem_scalar_3(felem out) { limb carry = 0; unsigned int i; for (i = 0;; i++) { - out[i] *= 3; - out[i] += carry; - carry = out[i] >> 29; - out[i] &= kBottom29Bits; - - i++; - if (i == NLIMBS) - break; - - out[i] *= 3; - out[i] += carry; - carry = out[i] >> 28; - out[i] &= kBottom28Bits; + out[i] *= 3; + out[i] += carry; + carry = out[i] >> 29; + out[i] &= kBottom29Bits; + + i++; + if (i == NLIMBS) + break; + + out[i] *= 3; + out[i] += carry; + carry = out[i] >> 28; + out[i] &= kBottom28Bits; } felem_reduce_carry(out, carry); @@ -739,28 +748,29 @@ static void felem_scalar_3(felem out) * On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ -static void felem_scalar_4(felem out) +static void +felem_scalar_4(felem out) { limb carry = 0, next_carry; unsigned int i; for (i = 0;; i++) { - next_carry = out[i] >> 27; - out[i] <<= 2; - out[i] &= kBottom29Bits; - out[i] += carry; - carry = next_carry + (out[i] >> 29); - out[i] &= kBottom29Bits; - - i++; - if (i == NLIMBS) - break; - next_carry = out[i] >> 26; - out[i] <<= 2; - out[i] &= kBottom28Bits; - out[i] += carry; - carry = next_carry + (out[i] >> 28); - out[i] &= kBottom28Bits; + next_carry = out[i] >> 27; + out[i] <<= 2; + out[i] &= kBottom29Bits; + out[i] += carry; + carry = next_carry + (out[i] >> 29); + out[i] &= kBottom29Bits; + + i++; + if (i == NLIMBS) + break; + next_carry = out[i] >> 26; + out[i] <<= 2; + out[i] &= kBottom28Bits; + out[i] += carry; + carry = next_carry + (out[i] >> 28); + out[i] &= kBottom28Bits; } felem_reduce_carry(out, carry); @@ -771,28 +781,29 @@ static void felem_scalar_4(felem out) * On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ -static void felem_scalar_8(felem out) +static void +felem_scalar_8(felem out) { limb carry = 0, next_carry; unsigned int i; for (i = 0;; i++) { - next_carry = out[i] >> 26; - out[i] <<= 3; - out[i] &= kBottom29Bits; - out[i] += carry; - carry = next_carry + (out[i] >> 29); - out[i] &= kBottom29Bits; - - i++; - if (i == NLIMBS) - break; - next_carry = out[i] >> 25; - out[i] <<= 3; - out[i] &= kBottom28Bits; - out[i] += carry; - carry = next_carry + (out[i] >> 28); - out[i] &= kBottom28Bits; + next_carry = out[i] >> 26; + out[i] <<= 3; + out[i] &= kBottom29Bits; + out[i] += carry; + carry = next_carry + (out[i] >> 29); + out[i] &= kBottom29Bits; + + i++; + if (i == NLIMBS) + break; + next_carry = out[i] >> 25; + out[i] <<= 3; + out[i] &= kBottom28Bits; + out[i] += carry; + carry = next_carry + (out[i] >> 28); + out[i] &= kBottom28Bits; } felem_reduce_carry(out, carry); @@ -801,7 +812,8 @@ static void felem_scalar_8(felem out) /* felem_is_zero_vartime returns 1 iff |in| == 0. It takes a variable amount of * time depending on the value of |in|. */ -static char felem_is_zero_vartime(const felem in) +static char +felem_is_zero_vartime(const felem in) { limb carry; int i; @@ -811,29 +823,29 @@ static char felem_is_zero_vartime(const felem in) /* First, reduce tmp to a minimal form. */ do { - carry = 0; - for (i = 0;; i++) { - tmp[i] += carry; - carry = tmp[i] >> 29; - tmp[i] &= kBottom29Bits; - - i++; - if (i == NLIMBS) - break; - - tmp[i] += carry; - carry = tmp[i] >> 28; - tmp[i] &= kBottom28Bits; - } - - felem_reduce_carry(tmp, carry); + carry = 0; + for (i = 0;; i++) { + tmp[i] += carry; + carry = tmp[i] >> 29; + tmp[i] &= kBottom29Bits; + + i++; + if (i == NLIMBS) + break; + + tmp[i] += carry; + carry = tmp[i] >> 28; + tmp[i] &= kBottom28Bits; + } + + felem_reduce_carry(tmp, carry); } while (carry); /* tmp < 2**257, so the only possible zero values are 0, p and 2p. */ return memcmp(tmp, kZero, sizeof(tmp)) == 0 || - memcmp(tmp, kP, sizeof(tmp)) == 0 || - memcmp(tmp, k2P, sizeof(tmp)) == 0; + memcmp(tmp, kP, sizeof(tmp)) == 0 || + memcmp(tmp, k2P, sizeof(tmp)) == 0; } /* Group operations: @@ -847,8 +859,9 @@ static char felem_is_zero_vartime(const felem in) * * See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l */ -static void point_double(felem x_out, felem y_out, felem z_out, - const felem x, const felem y, const felem z) +static void +point_double(felem x_out, felem y_out, felem z_out, + const felem x, const felem y, const felem z) { felem delta, gamma, alpha, beta, tmp, tmp2; @@ -886,9 +899,10 @@ static void point_double(felem x_out, felem y_out, felem z_out, * Note that this function does not handle P+P, infinity+P nor P+infinity * correctly. */ -static void point_add_mixed(felem x_out, felem y_out, felem z_out, - const felem x1, const felem y1, const felem z1, - const felem x2, const felem y2) +static void +point_add_mixed(felem x_out, felem y_out, felem z_out, + const felem x1, const felem y1, const felem z1, + const felem x2, const felem y2) { felem z1z1, z1z1z1, s2, u2, h, i, j, r, rr, v, tmp; @@ -926,9 +940,10 @@ static void point_add_mixed(felem x_out, felem y_out, felem z_out, * Note that this function does not handle P+P, infinity+P nor P+infinity * correctly. */ -static void point_add(felem x_out, felem y_out, felem z_out, - const felem x1, const felem y1, const felem z1, - const felem x2, const felem y2, const felem z2) +static void +point_add(felem x_out, felem y_out, felem z_out, + const felem x1, const felem y1, const felem z1, + const felem x2, const felem y2, const felem z2) { felem z1z1, z1z1z1, z2z2, z2z2z2, s1, s2, u1, u2, h, i, j, r, rr, v, tmp; @@ -975,7 +990,8 @@ static void point_add(felem x_out, felem y_out, felem z_out, * * This function handles the case where {x1,y1,z1}={x2,y2,z2}. */ -static void point_add_or_double_vartime( +static void +point_add_or_double_vartime( felem x_out, felem y_out, felem z_out, const felem x1, const felem y1, const felem z1, const felem x2, const felem y2, const felem z2) @@ -1006,8 +1022,8 @@ static void point_add_or_double_vartime( felem_diff(r, s2, s1); y_equal = felem_is_zero_vartime(r); if (x_equal && y_equal) { - point_double(x_out, y_out, z_out, x1, y1, z1); - return; + point_double(x_out, y_out, z_out, x1, y1, z1); + return; } felem_sum(r, r, r); felem_mul(v, u1, i); @@ -1029,21 +1045,23 @@ static void point_add_or_double_vartime( * * On entry: mask is either 0 or 0xffffffff. */ -static void copy_conditional(felem out, const felem in, limb mask) +static void +copy_conditional(felem out, const felem in, limb mask) { int i; for (i = 0; i < NLIMBS; i++) { - const limb tmp = mask & (in[i] ^ out[i]); - out[i] ^= tmp; + const limb tmp = mask & (in[i] ^ out[i]); + out[i] ^= tmp; } } /* select_affine_point sets {out_x,out_y} to the index'th entry of table. * On entry: index < 16, table[0] must be zero. */ -static void select_affine_point(felem out_x, felem out_y, - const limb *table, limb index) +static void +select_affine_point(felem out_x, felem out_y, + const limb *table, limb index) { limb i, j; @@ -1051,25 +1069,26 @@ static void select_affine_point(felem out_x, felem out_y, memset(out_y, 0, sizeof(felem)); for (i = 1; i < 16; i++) { - limb mask = i ^ index; - mask |= mask >> 2; - mask |= mask >> 1; - mask &= 1; - mask--; - for (j = 0; j < NLIMBS; j++, table++) { - out_x[j] |= *table & mask; - } - for (j = 0; j < NLIMBS; j++, table++) { - out_y[j] |= *table & mask; - } + limb mask = i ^ index; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < NLIMBS; j++, table++) { + out_x[j] |= *table & mask; + } + for (j = 0; j < NLIMBS; j++, table++) { + out_y[j] |= *table & mask; + } } } /* select_jacobian_point sets {out_x,out_y,out_z} to the index'th entry of * table. On entry: index < 16, table[0] must be zero. */ -static void select_jacobian_point(felem out_x, felem out_y, felem out_z, - const limb *table, limb index) +static void +select_jacobian_point(felem out_x, felem out_y, felem out_z, + const limb *table, limb index) { limb i, j; @@ -1080,28 +1099,29 @@ static void select_jacobian_point(felem out_x, felem out_y, felem out_z, /* The implicit value at index 0 is all zero. We don't need to perform that * iteration of the loop because we already set out_* to zero. */ - table += 3*NLIMBS; + table += 3 * NLIMBS; for (i = 1; i < 16; i++) { - limb mask = i ^ index; - mask |= mask >> 2; - mask |= mask >> 1; - mask &= 1; - mask--; - for (j = 0; j < NLIMBS; j++, table++) { - out_x[j] |= *table & mask; - } - for (j = 0; j < NLIMBS; j++, table++) { - out_y[j] |= *table & mask; - } - for (j = 0; j < NLIMBS; j++, table++) { - out_z[j] |= *table & mask; - } + limb mask = i ^ index; + mask |= mask >> 2; + mask |= mask >> 1; + mask &= 1; + mask--; + for (j = 0; j < NLIMBS; j++, table++) { + out_x[j] |= *table & mask; + } + for (j = 0; j < NLIMBS; j++, table++) { + out_y[j] |= *table & mask; + } + for (j = 0; j < NLIMBS; j++, table++) { + out_z[j] |= *table & mask; + } } } /* get_bit returns the bit'th bit of scalar. */ -static char get_bit(const u8 scalar[32], int bit) +static char +get_bit(const u8 scalar[32], int bit) { return ((scalar[bit >> 3]) >> (bit & 7)) & 1; } @@ -1110,7 +1130,8 @@ static char get_bit(const u8 scalar[32], int bit) * number. Note that the value of scalar must be less than the order of the * group. */ -static void scalar_base_mult(felem nx, felem ny, felem nz, const u8 scalar[32]) +static void +scalar_base_mult(felem nx, felem ny, felem nz, const u8 scalar[32]) { int i, j; limb n_is_infinity_mask = -1, p_is_noninfinite_mask, mask; @@ -1127,53 +1148,55 @@ static void scalar_base_mult(felem nx, felem ny, felem nz, const u8 scalar[32]) * positions 32,96,160 and 224 and does this 32 times. */ for (i = 0; i < 32; i++) { - if (i) { - point_double(nx, ny, nz, nx, ny, nz); - } - table_offset = 0; - for (j = 0; j <= 32; j += 32) { - char bit0 = get_bit(scalar, 31 - i + j); - char bit1 = get_bit(scalar, 95 - i + j); - char bit2 = get_bit(scalar, 159 - i + j); - char bit3 = get_bit(scalar, 223 - i + j); - limb index = bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3); - - select_affine_point(px, py, kPrecomputed + table_offset, index); - table_offset += 30 * NLIMBS; - - /* Since scalar is less than the order of the group, we know that - * {nx,ny,nz} != {px,py,1}, unless both are zero, which we handle - * below. - */ - point_add_mixed(tx, ty, tz, nx, ny, nz, px, py); - /* The result of point_add_mixed is incorrect if {nx,ny,nz} is zero - * (a.k.a. the point at infinity). We handle that situation by - * copying the point from the table. - */ - copy_conditional(nx, px, n_is_infinity_mask); - copy_conditional(ny, py, n_is_infinity_mask); - copy_conditional(nz, kOne, n_is_infinity_mask); - - /* Equally, the result is also wrong if the point from the table is - * zero, which happens when the index is zero. We handle that by - * only copying from {tx,ty,tz} to {nx,ny,nz} if index != 0. - */ - p_is_noninfinite_mask = NON_ZERO_TO_ALL_ONES(index); - mask = p_is_noninfinite_mask & ~n_is_infinity_mask; - copy_conditional(nx, tx, mask); - copy_conditional(ny, ty, mask); - copy_conditional(nz, tz, mask); - /* If p was not zero, then n is now non-zero. */ - n_is_infinity_mask &= ~p_is_noninfinite_mask; - } + if (i) { + point_double(nx, ny, nz, nx, ny, nz); + } + table_offset = 0; + for (j = 0; j <= 32; j += 32) { + char bit0 = get_bit(scalar, 31 - i + j); + char bit1 = get_bit(scalar, 95 - i + j); + char bit2 = get_bit(scalar, 159 - i + j); + char bit3 = get_bit(scalar, 223 - i + j); + limb index = bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3); + + select_affine_point(px, py, kPrecomputed + table_offset, index); + table_offset += 30 * NLIMBS; + + /* Since scalar is less than the order of the group, we know that + * {nx,ny,nz} != {px,py,1}, unless both are zero, which we handle + * below. + */ + point_add_mixed(tx, ty, tz, nx, ny, nz, px, py); + /* The result of point_add_mixed is incorrect if {nx,ny,nz} is zero + * (a.k.a. the point at infinity). We handle that situation by + * copying the point from the table. + */ + copy_conditional(nx, px, n_is_infinity_mask); + copy_conditional(ny, py, n_is_infinity_mask); + copy_conditional(nz, kOne, n_is_infinity_mask); + + /* Equally, the result is also wrong if the point from the table is + * zero, which happens when the index is zero. We handle that by + * only copying from {tx,ty,tz} to {nx,ny,nz} if index != 0. + */ + p_is_noninfinite_mask = NON_ZERO_TO_ALL_ONES(index); + mask = p_is_noninfinite_mask & ~n_is_infinity_mask; + copy_conditional(nx, tx, mask); + copy_conditional(ny, ty, mask); + copy_conditional(nz, tz, mask); + /* If p was not zero, then n is now non-zero. */ + n_is_infinity_mask &= ~p_is_noninfinite_mask; + } } } /* point_to_affine converts a Jacobian point to an affine point. If the input * is the point at infinity then it returns (0, 0) in constant time. */ -static void point_to_affine(felem x_out, felem y_out, - const felem nx, const felem ny, const felem nz) { +static void +point_to_affine(felem x_out, felem y_out, + const felem nx, const felem ny, const felem nz) +{ felem z_inv, z_inv_sq; felem_inv(z_inv, nz); felem_square(z_inv_sq, z_inv); @@ -1183,8 +1206,9 @@ static void point_to_affine(felem x_out, felem y_out, } /* scalar_mult sets {nx,ny,nz} = scalar*{x,y}. */ -static void scalar_mult(felem nx, felem ny, felem nz, - const felem x, const felem y, const u8 scalar[32]) +static void +scalar_mult(felem nx, felem ny, felem nz, + const felem x, const felem y, const u8 scalar[32]) { int i; felem px, py, pz, tx, ty, tz; @@ -1198,11 +1222,11 @@ static void scalar_mult(felem nx, felem ny, felem nz, memcpy(&precomp[1][2], kOne, sizeof(felem)); for (i = 2; i < 16; i += 2) { - point_double(precomp[i][0], precomp[i][1], precomp[i][2], - precomp[i / 2][0], precomp[i / 2][1], precomp[i / 2][2]); + point_double(precomp[i][0], precomp[i][1], precomp[i][2], + precomp[i / 2][0], precomp[i / 2][1], precomp[i / 2][2]); - point_add_mixed(precomp[i + 1][0], precomp[i + 1][1], precomp[i + 1][2], - precomp[i][0], precomp[i][1], precomp[i][2], x, y); + point_add_mixed(precomp[i + 1][0], precomp[i + 1][1], precomp[i + 1][2], + precomp[i][0], precomp[i][1], precomp[i][2], x, y); } memset(nx, 0, sizeof(felem)); @@ -1212,33 +1236,33 @@ static void scalar_mult(felem nx, felem ny, felem nz, /* We add in a window of four bits each iteration and do this 64 times. */ for (i = 0; i < 64; i++) { - if (i) { - point_double(nx, ny, nz, nx, ny, nz); - point_double(nx, ny, nz, nx, ny, nz); - point_double(nx, ny, nz, nx, ny, nz); - point_double(nx, ny, nz, nx, ny, nz); - } - - index = scalar[31 - i / 2]; - if ((i & 1) == 1) { - index &= 15; - } else { - index >>= 4; - } - - /* See the comments in scalar_base_mult about handling infinities. */ - select_jacobian_point(px, py, pz, precomp[0][0], index); - point_add(tx, ty, tz, nx, ny, nz, px, py, pz); - copy_conditional(nx, px, n_is_infinity_mask); - copy_conditional(ny, py, n_is_infinity_mask); - copy_conditional(nz, pz, n_is_infinity_mask); - - p_is_noninfinite_mask = NON_ZERO_TO_ALL_ONES(index); - mask = p_is_noninfinite_mask & ~n_is_infinity_mask; - copy_conditional(nx, tx, mask); - copy_conditional(ny, ty, mask); - copy_conditional(nz, tz, mask); - n_is_infinity_mask &= ~p_is_noninfinite_mask; + if (i) { + point_double(nx, ny, nz, nx, ny, nz); + point_double(nx, ny, nz, nx, ny, nz); + point_double(nx, ny, nz, nx, ny, nz); + point_double(nx, ny, nz, nx, ny, nz); + } + + index = scalar[31 - i / 2]; + if ((i & 1) == 1) { + index &= 15; + } else { + index >>= 4; + } + + /* See the comments in scalar_base_mult about handling infinities. */ + select_jacobian_point(px, py, pz, precomp[0][0], index); + point_add(tx, ty, tz, nx, ny, nz, px, py, pz); + copy_conditional(nx, px, n_is_infinity_mask); + copy_conditional(ny, py, n_is_infinity_mask); + copy_conditional(nz, pz, n_is_infinity_mask); + + p_is_noninfinite_mask = NON_ZERO_TO_ALL_ONES(index); + mask = p_is_noninfinite_mask & ~n_is_infinity_mask; + copy_conditional(nx, tx, mask); + copy_conditional(ny, ty, mask); + copy_conditional(nz, tz, mask); + n_is_infinity_mask &= ~p_is_noninfinite_mask; } } @@ -1254,12 +1278,12 @@ static void scalar_mult(felem nx, felem ny, felem nz, #define BYTESWAP64(x) OSSwapInt64(x) #else #define BYTESWAP32(x) \ - (((x) >> 24) | (((x) >> 8) & 0xff00) | (((x) & 0xff00) << 8) | ((x) << 24)) -#define BYTESWAP64(x) \ - (((x) >> 56) | (((x) >> 40) & 0xff00) | \ + (((x) >> 24) | (((x) >> 8) & 0xff00) | (((x)&0xff00) << 8) | ((x) << 24)) +#define BYTESWAP64(x) \ + (((x) >> 56) | (((x) >> 40) & 0xff00) | \ (((x) >> 24) & 0xff0000) | (((x) >> 8) & 0xff000000) | \ - (((x) & 0xff000000) << 8) | (((x) & 0xff0000) << 24) | \ - (((x) & 0xff00) << 40) | ((x) << 56)) + (((x)&0xff000000) << 8) | (((x)&0xff0000) << 24) | \ + (((x)&0xff00) << 40) | ((x) << 56)) #endif #ifdef MP_USE_UINT_DIGIT @@ -1276,23 +1300,24 @@ static const mp_digit kRInvDigits[8] = { }; #else static const mp_digit kRInvDigits[4] = { - PR_UINT64(0x180000000), 0xffffffff, + PR_UINT64(0x180000000), 0xffffffff, PR_UINT64(0xfffffffe80000001), PR_UINT64(0x7fffffff00000001) }; #endif -#define MP_DIGITS_IN_256_BITS (32/sizeof(mp_digit)) +#define MP_DIGITS_IN_256_BITS (32 / sizeof(mp_digit)) static const mp_int kRInv = { MP_ZPOS, MP_DIGITS_IN_256_BITS, MP_DIGITS_IN_256_BITS, - (mp_digit*) kRInvDigits + (mp_digit *)kRInvDigits }; static const limb kTwo28 = 0x10000000; static const limb kTwo29 = 0x20000000; /* to_montgomery sets out = R*in. */ -static mp_err to_montgomery(felem out, const mp_int *in, const ECGroup *group) +static mp_err +to_montgomery(felem out, const mp_int *in, const ECGroup *group) { /* There are no MPI functions for bitshift operations and we wish to shift * in 257 bits left so we move the digits 256-bits left and then multiply @@ -1302,23 +1327,23 @@ static mp_err to_montgomery(felem out, const mp_int *in, const ECGroup *group) int i; mp_err res; - mp_init(&in_shifted); - s_mp_pad(&in_shifted, MP_USED(in) + MP_DIGITS_IN_256_BITS); + MP_CHECKOK(mp_init(&in_shifted)); + MP_CHECKOK(s_mp_pad(&in_shifted, MP_USED(in) + MP_DIGITS_IN_256_BITS)); memcpy(&MP_DIGIT(&in_shifted, MP_DIGITS_IN_256_BITS), - MP_DIGITS(in), - MP_USED(in)*sizeof(mp_digit)); - mp_mul_2(&in_shifted, &in_shifted); + MP_DIGITS(in), + MP_USED(in) * sizeof(mp_digit)); + MP_CHECKOK(mp_mul_2(&in_shifted, &in_shifted)); MP_CHECKOK(group->meth->field_mod(&in_shifted, &in_shifted, group->meth)); for (i = 0;; i++) { - out[i] = MP_DIGIT(&in_shifted, 0) & kBottom29Bits; - mp_div_d(&in_shifted, kTwo29, &in_shifted, NULL); - - i++; - if (i == NLIMBS) - break; - out[i] = MP_DIGIT(&in_shifted, 0) & kBottom28Bits; - mp_div_d(&in_shifted, kTwo28, &in_shifted, NULL); + out[i] = MP_DIGIT(&in_shifted, 0) & kBottom29Bits; + MP_CHECKOK(mp_div_d(&in_shifted, kTwo29, &in_shifted, NULL)); + + i++; + if (i == NLIMBS) + break; + out[i] = MP_DIGIT(&in_shifted, 0) & kBottom28Bits; + MP_CHECKOK(mp_div_d(&in_shifted, kTwo28, &in_shifted, NULL)); } CLEANUP: @@ -1327,24 +1352,25 @@ CLEANUP: } /* from_montgomery sets out=in/R. */ -static mp_err from_montgomery(mp_int *out, const felem in, - const ECGroup *group) +static mp_err +from_montgomery(mp_int *out, const felem in, + const ECGroup *group) { mp_int result, tmp; mp_err res; int i; - mp_init(&result); - mp_init(&tmp); - - MP_CHECKOK(mp_add_d(&tmp, in[NLIMBS-1], &result)); - for (i = NLIMBS-2; i >= 0; i--) { - if ((i & 1) == 0) { - MP_CHECKOK(mp_mul_d(&result, kTwo29, &tmp)); - } else { - MP_CHECKOK(mp_mul_d(&result, kTwo28, &tmp)); - } - MP_CHECKOK(mp_add_d(&tmp, in[i], &result)); + MP_CHECKOK(mp_init(&result)); + MP_CHECKOK(mp_init(&tmp)); + + MP_CHECKOK(mp_add_d(&tmp, in[NLIMBS - 1], &result)); + for (i = NLIMBS - 2; i >= 0; i--) { + if ((i & 1) == 0) { + MP_CHECKOK(mp_mul_d(&result, kTwo29, &tmp)); + } else { + MP_CHECKOK(mp_mul_d(&result, kTwo28, &tmp)); + } + MP_CHECKOK(mp_add_d(&tmp, in[i], &result)); } MP_CHECKOK(mp_mul(&result, &kRInv, out)); @@ -1357,7 +1383,8 @@ CLEANUP: } /* scalar_from_mp_int sets out_scalar=n, where n < the group order. */ -static void scalar_from_mp_int(u8 out_scalar[32], const mp_int *n) +static void +scalar_from_mp_int(u8 out_scalar[32], const mp_int *n) { /* We require that |n| is less than the order of the group and therefore it * will fit into |out_scalar|. However, these is a timing side-channel here @@ -1369,12 +1396,12 @@ static void scalar_from_mp_int(u8 out_scalar[32], const mp_int *n) memcpy(out_scalar, MP_DIGITS(n), MP_USED(n) * sizeof(mp_digit)); #else { - mp_size i; - mp_digit swapped[MP_DIGITS_IN_256_BITS]; - for (i = 0; i < MP_USED(n); i++) { - swapped[i] = BYTESWAP_MP_DIGIT_TO_LE(MP_DIGIT(n, i)); - } - memcpy(out_scalar, swapped, MP_USED(n) * sizeof(mp_digit)); + mp_size i; + mp_digit swapped[MP_DIGITS_IN_256_BITS]; + for (i = 0; i < MP_USED(n); i++) { + swapped[i] = BYTESWAP_MP_DIGIT_TO_LE(MP_DIGIT(n, i)); + } + memcpy(out_scalar, swapped, MP_USED(n) * sizeof(mp_digit)); } #endif } @@ -1382,9 +1409,10 @@ static void scalar_from_mp_int(u8 out_scalar[32], const mp_int *n) /* ec_GFp_nistp256_base_point_mul sets {out_x,out_y} = nG, where n is < the * order of the group. */ -static mp_err ec_GFp_nistp256_base_point_mul(const mp_int *n, - mp_int *out_x, mp_int *out_y, - const ECGroup *group) +static mp_err +ec_GFp_nistp256_base_point_mul(const mp_int *n, + mp_int *out_x, mp_int *out_y, + const ECGroup *group) { u8 scalar[32]; felem x, y, z, x_affine, y_affine; @@ -1405,10 +1433,11 @@ CLEANUP: /* ec_GFp_nistp256_point_mul sets {out_x,out_y} = n*{in_x,in_y}, where n is < * the order of the group. */ -static mp_err ec_GFp_nistp256_point_mul(const mp_int *n, - const mp_int *in_x, const mp_int *in_y, - mp_int *out_x, mp_int *out_y, - const ECGroup *group) +static mp_err +ec_GFp_nistp256_point_mul(const mp_int *n, + const mp_int *in_x, const mp_int *in_y, + mp_int *out_x, mp_int *out_y, + const ECGroup *group) { u8 scalar[32]; felem x, y, z, x_affine, y_affine, px, py; @@ -1435,11 +1464,12 @@ CLEANUP: * is safe because it's used for signature validation which doesn't deal * with secrets. */ -static mp_err ec_GFp_nistp256_points_mul_vartime( - const mp_int *n1, const mp_int *n2, - const mp_int *in_x, const mp_int *in_y, - mp_int *out_x, mp_int *out_y, - const ECGroup *group) +static mp_err +ec_GFp_nistp256_points_mul_vartime( + const mp_int *n1, const mp_int *n2, + const mp_int *in_x, const mp_int *in_y, + mp_int *out_x, mp_int *out_y, + const ECGroup *group) { u8 scalar1[32], scalar2[32]; felem x1, y1, z1, x2, y2, z2, x_affine, y_affine, px, py; @@ -1447,19 +1477,19 @@ static mp_err ec_GFp_nistp256_points_mul_vartime( /* If n2 == NULL, this is just a base-point multiplication. */ if (n2 == NULL) { - return ec_GFp_nistp256_base_point_mul(n1, out_x, out_y, group); + return ec_GFp_nistp256_base_point_mul(n1, out_x, out_y, group); } /* If n1 == nULL, this is just an arbitary-point multiplication. */ if (n1 == NULL) { - return ec_GFp_nistp256_point_mul(n2, in_x, in_y, out_x, out_y, group); + return ec_GFp_nistp256_point_mul(n2, in_x, in_y, out_x, out_y, group); } /* If both scalars are zero, then the result is the point at infinity. */ if (mp_cmp_z(n1) == 0 && mp_cmp_z(n2) == 0) { - mp_zero(out_x); - mp_zero(out_y); - return res; + mp_zero(out_x); + mp_zero(out_y); + return res; } scalar_from_mp_int(scalar1, n1); @@ -1471,17 +1501,17 @@ static mp_err ec_GFp_nistp256_points_mul_vartime( scalar_mult(x2, y2, z2, px, py, scalar2); if (mp_cmp_z(n2) == 0) { - /* If n2 == 0, then {x2,y2,z2} is zero and the result is just - * {x1,y1,z1}. */ + /* If n2 == 0, then {x2,y2,z2} is zero and the result is just + * {x1,y1,z1}. */ } else if (mp_cmp_z(n1) == 0) { - /* If n1 == 0, then {x1,y1,z1} is zero and the result is just - * {x2,y2,z2}. */ - memcpy(x1, x2, sizeof(x2)); - memcpy(y1, y2, sizeof(y2)); - memcpy(z1, z2, sizeof(z2)); + /* If n1 == 0, then {x1,y1,z1} is zero and the result is just + * {x2,y2,z2}. */ + memcpy(x1, x2, sizeof(x2)); + memcpy(y1, y2, sizeof(y2)); + memcpy(z1, z2, sizeof(z2)); } else { - /* This function handles the case where {x1,y1,z1} == {x2,y2,z2}. */ - point_add_or_double_vartime(x1, y1, z1, x1, y1, z1, x2, y2, z2); + /* This function handles the case where {x1,y1,z1} == {x2,y2,z2}. */ + point_add_or_double_vartime(x1, y1, z1, x1, y1, z1, x2, y2, z2); } point_to_affine(x_affine, y_affine, x1, y1, z1); @@ -1493,7 +1523,8 @@ CLEANUP: } /* Wire in fast point multiplication for named curves. */ -mp_err ec_group_set_gfp256_32(ECGroup *group, ECCurveName name) +mp_err +ec_group_set_gfp256_32(ECGroup *group, ECCurveName name) { if (name == ECCurve_NIST_P256) { group->base_point_mul = &ec_GFp_nistp256_base_point_mul; diff --git a/nss/lib/freebl/ecl/ecp_384.c b/nss/lib/freebl/ecl/ecp_384.c index 4c1e85e..702fd97 100644 --- a/nss/lib/freebl/ecl/ecp_384.c +++ b/nss/lib/freebl/ecl/ecp_384.c @@ -7,226 +7,226 @@ #include "mplogic.h" #include "mpi-priv.h" -/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r. - * Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to +/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r. + * Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to * Elliptic Curve Cryptography. */ static mp_err ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; - int a_bits = mpl_significant_bits(a); - int i; + mp_err res = MP_OKAY; + int a_bits = mpl_significant_bits(a); + int i; - /* m1, m2 are statically-allocated mp_int of exactly the size we need */ - mp_int m[10]; + /* m1, m2 are statically-allocated mp_int of exactly the size we need */ + mp_int m[10]; #ifdef ECL_THIRTY_TWO_BIT - mp_digit s[10][12]; - for (i = 0; i < 10; i++) { - MP_SIGN(&m[i]) = MP_ZPOS; - MP_ALLOC(&m[i]) = 12; - MP_USED(&m[i]) = 12; - MP_DIGITS(&m[i]) = s[i]; - } + mp_digit s[10][12]; + for (i = 0; i < 10; i++) { + MP_SIGN(&m[i]) = MP_ZPOS; + MP_ALLOC(&m[i]) = 12; + MP_USED(&m[i]) = 12; + MP_DIGITS(&m[i]) = s[i]; + } #else - mp_digit s[10][6]; - for (i = 0; i < 10; i++) { - MP_SIGN(&m[i]) = MP_ZPOS; - MP_ALLOC(&m[i]) = 6; - MP_USED(&m[i]) = 6; - MP_DIGITS(&m[i]) = s[i]; - } + mp_digit s[10][6]; + for (i = 0; i < 10; i++) { + MP_SIGN(&m[i]) = MP_ZPOS; + MP_ALLOC(&m[i]) = 6; + MP_USED(&m[i]) = 6; + MP_DIGITS(&m[i]) = s[i]; + } #endif #ifdef ECL_THIRTY_TWO_BIT - /* for polynomials larger than twice the field size or polynomials - * not using all words, use regular reduction */ - if ((a_bits > 768) || (a_bits <= 736)) { - MP_CHECKOK(mp_mod(a, &meth->irr, r)); - } else { - for (i = 0; i < 12; i++) { - s[0][i] = MP_DIGIT(a, i); - } - s[1][0] = 0; - s[1][1] = 0; - s[1][2] = 0; - s[1][3] = 0; - s[1][4] = MP_DIGIT(a, 21); - s[1][5] = MP_DIGIT(a, 22); - s[1][6] = MP_DIGIT(a, 23); - s[1][7] = 0; - s[1][8] = 0; - s[1][9] = 0; - s[1][10] = 0; - s[1][11] = 0; - for (i = 0; i < 12; i++) { - s[2][i] = MP_DIGIT(a, i+12); - } - s[3][0] = MP_DIGIT(a, 21); - s[3][1] = MP_DIGIT(a, 22); - s[3][2] = MP_DIGIT(a, 23); - for (i = 3; i < 12; i++) { - s[3][i] = MP_DIGIT(a, i+9); - } - s[4][0] = 0; - s[4][1] = MP_DIGIT(a, 23); - s[4][2] = 0; - s[4][3] = MP_DIGIT(a, 20); - for (i = 4; i < 12; i++) { - s[4][i] = MP_DIGIT(a, i+8); - } - s[5][0] = 0; - s[5][1] = 0; - s[5][2] = 0; - s[5][3] = 0; - s[5][4] = MP_DIGIT(a, 20); - s[5][5] = MP_DIGIT(a, 21); - s[5][6] = MP_DIGIT(a, 22); - s[5][7] = MP_DIGIT(a, 23); - s[5][8] = 0; - s[5][9] = 0; - s[5][10] = 0; - s[5][11] = 0; - s[6][0] = MP_DIGIT(a, 20); - s[6][1] = 0; - s[6][2] = 0; - s[6][3] = MP_DIGIT(a, 21); - s[6][4] = MP_DIGIT(a, 22); - s[6][5] = MP_DIGIT(a, 23); - s[6][6] = 0; - s[6][7] = 0; - s[6][8] = 0; - s[6][9] = 0; - s[6][10] = 0; - s[6][11] = 0; - s[7][0] = MP_DIGIT(a, 23); - for (i = 1; i < 12; i++) { - s[7][i] = MP_DIGIT(a, i+11); - } - s[8][0] = 0; - s[8][1] = MP_DIGIT(a, 20); - s[8][2] = MP_DIGIT(a, 21); - s[8][3] = MP_DIGIT(a, 22); - s[8][4] = MP_DIGIT(a, 23); - s[8][5] = 0; - s[8][6] = 0; - s[8][7] = 0; - s[8][8] = 0; - s[8][9] = 0; - s[8][10] = 0; - s[8][11] = 0; - s[9][0] = 0; - s[9][1] = 0; - s[9][2] = 0; - s[9][3] = MP_DIGIT(a, 23); - s[9][4] = MP_DIGIT(a, 23); - s[9][5] = 0; - s[9][6] = 0; - s[9][7] = 0; - s[9][8] = 0; - s[9][9] = 0; - s[9][10] = 0; - s[9][11] = 0; + /* for polynomials larger than twice the field size or polynomials + * not using all words, use regular reduction */ + if ((a_bits > 768) || (a_bits <= 736)) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + for (i = 0; i < 12; i++) { + s[0][i] = MP_DIGIT(a, i); + } + s[1][0] = 0; + s[1][1] = 0; + s[1][2] = 0; + s[1][3] = 0; + s[1][4] = MP_DIGIT(a, 21); + s[1][5] = MP_DIGIT(a, 22); + s[1][6] = MP_DIGIT(a, 23); + s[1][7] = 0; + s[1][8] = 0; + s[1][9] = 0; + s[1][10] = 0; + s[1][11] = 0; + for (i = 0; i < 12; i++) { + s[2][i] = MP_DIGIT(a, i + 12); + } + s[3][0] = MP_DIGIT(a, 21); + s[3][1] = MP_DIGIT(a, 22); + s[3][2] = MP_DIGIT(a, 23); + for (i = 3; i < 12; i++) { + s[3][i] = MP_DIGIT(a, i + 9); + } + s[4][0] = 0; + s[4][1] = MP_DIGIT(a, 23); + s[4][2] = 0; + s[4][3] = MP_DIGIT(a, 20); + for (i = 4; i < 12; i++) { + s[4][i] = MP_DIGIT(a, i + 8); + } + s[5][0] = 0; + s[5][1] = 0; + s[5][2] = 0; + s[5][3] = 0; + s[5][4] = MP_DIGIT(a, 20); + s[5][5] = MP_DIGIT(a, 21); + s[5][6] = MP_DIGIT(a, 22); + s[5][7] = MP_DIGIT(a, 23); + s[5][8] = 0; + s[5][9] = 0; + s[5][10] = 0; + s[5][11] = 0; + s[6][0] = MP_DIGIT(a, 20); + s[6][1] = 0; + s[6][2] = 0; + s[6][3] = MP_DIGIT(a, 21); + s[6][4] = MP_DIGIT(a, 22); + s[6][5] = MP_DIGIT(a, 23); + s[6][6] = 0; + s[6][7] = 0; + s[6][8] = 0; + s[6][9] = 0; + s[6][10] = 0; + s[6][11] = 0; + s[7][0] = MP_DIGIT(a, 23); + for (i = 1; i < 12; i++) { + s[7][i] = MP_DIGIT(a, i + 11); + } + s[8][0] = 0; + s[8][1] = MP_DIGIT(a, 20); + s[8][2] = MP_DIGIT(a, 21); + s[8][3] = MP_DIGIT(a, 22); + s[8][4] = MP_DIGIT(a, 23); + s[8][5] = 0; + s[8][6] = 0; + s[8][7] = 0; + s[8][8] = 0; + s[8][9] = 0; + s[8][10] = 0; + s[8][11] = 0; + s[9][0] = 0; + s[9][1] = 0; + s[9][2] = 0; + s[9][3] = MP_DIGIT(a, 23); + s[9][4] = MP_DIGIT(a, 23); + s[9][5] = 0; + s[9][6] = 0; + s[9][7] = 0; + s[9][8] = 0; + s[9][9] = 0; + s[9][10] = 0; + s[9][11] = 0; - MP_CHECKOK(mp_add(&m[0], &m[1], r)); - MP_CHECKOK(mp_add(r, &m[1], r)); - MP_CHECKOK(mp_add(r, &m[2], r)); - MP_CHECKOK(mp_add(r, &m[3], r)); - MP_CHECKOK(mp_add(r, &m[4], r)); - MP_CHECKOK(mp_add(r, &m[5], r)); - MP_CHECKOK(mp_add(r, &m[6], r)); - MP_CHECKOK(mp_sub(r, &m[7], r)); - MP_CHECKOK(mp_sub(r, &m[8], r)); - MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); - s_mp_clamp(r); - } + MP_CHECKOK(mp_add(&m[0], &m[1], r)); + MP_CHECKOK(mp_add(r, &m[1], r)); + MP_CHECKOK(mp_add(r, &m[2], r)); + MP_CHECKOK(mp_add(r, &m[3], r)); + MP_CHECKOK(mp_add(r, &m[4], r)); + MP_CHECKOK(mp_add(r, &m[5], r)); + MP_CHECKOK(mp_add(r, &m[6], r)); + MP_CHECKOK(mp_sub(r, &m[7], r)); + MP_CHECKOK(mp_sub(r, &m[8], r)); + MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); + s_mp_clamp(r); + } #else - /* for polynomials larger than twice the field size or polynomials - * not using all words, use regular reduction */ - if ((a_bits > 768) || (a_bits <= 736)) { - MP_CHECKOK(mp_mod(a, &meth->irr, r)); - } else { - for (i = 0; i < 6; i++) { - s[0][i] = MP_DIGIT(a, i); - } - s[1][0] = 0; - s[1][1] = 0; - s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); - s[1][3] = MP_DIGIT(a, 11) >> 32; - s[1][4] = 0; - s[1][5] = 0; - for (i = 0; i < 6; i++) { - s[2][i] = MP_DIGIT(a, i+6); - } - s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); - s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); - for (i = 2; i < 6; i++) { - s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32); - } - s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32; - s[4][1] = MP_DIGIT(a, 10) << 32; - for (i = 2; i < 6; i++) { - s[4][i] = MP_DIGIT(a, i+4); - } - s[5][0] = 0; - s[5][1] = 0; - s[5][2] = MP_DIGIT(a, 10); - s[5][3] = MP_DIGIT(a, 11); - s[5][4] = 0; - s[5][5] = 0; - s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32; - s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32; - s[6][2] = MP_DIGIT(a, 11); - s[6][3] = 0; - s[6][4] = 0; - s[6][5] = 0; - s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); - for (i = 1; i < 6; i++) { - s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32); - } - s[8][0] = MP_DIGIT(a, 10) << 32; - s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); - s[8][2] = MP_DIGIT(a, 11) >> 32; - s[8][3] = 0; - s[8][4] = 0; - s[8][5] = 0; - s[9][0] = 0; - s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32; - s[9][2] = MP_DIGIT(a, 11) >> 32; - s[9][3] = 0; - s[9][4] = 0; - s[9][5] = 0; + /* for polynomials larger than twice the field size or polynomials + * not using all words, use regular reduction */ + if ((a_bits > 768) || (a_bits <= 736)) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + for (i = 0; i < 6; i++) { + s[0][i] = MP_DIGIT(a, i); + } + s[1][0] = 0; + s[1][1] = 0; + s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); + s[1][3] = MP_DIGIT(a, 11) >> 32; + s[1][4] = 0; + s[1][5] = 0; + for (i = 0; i < 6; i++) { + s[2][i] = MP_DIGIT(a, i + 6); + } + s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); + s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); + for (i = 2; i < 6; i++) { + s[3][i] = (MP_DIGIT(a, i + 4) >> 32) | (MP_DIGIT(a, i + 5) << 32); + } + s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32; + s[4][1] = MP_DIGIT(a, 10) << 32; + for (i = 2; i < 6; i++) { + s[4][i] = MP_DIGIT(a, i + 4); + } + s[5][0] = 0; + s[5][1] = 0; + s[5][2] = MP_DIGIT(a, 10); + s[5][3] = MP_DIGIT(a, 11); + s[5][4] = 0; + s[5][5] = 0; + s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32; + s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32; + s[6][2] = MP_DIGIT(a, 11); + s[6][3] = 0; + s[6][4] = 0; + s[6][5] = 0; + s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32); + for (i = 1; i < 6; i++) { + s[7][i] = (MP_DIGIT(a, i + 5) >> 32) | (MP_DIGIT(a, i + 6) << 32); + } + s[8][0] = MP_DIGIT(a, 10) << 32; + s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32); + s[8][2] = MP_DIGIT(a, 11) >> 32; + s[8][3] = 0; + s[8][4] = 0; + s[8][5] = 0; + s[9][0] = 0; + s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32; + s[9][2] = MP_DIGIT(a, 11) >> 32; + s[9][3] = 0; + s[9][4] = 0; + s[9][5] = 0; - MP_CHECKOK(mp_add(&m[0], &m[1], r)); - MP_CHECKOK(mp_add(r, &m[1], r)); - MP_CHECKOK(mp_add(r, &m[2], r)); - MP_CHECKOK(mp_add(r, &m[3], r)); - MP_CHECKOK(mp_add(r, &m[4], r)); - MP_CHECKOK(mp_add(r, &m[5], r)); - MP_CHECKOK(mp_add(r, &m[6], r)); - MP_CHECKOK(mp_sub(r, &m[7], r)); - MP_CHECKOK(mp_sub(r, &m[8], r)); - MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); - s_mp_clamp(r); - } + MP_CHECKOK(mp_add(&m[0], &m[1], r)); + MP_CHECKOK(mp_add(r, &m[1], r)); + MP_CHECKOK(mp_add(r, &m[2], r)); + MP_CHECKOK(mp_add(r, &m[3], r)); + MP_CHECKOK(mp_add(r, &m[4], r)); + MP_CHECKOK(mp_add(r, &m[5], r)); + MP_CHECKOK(mp_add(r, &m[6], r)); + MP_CHECKOK(mp_sub(r, &m[7], r)); + MP_CHECKOK(mp_sub(r, &m[8], r)); + MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r)); + s_mp_clamp(r); + } #endif - CLEANUP: - return res; +CLEANUP: + return res; } /* Compute the square of polynomial a, reduce modulo p384. Store the - * result in r. r could be a. Uses optimized modular reduction for p384. + * result in r. r could be a. Uses optimized modular reduction for p384. */ static mp_err ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; - MP_CHECKOK(mp_sqr(a, r)); - MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); - CLEANUP: - return res; + MP_CHECKOK(mp_sqr(a, r)); + MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); +CLEANUP: + return res; } /* Compute the product of two polynomials a and b, reduce modulo p384. @@ -234,14 +234,14 @@ ec_GFp_nistp384_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) * optimized modular reduction for p384. */ static mp_err ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; - MP_CHECKOK(mp_mul(a, b, r)); - MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); - CLEANUP: - return res; + MP_CHECKOK(mp_mul(a, b, r)); + MP_CHECKOK(ec_GFp_nistp384_mod(r, r, meth)); +CLEANUP: + return res; } /* Wire in fast field arithmetic and precomputation of base point for @@ -249,10 +249,10 @@ ec_GFp_nistp384_mul(const mp_int *a, const mp_int *b, mp_int *r, mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName name) { - if (name == ECCurve_NIST_P384) { - group->meth->field_mod = &ec_GFp_nistp384_mod; - group->meth->field_mul = &ec_GFp_nistp384_mul; - group->meth->field_sqr = &ec_GFp_nistp384_sqr; - } - return MP_OKAY; + if (name == ECCurve_NIST_P384) { + group->meth->field_mod = &ec_GFp_nistp384_mod; + group->meth->field_mul = &ec_GFp_nistp384_mul; + group->meth->field_sqr = &ec_GFp_nistp384_sqr; + } + return MP_OKAY; } diff --git a/nss/lib/freebl/ecl/ecp_521.c b/nss/lib/freebl/ecl/ecp_521.c index f70c2f4..6ca0dbb 100644 --- a/nss/lib/freebl/ecl/ecp_521.c +++ b/nss/lib/freebl/ecl/ecp_521.c @@ -10,76 +10,76 @@ #define ECP521_DIGITS ECL_CURVE_DIGITS(521) /* Fast modular reduction for p521 = 2^521 - 1. a can be r. Uses - * algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to + * algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to * Elliptic Curve Cryptography. */ static mp_err ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; - int a_bits = mpl_significant_bits(a); - unsigned int i; - - /* m1, m2 are statically-allocated mp_int of exactly the size we need */ - mp_int m1; - - mp_digit s1[ECP521_DIGITS] = { 0 }; - - MP_SIGN(&m1) = MP_ZPOS; - MP_ALLOC(&m1) = ECP521_DIGITS; - MP_USED(&m1) = ECP521_DIGITS; - MP_DIGITS(&m1) = s1; - - if (a_bits < 521) { - if (a==r) return MP_OKAY; - return mp_copy(a, r); - } - /* for polynomials larger than twice the field size or polynomials - * not using all words, use regular reduction */ - if (a_bits > (521*2)) { - MP_CHECKOK(mp_mod(a, &meth->irr, r)); - } else { -#define FIRST_DIGIT (ECP521_DIGITS-1) - for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) { - s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9) - | (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9)); - } - s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9; - - if ( a != r ) { - MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS)); - for (i = 0; i < ECP521_DIGITS; i++) { - MP_DIGIT(r,i) = MP_DIGIT(a, i); - } - } - MP_USED(r) = ECP521_DIGITS; - MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF; - - MP_CHECKOK(s_mp_add(r, &m1)); - if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) { - MP_CHECKOK(s_mp_add_d(r,1)); - MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF; - } else if (s_mp_cmp(r, &meth->irr) == 0) { - mp_zero(r); - } - s_mp_clamp(r); - } - - CLEANUP: - return res; + mp_err res = MP_OKAY; + int a_bits = mpl_significant_bits(a); + unsigned int i; + + /* m1, m2 are statically-allocated mp_int of exactly the size we need */ + mp_int m1; + + mp_digit s1[ECP521_DIGITS] = { 0 }; + + MP_SIGN(&m1) = MP_ZPOS; + MP_ALLOC(&m1) = ECP521_DIGITS; + MP_USED(&m1) = ECP521_DIGITS; + MP_DIGITS(&m1) = s1; + + if (a_bits < 521) { + if (a == r) + return MP_OKAY; + return mp_copy(a, r); + } + /* for polynomials larger than twice the field size or polynomials + * not using all words, use regular reduction */ + if (a_bits > (521 * 2)) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { +#define FIRST_DIGIT (ECP521_DIGITS - 1) + for (i = FIRST_DIGIT; i < MP_USED(a) - 1; i++) { + s1[i - FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9) | (MP_DIGIT(a, 1 + i) << (MP_DIGIT_BIT - 9)); + } + s1[i - FIRST_DIGIT] = MP_DIGIT(a, i) >> 9; + + if (a != r) { + MP_CHECKOK(s_mp_pad(r, ECP521_DIGITS)); + for (i = 0; i < ECP521_DIGITS; i++) { + MP_DIGIT(r, i) = MP_DIGIT(a, i); + } + } + MP_USED(r) = ECP521_DIGITS; + MP_DIGIT(r, FIRST_DIGIT) &= 0x1FF; + + MP_CHECKOK(s_mp_add(r, &m1)); + if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) { + MP_CHECKOK(s_mp_add_d(r, 1)); + MP_DIGIT(r, FIRST_DIGIT) &= 0x1FF; + } else if (s_mp_cmp(r, &meth->irr) == 0) { + mp_zero(r); + } + s_mp_clamp(r); + } + +CLEANUP: + return res; } /* Compute the square of polynomial a, reduce modulo p521. Store the - * result in r. r could be a. Uses optimized modular reduction for p521. + * result in r. r could be a. Uses optimized modular reduction for p521. */ static mp_err ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; - MP_CHECKOK(mp_sqr(a, r)); - MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth)); - CLEANUP: - return res; + MP_CHECKOK(mp_sqr(a, r)); + MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth)); +CLEANUP: + return res; } /* Compute the product of two polynomials a and b, reduce modulo p521. @@ -87,39 +87,39 @@ ec_GFp_nistp521_sqr(const mp_int *a, mp_int *r, const GFMethod *meth) * optimized modular reduction for p521. */ static mp_err ec_GFp_nistp521_mul(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; - MP_CHECKOK(mp_mul(a, b, r)); - MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth)); - CLEANUP: - return res; + MP_CHECKOK(mp_mul(a, b, r)); + MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth)); +CLEANUP: + return res; } /* Divides two field elements. If a is NULL, then returns the inverse of * b. */ static mp_err ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; - mp_int t; - - /* If a is NULL, then return the inverse of b, otherwise return a/b. */ - if (a == NULL) { - return mp_invmod(b, &meth->irr, r); - } else { - /* MPI doesn't support divmod, so we implement it using invmod and - * mulmod. */ - MP_CHECKOK(mp_init(&t)); - MP_CHECKOK(mp_invmod(b, &meth->irr, &t)); - MP_CHECKOK(mp_mul(a, &t, r)); - MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth)); - CLEANUP: - mp_clear(&t); - return res; - } + mp_err res = MP_OKAY; + mp_int t; + + /* If a is NULL, then return the inverse of b, otherwise return a/b. */ + if (a == NULL) { + return mp_invmod(b, &meth->irr, r); + } else { + /* MPI doesn't support divmod, so we implement it using invmod and + * mulmod. */ + MP_CHECKOK(mp_init(&t)); + MP_CHECKOK(mp_invmod(b, &meth->irr, &t)); + MP_CHECKOK(mp_mul(a, &t, r)); + MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth)); + CLEANUP: + mp_clear(&t); + return res; + } } /* Wire in fast field arithmetic and precomputation of base point for @@ -127,11 +127,11 @@ ec_GFp_nistp521_div(const mp_int *a, const mp_int *b, mp_int *r, mp_err ec_group_set_gfp521(ECGroup *group, ECCurveName name) { - if (name == ECCurve_NIST_P521) { - group->meth->field_mod = &ec_GFp_nistp521_mod; - group->meth->field_mul = &ec_GFp_nistp521_mul; - group->meth->field_sqr = &ec_GFp_nistp521_sqr; - group->meth->field_div = &ec_GFp_nistp521_div; - } - return MP_OKAY; + if (name == ECCurve_NIST_P521) { + group->meth->field_mod = &ec_GFp_nistp521_mod; + group->meth->field_mul = &ec_GFp_nistp521_mul; + group->meth->field_sqr = &ec_GFp_nistp521_sqr; + group->meth->field_div = &ec_GFp_nistp521_div; + } + return MP_OKAY; } diff --git a/nss/lib/freebl/ecl/ecp_aff.c b/nss/lib/freebl/ecl/ecp_aff.c index 92e8604..47fb273 100644 --- a/nss/lib/freebl/ecl/ecp_aff.c +++ b/nss/lib/freebl/ecl/ecp_aff.c @@ -11,107 +11,101 @@ mp_err ec_GFp_pt_is_inf_aff(const mp_int *px, const mp_int *py) { - if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) { - return MP_YES; - } else { - return MP_NO; - } - + if ((mp_cmp_z(px) == 0) && (mp_cmp_z(py) == 0)) { + return MP_YES; + } else { + return MP_NO; + } } /* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */ mp_err ec_GFp_pt_set_inf_aff(mp_int *px, mp_int *py) { - mp_zero(px); - mp_zero(py); - return MP_OKAY; + mp_zero(px); + mp_zero(py); + return MP_OKAY; } -/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P, +/* Computes R = P + Q based on IEEE P1363 A.10.1. Elliptic curve points P, * Q, and R can all be identical. Uses affine coordinates. Assumes input * is already field-encoded using field_enc, and returns output that is * still field-encoded. */ mp_err ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, - const ECGroup *group) + const mp_int *qy, mp_int *rx, mp_int *ry, + const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int lambda, temp, tempx, tempy; + mp_err res = MP_OKAY; + mp_int lambda, temp, tempx, tempy; - MP_DIGITS(&lambda) = 0; - MP_DIGITS(&temp) = 0; - MP_DIGITS(&tempx) = 0; - MP_DIGITS(&tempy) = 0; - MP_CHECKOK(mp_init(&lambda)); - MP_CHECKOK(mp_init(&temp)); - MP_CHECKOK(mp_init(&tempx)); - MP_CHECKOK(mp_init(&tempy)); - /* if P = inf, then R = Q */ - if (ec_GFp_pt_is_inf_aff(px, py) == 0) { - MP_CHECKOK(mp_copy(qx, rx)); - MP_CHECKOK(mp_copy(qy, ry)); - res = MP_OKAY; - goto CLEANUP; - } - /* if Q = inf, then R = P */ - if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - res = MP_OKAY; - goto CLEANUP; - } - /* if px != qx, then lambda = (py-qy) / (px-qx) */ - if (mp_cmp(px, qx) != 0) { - MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth)); - MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_div(&tempy, &tempx, &lambda, group->meth)); - } else { - /* if py != qy or qy = 0, then R = inf */ - if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) { - mp_zero(rx); - mp_zero(ry); - res = MP_OKAY; - goto CLEANUP; - } - /* lambda = (3qx^2+a) / (2qy) */ - MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth)); - MP_CHECKOK(mp_set_int(&temp, 3)); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth)); - } - MP_CHECKOK(group->meth-> - field_mul(&tempx, &temp, &tempx, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&tempx, &group->curvea, &tempx, group->meth)); - MP_CHECKOK(mp_set_int(&temp, 2)); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth)); - } - MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth)); - MP_CHECKOK(group->meth-> - field_div(&tempx, &tempy, &lambda, group->meth)); - } - /* rx = lambda^2 - px - qx */ - MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth)); - MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth)); - MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth)); - /* ry = (x1-x2) * lambda - y1 */ - MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(&tempy, &lambda, &tempy, group->meth)); - MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth)); - MP_CHECKOK(mp_copy(&tempx, rx)); - MP_CHECKOK(mp_copy(&tempy, ry)); + MP_DIGITS(&lambda) = 0; + MP_DIGITS(&temp) = 0; + MP_DIGITS(&tempx) = 0; + MP_DIGITS(&tempy) = 0; + MP_CHECKOK(mp_init(&lambda)); + MP_CHECKOK(mp_init(&temp)); + MP_CHECKOK(mp_init(&tempx)); + MP_CHECKOK(mp_init(&tempy)); + /* if P = inf, then R = Q */ + if (ec_GFp_pt_is_inf_aff(px, py) == 0) { + MP_CHECKOK(mp_copy(qx, rx)); + MP_CHECKOK(mp_copy(qy, ry)); + res = MP_OKAY; + goto CLEANUP; + } + /* if Q = inf, then R = P */ + if (ec_GFp_pt_is_inf_aff(qx, qy) == 0) { + MP_CHECKOK(mp_copy(px, rx)); + MP_CHECKOK(mp_copy(py, ry)); + res = MP_OKAY; + goto CLEANUP; + } + /* if px != qx, then lambda = (py-qy) / (px-qx) */ + if (mp_cmp(px, qx) != 0) { + MP_CHECKOK(group->meth->field_sub(py, qy, &tempy, group->meth)); + MP_CHECKOK(group->meth->field_sub(px, qx, &tempx, group->meth)); + MP_CHECKOK(group->meth->field_div(&tempy, &tempx, &lambda, group->meth)); + } else { + /* if py != qy or qy = 0, then R = inf */ + if (((mp_cmp(py, qy) != 0)) || (mp_cmp_z(qy) == 0)) { + mp_zero(rx); + mp_zero(ry); + res = MP_OKAY; + goto CLEANUP; + } + /* lambda = (3qx^2+a) / (2qy) */ + MP_CHECKOK(group->meth->field_sqr(qx, &tempx, group->meth)); + MP_CHECKOK(mp_set_int(&temp, 3)); + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth)); + } + MP_CHECKOK(group->meth->field_mul(&tempx, &temp, &tempx, group->meth)); + MP_CHECKOK(group->meth->field_add(&tempx, &group->curvea, &tempx, group->meth)); + MP_CHECKOK(mp_set_int(&temp, 2)); + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(&temp, &temp, group->meth)); + } + MP_CHECKOK(group->meth->field_mul(qy, &temp, &tempy, group->meth)); + MP_CHECKOK(group->meth->field_div(&tempx, &tempy, &lambda, group->meth)); + } + /* rx = lambda^2 - px - qx */ + MP_CHECKOK(group->meth->field_sqr(&lambda, &tempx, group->meth)); + MP_CHECKOK(group->meth->field_sub(&tempx, px, &tempx, group->meth)); + MP_CHECKOK(group->meth->field_sub(&tempx, qx, &tempx, group->meth)); + /* ry = (x1-x2) * lambda - y1 */ + MP_CHECKOK(group->meth->field_sub(qx, &tempx, &tempy, group->meth)); + MP_CHECKOK(group->meth->field_mul(&tempy, &lambda, &tempy, group->meth)); + MP_CHECKOK(group->meth->field_sub(&tempy, qy, &tempy, group->meth)); + MP_CHECKOK(mp_copy(&tempx, rx)); + MP_CHECKOK(mp_copy(&tempy, ry)); - CLEANUP: - mp_clear(&lambda); - mp_clear(&temp); - mp_clear(&tempx); - mp_clear(&tempy); - return res; +CLEANUP: + mp_clear(&lambda); + mp_clear(&temp); + mp_clear(&tempx); + mp_clear(&tempy); + return res; } /* Computes R = P - Q. Elliptic curve points P, Q, and R can all be @@ -120,20 +114,20 @@ ec_GFp_pt_add_aff(const mp_int *px, const mp_int *py, const mp_int *qx, * field-encoded. */ mp_err ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, - const ECGroup *group) + const mp_int *qy, mp_int *rx, mp_int *ry, + const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int nqy; + mp_err res = MP_OKAY; + mp_int nqy; - MP_DIGITS(&nqy) = 0; - MP_CHECKOK(mp_init(&nqy)); - /* nqy = -qy */ - MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth)); - res = group->point_add(px, py, qx, &nqy, rx, ry, group); - CLEANUP: - mp_clear(&nqy); - return res; + MP_DIGITS(&nqy) = 0; + MP_CHECKOK(mp_init(&nqy)); + /* nqy = -qy */ + MP_CHECKOK(group->meth->field_neg(qy, &nqy, group->meth)); + res = group->point_add(px, py, qx, &nqy, rx, ry, group); +CLEANUP: + mp_clear(&nqy); + return res; } /* Computes R = 2P. Elliptic curve points P and R can be identical. Uses @@ -141,177 +135,174 @@ ec_GFp_pt_sub_aff(const mp_int *px, const mp_int *py, const mp_int *qx, * field_enc, and returns output that is still field-encoded. */ mp_err ec_GFp_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, const ECGroup *group) + mp_int *ry, const ECGroup *group) { - return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group); + return ec_GFp_pt_add_aff(px, py, px, py, rx, ry, group); } /* by default, this routine is unused and thus doesn't need to be compiled */ #ifdef ECL_ENABLE_GFP_PT_MUL_AFF -/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and +/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and * R can be identical. Uses affine coordinates. Assumes input is already * field-encoded using field_enc, and returns output that is still * field-encoded. */ mp_err ec_GFp_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) + mp_int *rx, mp_int *ry, const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int k, k3, qx, qy, sx, sy; - int b1, b3, i, l; + mp_err res = MP_OKAY; + mp_int k, k3, qx, qy, sx, sy; + int b1, b3, i, l; - MP_DIGITS(&k) = 0; - MP_DIGITS(&k3) = 0; - MP_DIGITS(&qx) = 0; - MP_DIGITS(&qy) = 0; - MP_DIGITS(&sx) = 0; - MP_DIGITS(&sy) = 0; - MP_CHECKOK(mp_init(&k)); - MP_CHECKOK(mp_init(&k3)); - MP_CHECKOK(mp_init(&qx)); - MP_CHECKOK(mp_init(&qy)); - MP_CHECKOK(mp_init(&sx)); - MP_CHECKOK(mp_init(&sy)); + MP_DIGITS(&k) = 0; + MP_DIGITS(&k3) = 0; + MP_DIGITS(&qx) = 0; + MP_DIGITS(&qy) = 0; + MP_DIGITS(&sx) = 0; + MP_DIGITS(&sy) = 0; + MP_CHECKOK(mp_init(&k)); + MP_CHECKOK(mp_init(&k3)); + MP_CHECKOK(mp_init(&qx)); + MP_CHECKOK(mp_init(&qy)); + MP_CHECKOK(mp_init(&sx)); + MP_CHECKOK(mp_init(&sy)); - /* if n = 0 then r = inf */ - if (mp_cmp_z(n) == 0) { - mp_zero(rx); - mp_zero(ry); - res = MP_OKAY; - goto CLEANUP; - } - /* Q = P, k = n */ - MP_CHECKOK(mp_copy(px, &qx)); - MP_CHECKOK(mp_copy(py, &qy)); - MP_CHECKOK(mp_copy(n, &k)); - /* if n < 0 then Q = -Q, k = -k */ - if (mp_cmp_z(n) < 0) { - MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth)); - MP_CHECKOK(mp_neg(&k, &k)); - } -#ifdef ECL_DEBUG /* basic double and add method */ - l = mpl_significant_bits(&k) - 1; - MP_CHECKOK(mp_copy(&qx, &sx)); - MP_CHECKOK(mp_copy(&qy, &sy)); - for (i = l - 1; i >= 0; i--) { - /* S = 2S */ - MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); - /* if k_i = 1, then S = S + Q */ - if (mpl_get_bit(&k, i) != 0) { - MP_CHECKOK(group-> - point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); - } - } -#else /* double and add/subtract method from - * standard */ - /* k3 = 3 * k */ - MP_CHECKOK(mp_set_int(&k3, 3)); - MP_CHECKOK(mp_mul(&k, &k3, &k3)); - /* S = Q */ - MP_CHECKOK(mp_copy(&qx, &sx)); - MP_CHECKOK(mp_copy(&qy, &sy)); - /* l = index of high order bit in binary representation of 3*k */ - l = mpl_significant_bits(&k3) - 1; - /* for i = l-1 downto 1 */ - for (i = l - 1; i >= 1; i--) { - /* S = 2S */ - MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); - b3 = MP_GET_BIT(&k3, i); - b1 = MP_GET_BIT(&k, i); - /* if k3_i = 1 and k_i = 0, then S = S + Q */ - if ((b3 == 1) && (b1 == 0)) { - MP_CHECKOK(group-> - point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); - /* if k3_i = 0 and k_i = 1, then S = S - Q */ - } else if ((b3 == 0) && (b1 == 1)) { - MP_CHECKOK(group-> - point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group)); - } - } + /* if n = 0 then r = inf */ + if (mp_cmp_z(n) == 0) { + mp_zero(rx); + mp_zero(ry); + res = MP_OKAY; + goto CLEANUP; + } + /* Q = P, k = n */ + MP_CHECKOK(mp_copy(px, &qx)); + MP_CHECKOK(mp_copy(py, &qy)); + MP_CHECKOK(mp_copy(n, &k)); + /* if n < 0 then Q = -Q, k = -k */ + if (mp_cmp_z(n) < 0) { + MP_CHECKOK(group->meth->field_neg(&qy, &qy, group->meth)); + MP_CHECKOK(mp_neg(&k, &k)); + } +#ifdef ECL_DEBUG /* basic double and add method */ + l = mpl_significant_bits(&k) - 1; + MP_CHECKOK(mp_copy(&qx, &sx)); + MP_CHECKOK(mp_copy(&qy, &sy)); + for (i = l - 1; i >= 0; i--) { + /* S = 2S */ + MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); + /* if k_i = 1, then S = S + Q */ + if (mpl_get_bit(&k, i) != 0) { + MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); + } + } +#else /* double and add/subtract method from \ + * standard */ + /* k3 = 3 * k */ + MP_CHECKOK(mp_set_int(&k3, 3)); + MP_CHECKOK(mp_mul(&k, &k3, &k3)); + /* S = Q */ + MP_CHECKOK(mp_copy(&qx, &sx)); + MP_CHECKOK(mp_copy(&qy, &sy)); + /* l = index of high order bit in binary representation of 3*k */ + l = mpl_significant_bits(&k3) - 1; + /* for i = l-1 downto 1 */ + for (i = l - 1; i >= 1; i--) { + /* S = 2S */ + MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group)); + b3 = MP_GET_BIT(&k3, i); + b1 = MP_GET_BIT(&k, i); + /* if k3_i = 1 and k_i = 0, then S = S + Q */ + if ((b3 == 1) && (b1 == 0)) { + MP_CHECKOK(group->point_add(&sx, &sy, &qx, &qy, &sx, &sy, group)); + /* if k3_i = 0 and k_i = 1, then S = S - Q */ + } else if ((b3 == 0) && (b1 == 1)) { + MP_CHECKOK(group->point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group)); + } + } #endif - /* output S */ - MP_CHECKOK(mp_copy(&sx, rx)); - MP_CHECKOK(mp_copy(&sy, ry)); + /* output S */ + MP_CHECKOK(mp_copy(&sx, rx)); + MP_CHECKOK(mp_copy(&sy, ry)); - CLEANUP: - mp_clear(&k); - mp_clear(&k3); - mp_clear(&qx); - mp_clear(&qy); - mp_clear(&sx); - mp_clear(&sy); - return res; +CLEANUP: + mp_clear(&k); + mp_clear(&k3); + mp_clear(&qx); + mp_clear(&qy); + mp_clear(&sx); + mp_clear(&sy); + return res; } #endif /* Validates a point on a GFp curve. */ -mp_err +mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group) { - mp_err res = MP_NO; - mp_int accl, accr, tmp, pxt, pyt; + mp_err res = MP_NO; + mp_int accl, accr, tmp, pxt, pyt; - MP_DIGITS(&accl) = 0; - MP_DIGITS(&accr) = 0; - MP_DIGITS(&tmp) = 0; - MP_DIGITS(&pxt) = 0; - MP_DIGITS(&pyt) = 0; - MP_CHECKOK(mp_init(&accl)); - MP_CHECKOK(mp_init(&accr)); - MP_CHECKOK(mp_init(&tmp)); - MP_CHECKOK(mp_init(&pxt)); - MP_CHECKOK(mp_init(&pyt)); + MP_DIGITS(&accl) = 0; + MP_DIGITS(&accr) = 0; + MP_DIGITS(&tmp) = 0; + MP_DIGITS(&pxt) = 0; + MP_DIGITS(&pyt) = 0; + MP_CHECKOK(mp_init(&accl)); + MP_CHECKOK(mp_init(&accr)); + MP_CHECKOK(mp_init(&tmp)); + MP_CHECKOK(mp_init(&pxt)); + MP_CHECKOK(mp_init(&pyt)); /* 1: Verify that publicValue is not the point at infinity */ - if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) { - res = MP_NO; - goto CLEANUP; - } - /* 2: Verify that the coordinates of publicValue are elements + if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) { + res = MP_NO; + goto CLEANUP; + } + /* 2: Verify that the coordinates of publicValue are elements * of the field. */ - if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || - (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) { - res = MP_NO; - goto CLEANUP; - } + if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) || + (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) { + res = MP_NO; + goto CLEANUP; + } /* 3: Verify that publicValue is on the curve. */ - if (group->meth->field_enc) { - group->meth->field_enc(px, &pxt, group->meth); - group->meth->field_enc(py, &pyt, group->meth); - } else { - mp_copy(px, &pxt); - mp_copy(py, &pyt); - } - /* left-hand side: y^2 */ - MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) ); - /* right-hand side: x^3 + a*x + b = (x^2 + a)*x + b by Horner's rule */ - MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_add(&tmp, &group->curvea, &tmp, group->meth) ); - MP_CHECKOK( group->meth->field_mul(&tmp, &pxt, &accr, group->meth) ); - MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) ); - /* check LHS - RHS == 0 */ - MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) ); - if (mp_cmp_z(&accr) != 0) { - res = MP_NO; - goto CLEANUP; - } + if (group->meth->field_enc) { + group->meth->field_enc(px, &pxt, group->meth); + group->meth->field_enc(py, &pyt, group->meth); + } else { + MP_CHECKOK(mp_copy(px, &pxt)); + MP_CHECKOK(mp_copy(py, &pyt)); + } + /* left-hand side: y^2 */ + MP_CHECKOK(group->meth->field_sqr(&pyt, &accl, group->meth)); + /* right-hand side: x^3 + a*x + b = (x^2 + a)*x + b by Horner's rule */ + MP_CHECKOK(group->meth->field_sqr(&pxt, &tmp, group->meth)); + MP_CHECKOK(group->meth->field_add(&tmp, &group->curvea, &tmp, group->meth)); + MP_CHECKOK(group->meth->field_mul(&tmp, &pxt, &accr, group->meth)); + MP_CHECKOK(group->meth->field_add(&accr, &group->curveb, &accr, group->meth)); + /* check LHS - RHS == 0 */ + MP_CHECKOK(group->meth->field_sub(&accl, &accr, &accr, group->meth)); + if (mp_cmp_z(&accr) != 0) { + res = MP_NO; + goto CLEANUP; + } /* 4: Verify that the order of the curve times the publicValue * is the point at infinity. */ - MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) ); - if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { - res = MP_NO; - goto CLEANUP; - } + MP_CHECKOK(ECPoint_mul(group, &group->order, px, py, &pxt, &pyt)); + if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) { + res = MP_NO; + goto CLEANUP; + } - res = MP_YES; + res = MP_YES; CLEANUP: - mp_clear(&accl); - mp_clear(&accr); - mp_clear(&tmp); - mp_clear(&pxt); - mp_clear(&pyt); - return res; + mp_clear(&accl); + mp_clear(&accr); + mp_clear(&tmp); + mp_clear(&pxt); + mp_clear(&pyt); + return res; } diff --git a/nss/lib/freebl/ecl/ecp_fp.c b/nss/lib/freebl/ecl/ecp_fp.c deleted file mode 100644 index 46dc123..0000000 --- a/nss/lib/freebl/ecl/ecp_fp.c +++ /dev/null @@ -1,531 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp_fp.h" -#include "ecl-priv.h" -#include <stdlib.h> - -/* Performs tidying on a short multi-precision floating point integer (the - * lower group->numDoubles floats). */ -void -ecfp_tidyShort(double *t, const EC_group_fp * group) -{ - group->ecfp_tidy(t, group->alpha, group); -} - -/* Performs tidying on only the upper float digits of a multi-precision - * floating point integer, i.e. the digits beyond the regular length which - * are removed in the reduction step. */ -void -ecfp_tidyUpper(double *t, const EC_group_fp * group) -{ - group->ecfp_tidy(t + group->numDoubles, - group->alpha + group->numDoubles, group); -} - -/* Performs a "tidy" operation, which performs carrying, moving excess - * bits from one double to the next double, so that the precision of the - * doubles is reduced to the regular precision group->doubleBitSize. This - * might result in some float digits being negative. Alternative C version - * for portability. */ -void -ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group) -{ - double q; - int i; - - /* Do carrying */ - for (i = 0; i < group->numDoubles - 1; i++) { - q = t[i] + alpha[i + 1]; - q -= alpha[i + 1]; - t[i] -= q; - t[i + 1] += q; - - /* If we don't assume that truncation rounding is used, then q - * might be 2^n bigger than expected (if it rounds up), then t[0] - * could be negative and t[1] 2^n larger than expected. */ - } -} - -/* Performs a more mathematically precise "tidying" so that each term is - * positive. This is slower than the regular tidying, and is used for - * conversion from floating point to integer. */ -void -ecfp_positiveTidy(double *t, const EC_group_fp * group) -{ - double q; - int i; - - /* Do carrying */ - for (i = 0; i < group->numDoubles - 1; i++) { - /* Subtract beta to force rounding down */ - q = t[i] - ecfp_beta[i + 1]; - q += group->alpha[i + 1]; - q -= group->alpha[i + 1]; - t[i] -= q; - t[i + 1] += q; - - /* Due to subtracting ecfp_beta, we should have each term a - * non-negative int */ - ECFP_ASSERT(t[i] / ecfp_exp[i] == - (unsigned long long) (t[i] / ecfp_exp[i])); - ECFP_ASSERT(t[i] >= 0); - } -} - -/* Converts from a floating point representation into an mp_int. Expects - * that d is already reduced. */ -void -ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup) -{ - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - unsigned short i16[(group->primeBitSize + 15) / 16]; - double q = 1; - -#ifdef ECL_THIRTY_TWO_BIT - /* TEST uint32_t z = 0; */ - unsigned int z = 0; -#else - uint64_t z = 0; -#endif - int zBits = 0; - int copiedBits = 0; - int i = 0; - int j = 0; - - mp_digit *out; - - /* Result should always be >= 0, so set sign accordingly */ - MP_SIGN(mpout) = MP_ZPOS; - - /* Tidy up so we're just dealing with positive numbers */ - ecfp_positiveTidy(d, group); - - /* We might need to do this reduction step more than once if the - * reduction adds smaller terms which carry-over to cause another - * reduction. However, this should happen very rarely, if ever, - * depending on the elliptic curve. */ - do { - /* Init loop data */ - z = 0; - zBits = 0; - q = 1; - i = 0; - j = 0; - copiedBits = 0; - - /* Might have to do a bit more reduction */ - group->ecfp_singleReduce(d, group); - - /* Grow the size of the mpint if it's too small */ - s_mp_grow(mpout, group->numInts); - MP_USED(mpout) = group->numInts; - out = MP_DIGITS(mpout); - - /* Convert double to 16 bit integers */ - while (copiedBits < group->primeBitSize) { - if (zBits < 16) { - z += d[i] * q; - i++; - ECFP_ASSERT(i < (group->primeBitSize + 15) / 16); - zBits += group->doubleBitSize; - } - i16[j] = z; - j++; - z >>= 16; - zBits -= 16; - q *= ecfp_twom16; - copiedBits += 16; - } - } while (z != 0); - - /* Convert 16 bit integers to mp_digit */ -#ifdef ECL_THIRTY_TWO_BIT - for (i = 0; i < (group->primeBitSize + 15) / 16; i += 2) { - *out = 0; - if (i + 1 < (group->primeBitSize + 15) / 16) { - *out = i16[i + 1]; - *out <<= 16; - } - *out++ += i16[i]; - } -#else /* 64 bit */ - for (i = 0; i < (group->primeBitSize + 15) / 16; i += 4) { - *out = 0; - if (i + 3 < (group->primeBitSize + 15) / 16) { - *out = i16[i + 3]; - *out <<= 16; - } - if (i + 2 < (group->primeBitSize + 15) / 16) { - *out += i16[i + 2]; - *out <<= 16; - } - if (i + 1 < (group->primeBitSize + 15) / 16) { - *out += i16[i + 1]; - *out <<= 16; - } - *out++ += i16[i]; - } -#endif - - /* Perform final reduction. mpout should already be the same number - * of bits as p, but might not be less than p. Make it so. Since - * mpout has the same number of bits as p, and 2p has a larger bit - * size, then mpout < 2p, so a single subtraction of p will suffice. */ - if (mp_cmp(mpout, &ecgroup->meth->irr) >= 0) { - mp_sub(mpout, &ecgroup->meth->irr, mpout); - } - - /* Shrink the size of the mp_int to the actual used size (required for - * mp_cmp_z == 0) */ - out = MP_DIGITS(mpout); - for (i = group->numInts - 1; i > 0; i--) { - if (out[i] != 0) - break; - } - MP_USED(mpout) = i + 1; - - /* Should be between 0 and p-1 */ - ECFP_ASSERT(mp_cmp(mpout, &ecgroup->meth->irr) < 0); - ECFP_ASSERT(mp_cmp_z(mpout) >= 0); -} - -/* Converts from an mpint into a floating point representation. */ -void -ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup) -{ - int i; - int j = 0; - int size; - double shift = 1; - mp_digit *in; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - -#ifdef ECL_DEBUG - /* if debug mode, convert result back using ecfp_fp2i into cmp, then - * compare to x. */ - mp_int cmp; - - MP_DIGITS(&cmp) = NULL; - mp_init(&cmp); -#endif - - ECFP_ASSERT(group != NULL); - - /* init output to 0 (since we skip over some terms) */ - for (i = 0; i < group->numDoubles; i++) - out[i] = 0; - i = 0; - - size = MP_USED(x); - in = MP_DIGITS(x); - - /* Copy from int into doubles */ -#ifdef ECL_THIRTY_TWO_BIT - while (j < size) { - while (group->doubleBitSize * (i + 1) <= 32 * j) { - i++; - } - ECFP_ASSERT(group->doubleBitSize * i <= 32 * j); - out[i] = in[j]; - out[i] *= shift; - shift *= ecfp_two32; - j++; - } -#else - while (j < size) { - while (group->doubleBitSize * (i + 1) <= 64 * j) { - i++; - } - ECFP_ASSERT(group->doubleBitSize * i <= 64 * j); - out[i] = (in[j] & 0x00000000FFFFFFFF) * shift; - - while (group->doubleBitSize * (i + 1) <= 64 * j + 32) { - i++; - } - ECFP_ASSERT(24 * i <= 64 * j + 32); - out[i] = (in[j] & 0xFFFFFFFF00000000) * shift; - - shift *= ecfp_two64; - j++; - } -#endif - /* Realign bits to match double boundaries */ - ecfp_tidyShort(out, group); - -#ifdef ECL_DEBUG - /* Convert result back to mp_int, compare to original */ - ecfp_fp2i(&cmp, out, ecgroup); - ECFP_ASSERT(mp_cmp(&cmp, x) == 0); - mp_clear(&cmp); -#endif -} - -/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters - * a, b and p are the elliptic curve coefficients and the prime that - * determines the field GFp. Elliptic curve points P and R can be - * identical. Uses Jacobian coordinates. Uses 4-bit window method. */ -mp_err -ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *ecgroup) -{ - mp_err res = MP_OKAY; - ecfp_jac_pt precomp[16], r; - ecfp_aff_pt p; - EC_group_fp *group; - - mp_int rz; - int i, ni, d; - - ARGCHK(ecgroup != NULL, MP_BADARG); - ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); - - group = (EC_group_fp *) ecgroup->extra1; - MP_DIGITS(&rz) = 0; - MP_CHECKOK(mp_init(&rz)); - - /* init p, da */ - ecfp_i2fp(p.x, px, ecgroup); - ecfp_i2fp(p.y, py, ecgroup); - ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); - - /* Do precomputation */ - group->precompute_jac(precomp, &p, group); - - /* Do main body of calculations */ - d = (mpl_significant_bits(n) + 3) / 4; - - /* R = inf */ - for (i = 0; i < group->numDoubles; i++) { - r.z[i] = 0; - } - - for (i = d - 1; i >= 0; i--) { - /* compute window ni */ - ni = MP_GET_BIT(n, 4 * i + 3); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i + 2); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i + 1); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i); - - /* R = 2^4 * R */ - group->pt_dbl_jac(&r, &r, group); - group->pt_dbl_jac(&r, &r, group); - group->pt_dbl_jac(&r, &r, group); - group->pt_dbl_jac(&r, &r, group); - - /* R = R + (ni * P) */ - group->pt_add_jac(&r, &precomp[ni], &r, group); - } - - /* Convert back to integer */ - ecfp_fp2i(rx, r.x, ecgroup); - ecfp_fp2i(ry, r.y, ecgroup); - ecfp_fp2i(&rz, r.z, ecgroup); - - /* convert result S to affine coordinates */ - MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, ecgroup)); - - CLEANUP: - mp_clear(&rz); - return res; -} - -/* Uses mixed Jacobian-affine coordinates to perform a point - * multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine - * coordinates (Jacobian coordinates for doubles and affine coordinates - * for additions; based on recommendation from Brown et al.). Not very - * time efficient but quite space efficient, no precomputation needed. - * group contains the elliptic curve coefficients and the prime that - * determines the field GFp. Elliptic curve points P and R can be - * identical. Performs calculations in floating point number format, since - * this is faster than the integer operations on the ULTRASPARC III. - * Uses left-to-right binary method (double & add) (algorithm 9) for - * scalar-point multiplication from Brown, Hankerson, Lopez, Menezes. - * Software Implementation of the NIST Elliptic Curves Over Prime Fields. */ -mp_err -ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *ecgroup) -{ - mp_err res; - mp_int sx, sy, sz; - - ecfp_aff_pt p; - ecfp_jac_pt r; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - int i, l; - - MP_DIGITS(&sx) = 0; - MP_DIGITS(&sy) = 0; - MP_DIGITS(&sz) = 0; - MP_CHECKOK(mp_init(&sx)); - MP_CHECKOK(mp_init(&sy)); - MP_CHECKOK(mp_init(&sz)); - - /* if n = 0 then r = inf */ - if (mp_cmp_z(n) == 0) { - mp_zero(rx); - mp_zero(ry); - res = MP_OKAY; - goto CLEANUP; - /* if n < 0 then out of range error */ - } else if (mp_cmp_z(n) < 0) { - res = MP_RANGE; - goto CLEANUP; - } - - /* Convert from integer to floating point */ - ecfp_i2fp(p.x, px, ecgroup); - ecfp_i2fp(p.y, py, ecgroup); - ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); - - /* Init r to point at infinity */ - for (i = 0; i < group->numDoubles; i++) { - r.z[i] = 0; - } - - /* double and add method */ - l = mpl_significant_bits(n) - 1; - - for (i = l; i >= 0; i--) { - /* R = 2R */ - group->pt_dbl_jac(&r, &r, group); - - /* if n_i = 1, then R = R + Q */ - if (MP_GET_BIT(n, i) != 0) { - group->pt_add_jac_aff(&r, &p, &r, group); - } - } - - /* Convert from floating point to integer */ - ecfp_fp2i(&sx, r.x, ecgroup); - ecfp_fp2i(&sy, r.y, ecgroup); - ecfp_fp2i(&sz, r.z, ecgroup); - - /* convert result R to affine coordinates */ - MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup)); - - CLEANUP: - mp_clear(&sx); - mp_clear(&sy); - mp_clear(&sz); - return res; -} - -/* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic - * curve points P and R can be identical. Uses mixed Modified-Jacobian - * co-ordinates for doubling and Chudnovsky Jacobian coordinates for - * additions. Uses 5-bit window NAF method (algorithm 11) for scalar-point - * multiplication from Brown, Hankerson, Lopez, Menezes. Software - * Implementation of the NIST Elliptic Curves Over Prime Fields. */ -mp_err -ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *ecgroup) -{ - mp_err res = MP_OKAY; - mp_int sx, sy, sz; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - ecfp_chud_pt precomp[16]; - - ecfp_aff_pt p; - ecfp_jm_pt r; - - signed char naf[group->orderBitSize + 1]; - int i; - - MP_DIGITS(&sx) = 0; - MP_DIGITS(&sy) = 0; - MP_DIGITS(&sz) = 0; - MP_CHECKOK(mp_init(&sx)); - MP_CHECKOK(mp_init(&sy)); - MP_CHECKOK(mp_init(&sz)); - - /* if n = 0 then r = inf */ - if (mp_cmp_z(n) == 0) { - mp_zero(rx); - mp_zero(ry); - res = MP_OKAY; - goto CLEANUP; - /* if n < 0 then out of range error */ - } else if (mp_cmp_z(n) < 0) { - res = MP_RANGE; - goto CLEANUP; - } - - /* Convert from integer to floating point */ - ecfp_i2fp(p.x, px, ecgroup); - ecfp_i2fp(p.y, py, ecgroup); - ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); - - /* Perform precomputation */ - group->precompute_chud(precomp, &p, group); - - /* Compute 5NAF */ - ec_compute_wNAF(naf, group->orderBitSize, n, 5); - - /* Init R = pt at infinity */ - for (i = 0; i < group->numDoubles; i++) { - r.z[i] = 0; - } - - /* wNAF method */ - for (i = group->orderBitSize; i >= 0; i--) { - /* R = 2R */ - group->pt_dbl_jm(&r, &r, group); - - if (naf[i] != 0) { - group->pt_add_jm_chud(&r, &precomp[(naf[i] + 15) / 2], &r, - group); - } - } - - /* Convert from floating point to integer */ - ecfp_fp2i(&sx, r.x, ecgroup); - ecfp_fp2i(&sy, r.y, ecgroup); - ecfp_fp2i(&sz, r.z, ecgroup); - - /* convert result R to affine coordinates */ - MP_CHECKOK(ec_GFp_pt_jac2aff(&sx, &sy, &sz, rx, ry, ecgroup)); - - CLEANUP: - mp_clear(&sx); - mp_clear(&sy); - mp_clear(&sz); - return res; -} - -/* Cleans up extra memory allocated in ECGroup for this implementation. */ -void -ec_GFp_extra_free_fp(ECGroup *group) -{ - if (group->extra1 != NULL) { - free(group->extra1); - group->extra1 = NULL; - } -} - -/* Tests what precision floating point arithmetic is set to. This should - * be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa - * (extended precision on x86) and sets it into the EC_group_fp. Returns - * either 53 or 64 accordingly. */ -int -ec_set_fp_precision(EC_group_fp * group) -{ - double a = 9007199254740992.0; /* 2^53 */ - double b = a + 1; - - if (a == b) { - group->fpPrecision = 53; - group->alpha = ecfp_alpha_53; - return 53; - } - group->fpPrecision = 64; - group->alpha = ecfp_alpha_64; - return 64; -} diff --git a/nss/lib/freebl/ecl/ecp_fp.h b/nss/lib/freebl/ecl/ecp_fp.h deleted file mode 100644 index a5a6769..0000000 --- a/nss/lib/freebl/ecl/ecp_fp.h +++ /dev/null @@ -1,372 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef __ecp_fp_h_ -#define __ecp_fp_h_ - -#include "mpi.h" -#include "ecl.h" -#include "ecp.h" - -#include <sys/types.h> -#include "mpi-priv.h" - -#ifdef ECL_DEBUG -#include <assert.h> -#endif - -/* Largest number of doubles to store one reduced number in floating - * point. Used for memory allocation on the stack. */ -#define ECFP_MAXDOUBLES 10 - -/* For debugging purposes */ -#ifndef ECL_DEBUG -#define ECFP_ASSERT(x) -#else -#define ECFP_ASSERT(x) assert(x) -#endif - -/* ECFP_Ti = 2^(i*24) Define as preprocessor constants so we can use in - * multiple static constants */ -#define ECFP_T0 1.0 -#define ECFP_T1 16777216.0 -#define ECFP_T2 281474976710656.0 -#define ECFP_T3 4722366482869645213696.0 -#define ECFP_T4 79228162514264337593543950336.0 -#define ECFP_T5 1329227995784915872903807060280344576.0 -#define ECFP_T6 22300745198530623141535718272648361505980416.0 -#define ECFP_T7 374144419156711147060143317175368453031918731001856.0 -#define ECFP_T8 6277101735386680763835789423207666416102355444464034512896.0 -#define ECFP_T9 105312291668557186697918027683670432318895095400549111254310977536.0 -#define ECFP_T10 1766847064778384329583297500742918515827483896875618958121606201292619776.0 -#define ECFP_T11 29642774844752946028434172162224104410437116074403984394101141506025761187823616.0 -#define ECFP_T12 497323236409786642155382248146820840100456150797347717440463976893159497012533375533056.0 -#define ECFP_T13 8343699359066055009355553539724812947666814540455674882605631280555545803830627148527195652096.0 -#define ECFP_T14 139984046386112763159840142535527767382602843577165595931249318810236991948760059086304843329475444736.0 -#define ECFP_T15 2348542582773833227889480596789337027375682548908319870707290971532209025114608443463698998384768703031934976.0 -#define ECFP_T16 39402006196394479212279040100143613805079739270465446667948293404245\ -721771497210611414266254884915640806627990306816.0 -#define ECFP_T17 66105596879024859895191530803277103982840468296428121928464879527440\ -5791236311345825189210439715284847591212025023358304256.0 -#define ECFP_T18 11090678776483259438313656736572334813745748301503266300681918322458\ -485231222502492159897624416558312389564843845614287315896631296.0 -#define ECFP_T19 18607071341967536398062689481932916079453218833595342343206149099024\ -36577570298683715049089827234727835552055312041415509848580169253519\ -36.0 - -#define ECFP_TWO160 1461501637330902918203684832716283019655932542976.0 -#define ECFP_TWO192 6277101735386680763835789423207666416102355444464034512896.0 -#define ECFP_TWO224 26959946667150639794667015087019630673637144422540572481103610249216.0 - -/* Multiplicative constants */ -static const double ecfp_two32 = 4294967296.0; -static const double ecfp_two64 = 18446744073709551616.0; -static const double ecfp_twom16 = .0000152587890625; -static const double ecfp_twom128 = - .00000000000000000000000000000000000000293873587705571876992184134305561419454666389193021880377187926569604314863681793212890625; -static const double ecfp_twom129 = - .000000000000000000000000000000000000001469367938527859384960920671527807097273331945965109401885939632848021574318408966064453125; -static const double ecfp_twom160 = - .0000000000000000000000000000000000000000000000006842277657836020854119773355907793609766904013068924666782559979930620520927053718196475529111921787261962890625; -static const double ecfp_twom192 = - .000000000000000000000000000000000000000000000000000000000159309191113245227702888039776771180559110455519261878607388585338616290151305816094308987472018268594098344692611135542392730712890625; -static const double ecfp_twom224 = - .00000000000000000000000000000000000000000000000000000000000000000003709206150687421385731735261547639513367564778757791002453039058917581340095629358997312082723208437536338919136001159027049567384892725385725498199462890625; - -/* ecfp_exp[i] = 2^(i*ECFP_DSIZE) */ -static const double ecfp_exp[2 * ECFP_MAXDOUBLES] = { - ECFP_T0, ECFP_T1, ECFP_T2, ECFP_T3, ECFP_T4, ECFP_T5, - ECFP_T6, ECFP_T7, ECFP_T8, ECFP_T9, ECFP_T10, ECFP_T11, - ECFP_T12, ECFP_T13, ECFP_T14, ECFP_T15, ECFP_T16, ECFP_T17, ECFP_T18, - ECFP_T19 -}; - -/* 1.1 * 2^52 Uses 2^52 to truncate, the .1 is an extra 2^51 to protect - * the 2^52 bit, so that adding alphas to a negative number won't borrow - * and empty the important 2^52 bit */ -#define ECFP_ALPHABASE_53 6755399441055744.0 -/* Special case: On some platforms, notably x86 Linux, there is an - * extended-precision floating point representation with 64-bits of - * precision in the mantissa. These extra bits of precision require a - * larger value of alpha to truncate, i.e. 1.1 * 2^63. */ -#define ECFP_ALPHABASE_64 13835058055282163712.0 - -/* - * ecfp_alpha[i] = 1.5 * 2^(52 + i*ECFP_DSIZE) we add and subtract alpha - * to truncate floating point numbers to a certain number of bits for - * tidying */ -static const double ecfp_alpha_53[2 * ECFP_MAXDOUBLES] = { - ECFP_ALPHABASE_53 * ECFP_T0, - ECFP_ALPHABASE_53 * ECFP_T1, - ECFP_ALPHABASE_53 * ECFP_T2, - ECFP_ALPHABASE_53 * ECFP_T3, - ECFP_ALPHABASE_53 * ECFP_T4, - ECFP_ALPHABASE_53 * ECFP_T5, - ECFP_ALPHABASE_53 * ECFP_T6, - ECFP_ALPHABASE_53 * ECFP_T7, - ECFP_ALPHABASE_53 * ECFP_T8, - ECFP_ALPHABASE_53 * ECFP_T9, - ECFP_ALPHABASE_53 * ECFP_T10, - ECFP_ALPHABASE_53 * ECFP_T11, - ECFP_ALPHABASE_53 * ECFP_T12, - ECFP_ALPHABASE_53 * ECFP_T13, - ECFP_ALPHABASE_53 * ECFP_T14, - ECFP_ALPHABASE_53 * ECFP_T15, - ECFP_ALPHABASE_53 * ECFP_T16, - ECFP_ALPHABASE_53 * ECFP_T17, - ECFP_ALPHABASE_53 * ECFP_T18, - ECFP_ALPHABASE_53 * ECFP_T19 -}; - -/* - * ecfp_alpha[i] = 1.5 * 2^(63 + i*ECFP_DSIZE) we add and subtract alpha - * to truncate floating point numbers to a certain number of bits for - * tidying */ -static const double ecfp_alpha_64[2 * ECFP_MAXDOUBLES] = { - ECFP_ALPHABASE_64 * ECFP_T0, - ECFP_ALPHABASE_64 * ECFP_T1, - ECFP_ALPHABASE_64 * ECFP_T2, - ECFP_ALPHABASE_64 * ECFP_T3, - ECFP_ALPHABASE_64 * ECFP_T4, - ECFP_ALPHABASE_64 * ECFP_T5, - ECFP_ALPHABASE_64 * ECFP_T6, - ECFP_ALPHABASE_64 * ECFP_T7, - ECFP_ALPHABASE_64 * ECFP_T8, - ECFP_ALPHABASE_64 * ECFP_T9, - ECFP_ALPHABASE_64 * ECFP_T10, - ECFP_ALPHABASE_64 * ECFP_T11, - ECFP_ALPHABASE_64 * ECFP_T12, - ECFP_ALPHABASE_64 * ECFP_T13, - ECFP_ALPHABASE_64 * ECFP_T14, - ECFP_ALPHABASE_64 * ECFP_T15, - ECFP_ALPHABASE_64 * ECFP_T16, - ECFP_ALPHABASE_64 * ECFP_T17, - ECFP_ALPHABASE_64 * ECFP_T18, - ECFP_ALPHABASE_64 * ECFP_T19 -}; - -/* 0.011111111111111111111111 (binary) = 0.5 - 2^25 (24 ones) */ -#define ECFP_BETABASE 0.4999999701976776123046875 - -/* - * We subtract beta prior to using alpha to simulate rounding down. We - * make this close to 0.5 to round almost everything down, but exactly 0.5 - * would cause some incorrect rounding. */ -static const double ecfp_beta[2 * ECFP_MAXDOUBLES] = { - ECFP_BETABASE * ECFP_T0, - ECFP_BETABASE * ECFP_T1, - ECFP_BETABASE * ECFP_T2, - ECFP_BETABASE * ECFP_T3, - ECFP_BETABASE * ECFP_T4, - ECFP_BETABASE * ECFP_T5, - ECFP_BETABASE * ECFP_T6, - ECFP_BETABASE * ECFP_T7, - ECFP_BETABASE * ECFP_T8, - ECFP_BETABASE * ECFP_T9, - ECFP_BETABASE * ECFP_T10, - ECFP_BETABASE * ECFP_T11, - ECFP_BETABASE * ECFP_T12, - ECFP_BETABASE * ECFP_T13, - ECFP_BETABASE * ECFP_T14, - ECFP_BETABASE * ECFP_T15, - ECFP_BETABASE * ECFP_T16, - ECFP_BETABASE * ECFP_T17, - ECFP_BETABASE * ECFP_T18, - ECFP_BETABASE * ECFP_T19 -}; - -static const double ecfp_beta_160 = ECFP_BETABASE * ECFP_TWO160; -static const double ecfp_beta_192 = ECFP_BETABASE * ECFP_TWO192; -static const double ecfp_beta_224 = ECFP_BETABASE * ECFP_TWO224; - -/* Affine EC Point. This is the basic representation (x, y) of an elliptic - * curve point. */ -typedef struct { - double x[ECFP_MAXDOUBLES]; - double y[ECFP_MAXDOUBLES]; -} ecfp_aff_pt; - -/* Jacobian EC Point. This coordinate system uses X = x/z^2, Y = y/z^3, - * which enables calculations with fewer inversions than affine - * coordinates. */ -typedef struct { - double x[ECFP_MAXDOUBLES]; - double y[ECFP_MAXDOUBLES]; - double z[ECFP_MAXDOUBLES]; -} ecfp_jac_pt; - -/* Chudnovsky Jacobian EC Point. This coordinate system is the same as - * Jacobian, except it keeps z^2, z^3 for faster additions. */ -typedef struct { - double x[ECFP_MAXDOUBLES]; - double y[ECFP_MAXDOUBLES]; - double z[ECFP_MAXDOUBLES]; - double z2[ECFP_MAXDOUBLES]; - double z3[ECFP_MAXDOUBLES]; -} ecfp_chud_pt; - -/* Modified Jacobian EC Point. This coordinate system is the same as - * Jacobian, except it keeps a*z^4 for faster doublings. */ -typedef struct { - double x[ECFP_MAXDOUBLES]; - double y[ECFP_MAXDOUBLES]; - double z[ECFP_MAXDOUBLES]; - double az4[ECFP_MAXDOUBLES]; -} ecfp_jm_pt; - -struct EC_group_fp_str; - -typedef struct EC_group_fp_str EC_group_fp; -struct EC_group_fp_str { - int fpPrecision; /* Set to number of bits in mantissa, 53 - * or 64 */ - int numDoubles; - int primeBitSize; - int orderBitSize; - int doubleBitSize; - int numInts; - int aIsM3; /* True if curvea == -3 (mod p), then we - * can optimize doubling */ - double curvea[ECFP_MAXDOUBLES]; - /* Used to truncate a double to the number of bits in the curve */ - double bitSize_alpha; - /* Pointer to either ecfp_alpha_53 or ecfp_alpha_64 */ - const double *alpha; - - void (*ecfp_singleReduce) (double *r, const EC_group_fp * group); - void (*ecfp_reduce) (double *r, double *x, const EC_group_fp * group); - /* Performs a "tidy" operation, which performs carrying, moving excess - * bits from one double to the next double, so that the precision of - * the doubles is reduced to the regular precision ECFP_DSIZE. This - * might result in some float digits being negative. */ - void (*ecfp_tidy) (double *t, const double *alpha, - const EC_group_fp * group); - /* Perform a point addition using coordinate system Jacobian + Affine - * -> Jacobian. Input and output should be multi-precision floating - * point integers. */ - void (*pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q, - ecfp_jac_pt * r, const EC_group_fp * group); - /* Perform a point doubling in Jacobian coordinates. Input and output - * should be multi-precision floating point integers. */ - void (*pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr, - const EC_group_fp * group); - /* Perform a point addition using Jacobian coordinate system. Input - * and output should be multi-precision floating point integers. */ - void (*pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q, - ecfp_jac_pt * r, const EC_group_fp * group); - /* Perform a point doubling in Modified Jacobian coordinates. Input - * and output should be multi-precision floating point integers. */ - void (*pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r, - const EC_group_fp * group); - /* Perform a point doubling using coordinates Affine -> Chudnovsky - * Jacobian. Input and output should be multi-precision floating point - * integers. */ - void (*pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r, - const EC_group_fp * group); - /* Perform a point addition using coordinates: Modified Jacobian + - * Chudnovsky Jacobian -> Modified Jacobian. Input and output should - * be multi-precision floating point integers. */ - void (*pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q, - ecfp_jm_pt * r, const EC_group_fp * group); - /* Perform a point addition using Chudnovsky Jacobian coordinates. - * Input and output should be multi-precision floating point integers. - */ - void (*pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q, - ecfp_chud_pt * r, const EC_group_fp * group); - /* Expects out to be an array of size 16 of Chudnovsky Jacobian - * points. Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for - * -15P, -13P, -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P, - * 13P, 15P */ - void (*precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p, - const EC_group_fp * group); - /* Expects out to be an array of size 16 of Jacobian points. Fills in - * Chudnovsky Jacobian form (x, y, z), for O, P, 2P, ... 15P */ - void (*precompute_jac) (ecfp_jac_pt * out, const ecfp_aff_pt * p, - const EC_group_fp * group); - -}; - -/* Computes r = x*y. - * r must be different (point to different memory) than x and y. - * Does not tidy or reduce. */ -void ecfp_multiply(double *r, const double *x, const double *y); - -/* Performs a "tidy" operation, which performs carrying, moving excess - * bits from one double to the next double, so that the precision of the - * doubles is reduced to the regular precision group->doubleBitSize. This - * might result in some float digits being negative. */ -void ecfp_tidy(double *t, const double *alpha, const EC_group_fp * group); - -/* Performs tidying on only the upper float digits of a multi-precision - * floating point integer, i.e. the digits beyond the regular length which - * are removed in the reduction step. */ -void ecfp_tidyUpper(double *t, const EC_group_fp * group); - -/* Performs tidying on a short multi-precision floating point integer (the - * lower group->numDoubles floats). */ -void ecfp_tidyShort(double *t, const EC_group_fp * group); - -/* Performs a more mathematically precise "tidying" so that each term is - * positive. This is slower than the regular tidying, and is used for - * conversion from floating point to integer. */ -void ecfp_positiveTidy(double *t, const EC_group_fp * group); - -/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters - * a, b and p are the elliptic curve coefficients and the prime that - * determines the field GFp. Elliptic curve points P and R can be - * identical. Uses mixed Jacobian-affine coordinates. Uses 4-bit window - * method. */ -mp_err - ec_GFp_point_mul_jac_4w_fp(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *ecgroup); - -/* Computes R = nP where R is (rx, ry) and P is the base point. The - * parameters a, b and p are the elliptic curve coefficients and the prime - * that determines the field GFp. Elliptic curve points P and R can be - * identical. Uses mixed Jacobian-affine coordinates (Jacobian - * coordinates for doubles and affine coordinates for additions; based on - * recommendation from Brown et al.). Uses window NAF method (algorithm - * 11) for scalar-point multiplication from Brown, Hankerson, Lopez, - * Menezes. Software Implementation of the NIST Elliptic Curves Over Prime - * Fields. */ -mp_err ec_GFp_point_mul_wNAF_fp(const mp_int *n, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *ecgroup); - -/* Uses mixed Jacobian-affine coordinates to perform a point - * multiplication: R = n * P, n scalar. Uses mixed Jacobian-affine - * coordinates (Jacobian coordinates for doubles and affine coordinates - * for additions; based on recommendation from Brown et al.). Not very - * time efficient but quite space efficient, no precomputation needed. - * group contains the elliptic curve coefficients and the prime that - * determines the field GFp. Elliptic curve points P and R can be - * identical. Performs calculations in floating point number format, since - * this is faster than the integer operations on the ULTRASPARC III. - * Uses left-to-right binary method (double & add) (algorithm 9) for - * scalar-point multiplication from Brown, Hankerson, Lopez, Menezes. - * Software Implementation of the NIST Elliptic Curves Over Prime Fields. */ -mp_err - ec_GFp_pt_mul_jac_fp(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *ecgroup); - -/* Cleans up extra memory allocated in ECGroup for this implementation. */ -void ec_GFp_extra_free_fp(ECGroup *group); - -/* Converts from a floating point representation into an mp_int. Expects - * that d is already reduced. */ -void - ecfp_fp2i(mp_int *mpout, double *d, const ECGroup *ecgroup); - -/* Converts from an mpint into a floating point representation. */ -void - ecfp_i2fp(double *out, const mp_int *x, const ECGroup *ecgroup); - -/* Tests what precision floating point arithmetic is set to. This should - * be either a 53-bit mantissa (IEEE standard) or a 64-bit mantissa - * (extended precision on x86) and sets it into the EC_group_fp. Returns - * either 53 or 64 accordingly. */ -int ec_set_fp_precision(EC_group_fp * group); - -#endif diff --git a/nss/lib/freebl/ecl/ecp_fp160.c b/nss/lib/freebl/ecl/ecp_fp160.c deleted file mode 100644 index f462f3b..0000000 --- a/nss/lib/freebl/ecl/ecp_fp160.c +++ /dev/null @@ -1,145 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp_fp.h" -#include <stdlib.h> - -#define ECFP_BSIZE 160 -#define ECFP_NUMDOUBLES 7 - -#include "ecp_fpinc.c" - -/* Performs a single step of reduction, just on the uppermost float - * (assumes already tidied), and then retidies. Note, this does not - * guarantee that the result will be less than p, but truncates the number - * of bits. */ -void -ecfp160_singleReduce(double *d, const EC_group_fp * group) -{ - double q; - - ECFP_ASSERT(group->doubleBitSize == 24); - ECFP_ASSERT(group->primeBitSize == 160); - ECFP_ASSERT(ECFP_NUMDOUBLES == 7); - - q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_160; - q += group->bitSize_alpha; - q -= group->bitSize_alpha; - - d[ECFP_NUMDOUBLES - 1] -= q; - d[0] += q * ecfp_twom160; - d[1] += q * ecfp_twom129; - ecfp_positiveTidy(d, group); - - /* Assertions for the highest order term */ - ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] / ecfp_exp[ECFP_NUMDOUBLES - 1] == - (unsigned long long) (d[ECFP_NUMDOUBLES - 1] / - ecfp_exp[ECFP_NUMDOUBLES - 1])); - ECFP_ASSERT(d[ECFP_NUMDOUBLES - 1] >= 0); -} - -/* Performs imperfect reduction. This might leave some negative terms, - * and one more reduction might be required for the result to be between 0 - * and p-1. x should not already be reduced, i.e. should have - * 2*ECFP_NUMDOUBLES significant terms. x and r can be the same, but then - * the upper parts of r are not zeroed */ -void -ecfp160_reduce(double *r, double *x, const EC_group_fp * group) -{ - - double x7, x8, q; - - ECFP_ASSERT(group->doubleBitSize == 24); - ECFP_ASSERT(group->primeBitSize == 160); - ECFP_ASSERT(ECFP_NUMDOUBLES == 7); - - /* Tidy just the upper bits, the lower bits can wait. */ - ecfp_tidyUpper(x, group); - - /* Assume that this is already tidied so that we have enough extra - * bits */ - x7 = x[7] + x[13] * ecfp_twom129; /* adds bits 15-39 */ - - /* Tidy x7, or we won't have enough bits later to add it in */ - q = x7 + group->alpha[8]; - q -= group->alpha[8]; - x7 -= q; /* holds bits 0-24 */ - x8 = x[8] + q; /* holds bits 0-25 */ - - r[6] = x[6] + x[13] * ecfp_twom160 + x[12] * ecfp_twom129; /* adds - * bits - * 8-39 */ - r[5] = x[5] + x[12] * ecfp_twom160 + x[11] * ecfp_twom129; - r[4] = x[4] + x[11] * ecfp_twom160 + x[10] * ecfp_twom129; - r[3] = x[3] + x[10] * ecfp_twom160 + x[9] * ecfp_twom129; - r[2] = x[2] + x[9] * ecfp_twom160 + x8 * ecfp_twom129; /* adds bits - * 8-40 */ - r[1] = x[1] + x8 * ecfp_twom160 + x7 * ecfp_twom129; /* adds bits - * 8-39 */ - r[0] = x[0] + x7 * ecfp_twom160; - - /* Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions - * is accurate plus or minus one. (Rather than tidy all to make it - * totally accurate, which is more costly.) */ - q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1]; - q -= group->alpha[ECFP_NUMDOUBLES - 1]; - r[ECFP_NUMDOUBLES - 2] -= q; - r[ECFP_NUMDOUBLES - 1] += q; - - /* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */ - /* Use ecfp_beta so we get a positive result */ - q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_160; - q += group->bitSize_alpha; - q -= group->bitSize_alpha; - - r[ECFP_NUMDOUBLES - 1] -= q; - r[0] += q * ecfp_twom160; - r[1] += q * ecfp_twom129; - - /* Tidy the result */ - ecfp_tidyShort(r, group); -} - -/* Sets group to use optimized calculations in this file */ -mp_err -ec_group_set_secp160r1_fp(ECGroup *group) -{ - - EC_group_fp *fpg = NULL; - - /* Allocate memory for floating point group data */ - fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp)); - if (fpg == NULL) { - return MP_MEM; - } - - fpg->numDoubles = ECFP_NUMDOUBLES; - fpg->primeBitSize = ECFP_BSIZE; - fpg->orderBitSize = 161; - fpg->doubleBitSize = 24; - fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS; - fpg->aIsM3 = 1; - fpg->ecfp_singleReduce = &ecfp160_singleReduce; - fpg->ecfp_reduce = &ecfp160_reduce; - fpg->ecfp_tidy = &ecfp_tidy; - - fpg->pt_add_jac_aff = &ecfp160_pt_add_jac_aff; - fpg->pt_add_jac = &ecfp160_pt_add_jac; - fpg->pt_add_jm_chud = &ecfp160_pt_add_jm_chud; - fpg->pt_add_chud = &ecfp160_pt_add_chud; - fpg->pt_dbl_jac = &ecfp160_pt_dbl_jac; - fpg->pt_dbl_jm = &ecfp160_pt_dbl_jm; - fpg->pt_dbl_aff2chud = &ecfp160_pt_dbl_aff2chud; - fpg->precompute_chud = &ecfp160_precompute_chud; - fpg->precompute_jac = &ecfp160_precompute_jac; - - group->point_mul = &ec_GFp_point_mul_wNAF_fp; - group->points_mul = &ec_pts_mul_basic; - group->extra1 = fpg; - group->extra_free = &ec_GFp_extra_free_fp; - - ec_set_fp_precision(fpg); - fpg->bitSize_alpha = ECFP_TWO160 * fpg->alpha[0]; - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ecp_fp192.c b/nss/lib/freebl/ecl/ecp_fp192.c deleted file mode 100644 index a415bcd..0000000 --- a/nss/lib/freebl/ecl/ecp_fp192.c +++ /dev/null @@ -1,143 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp_fp.h" -#include <stdlib.h> - -#define ECFP_BSIZE 192 -#define ECFP_NUMDOUBLES 8 - -#include "ecp_fpinc.c" - -/* Performs a single step of reduction, just on the uppermost float - * (assumes already tidied), and then retidies. Note, this does not - * guarantee that the result will be less than p. */ -void -ecfp192_singleReduce(double *d, const EC_group_fp * group) -{ - double q; - - ECFP_ASSERT(group->doubleBitSize == 24); - ECFP_ASSERT(group->primeBitSize == 192); - ECFP_ASSERT(group->numDoubles == 8); - - q = d[ECFP_NUMDOUBLES - 1] - ecfp_beta_192; - q += group->bitSize_alpha; - q -= group->bitSize_alpha; - - d[ECFP_NUMDOUBLES - 1] -= q; - d[0] += q * ecfp_twom192; - d[2] += q * ecfp_twom128; - ecfp_positiveTidy(d, group); -} - -/* - * Performs imperfect reduction. This might leave some negative terms, - * and one more reduction might be required for the result to be between 0 - * and p-1. x should be be an array of at least 16, and r at least 8 x and - * r can be the same, but then the upper parts of r are not zeroed */ -void -ecfp_reduce_192(double *r, double *x, const EC_group_fp * group) -{ - double x8, x9, x10, q; - - ECFP_ASSERT(group->doubleBitSize == 24); - ECFP_ASSERT(group->primeBitSize == 192); - ECFP_ASSERT(group->numDoubles == 8); - - /* Tidy just the upper portion, the lower part can wait */ - ecfp_tidyUpper(x, group); - - x8 = x[8] + x[14] * ecfp_twom128; /* adds bits 16-40 */ - x9 = x[9] + x[15] * ecfp_twom128; /* adds bits 16-40 */ - - /* Tidy up, or we won't have enough bits later to add it in */ - - q = x8 + group->alpha[9]; - q -= group->alpha[9]; - x8 -= q; - x9 += q; - - q = x9 + group->alpha[10]; - q -= group->alpha[10]; - x9 -= q; - x10 = x[10] + q; - - r[7] = x[7] + x[15] * ecfp_twom192 + x[13] * ecfp_twom128; /* adds - * bits - * 0-40 */ - r[6] = x[6] + x[14] * ecfp_twom192 + x[12] * ecfp_twom128; - r[5] = x[5] + x[13] * ecfp_twom192 + x[11] * ecfp_twom128; - r[4] = x[4] + x[12] * ecfp_twom192 + x10 * ecfp_twom128; - r[3] = x[3] + x[11] * ecfp_twom192 + x9 * ecfp_twom128; /* adds bits - * 0-40 */ - r[2] = x[2] + x10 * ecfp_twom192 + x8 * ecfp_twom128; - r[1] = x[1] + x9 * ecfp_twom192; /* adds bits 16-40 */ - r[0] = x[0] + x8 * ecfp_twom192; - - /* - * Tidy up just r[group->numDoubles-2] so that the number of - * reductions is accurate plus or minus one. (Rather than tidy all to - * make it totally accurate) */ - q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1]; - q -= group->alpha[ECFP_NUMDOUBLES - 1]; - r[ECFP_NUMDOUBLES - 2] -= q; - r[ECFP_NUMDOUBLES - 1] += q; - - /* Tidy up the excess bits on r[group->numDoubles-1] using reduction */ - /* Use ecfp_beta so we get a positive res */ - q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_192; - q += group->bitSize_alpha; - q -= group->bitSize_alpha; - - r[ECFP_NUMDOUBLES - 1] -= q; - r[0] += q * ecfp_twom192; - r[2] += q * ecfp_twom128; - - /* Tidy the result */ - ecfp_tidyShort(r, group); -} - -/* Sets group to use optimized calculations in this file */ -mp_err -ec_group_set_nistp192_fp(ECGroup *group) -{ - EC_group_fp *fpg; - - /* Allocate memory for floating point group data */ - fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp)); - if (fpg == NULL) { - return MP_MEM; - } - - fpg->numDoubles = ECFP_NUMDOUBLES; - fpg->primeBitSize = ECFP_BSIZE; - fpg->orderBitSize = 192; - fpg->doubleBitSize = 24; - fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS; - fpg->aIsM3 = 1; - fpg->ecfp_singleReduce = &ecfp192_singleReduce; - fpg->ecfp_reduce = &ecfp_reduce_192; - fpg->ecfp_tidy = &ecfp_tidy; - - fpg->pt_add_jac_aff = &ecfp192_pt_add_jac_aff; - fpg->pt_add_jac = &ecfp192_pt_add_jac; - fpg->pt_add_jm_chud = &ecfp192_pt_add_jm_chud; - fpg->pt_add_chud = &ecfp192_pt_add_chud; - fpg->pt_dbl_jac = &ecfp192_pt_dbl_jac; - fpg->pt_dbl_jm = &ecfp192_pt_dbl_jm; - fpg->pt_dbl_aff2chud = &ecfp192_pt_dbl_aff2chud; - fpg->precompute_chud = &ecfp192_precompute_chud; - fpg->precompute_jac = &ecfp192_precompute_jac; - - group->point_mul = &ec_GFp_point_mul_wNAF_fp; - group->points_mul = &ec_pts_mul_basic; - group->extra1 = fpg; - group->extra_free = &ec_GFp_extra_free_fp; - - ec_set_fp_precision(fpg); - fpg->bitSize_alpha = ECFP_TWO192 * fpg->alpha[0]; - - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ecp_fp224.c b/nss/lib/freebl/ecl/ecp_fp224.c deleted file mode 100644 index 71b6a6d..0000000 --- a/nss/lib/freebl/ecl/ecp_fp224.c +++ /dev/null @@ -1,156 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp_fp.h" -#include <stdlib.h> - -#define ECFP_BSIZE 224 -#define ECFP_NUMDOUBLES 10 - -#include "ecp_fpinc.c" - -/* Performs a single step of reduction, just on the uppermost float - * (assumes already tidied), and then retidies. Note, this does not - * guarantee that the result will be less than p. */ -void -ecfp224_singleReduce(double *r, const EC_group_fp * group) -{ - double q; - - ECFP_ASSERT(group->doubleBitSize == 24); - ECFP_ASSERT(group->primeBitSize == 224); - ECFP_ASSERT(group->numDoubles == 10); - - q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224; - q += group->bitSize_alpha; - q -= group->bitSize_alpha; - - r[ECFP_NUMDOUBLES - 1] -= q; - r[0] -= q * ecfp_twom224; - r[4] += q * ecfp_twom128; - - ecfp_positiveTidy(r, group); -} - -/* - * Performs imperfect reduction. This might leave some negative terms, - * and one more reduction might be required for the result to be between 0 - * and p-1. x should be be an array of at least 20, and r at least 10 x - * and r can be the same, but then the upper parts of r are not zeroed */ -void -ecfp224_reduce(double *r, double *x, const EC_group_fp * group) -{ - - double x10, x11, x12, x13, x14, q; - - ECFP_ASSERT(group->doubleBitSize == 24); - ECFP_ASSERT(group->primeBitSize == 224); - ECFP_ASSERT(group->numDoubles == 10); - - /* Tidy just the upper bits of x. Don't need to tidy the lower ones - * yet. */ - ecfp_tidyUpper(x, group); - - x10 = x[10] + x[16] * ecfp_twom128; - x11 = x[11] + x[17] * ecfp_twom128; - x12 = x[12] + x[18] * ecfp_twom128; - x13 = x[13] + x[19] * ecfp_twom128; - - /* Tidy up, or we won't have enough bits later to add it in */ - q = x10 + group->alpha[11]; - q -= group->alpha[11]; - x10 -= q; - x11 = x11 + q; - - q = x11 + group->alpha[12]; - q -= group->alpha[12]; - x11 -= q; - x12 = x12 + q; - - q = x12 + group->alpha[13]; - q -= group->alpha[13]; - x12 -= q; - x13 = x13 + q; - - q = x13 + group->alpha[14]; - q -= group->alpha[14]; - x13 -= q; - x14 = x[14] + q; - - r[9] = x[9] + x[15] * ecfp_twom128 - x[19] * ecfp_twom224; - r[8] = x[8] + x14 * ecfp_twom128 - x[18] * ecfp_twom224; - r[7] = x[7] + x13 * ecfp_twom128 - x[17] * ecfp_twom224; - r[6] = x[6] + x12 * ecfp_twom128 - x[16] * ecfp_twom224; - r[5] = x[5] + x11 * ecfp_twom128 - x[15] * ecfp_twom224; - r[4] = x[4] + x10 * ecfp_twom128 - x14 * ecfp_twom224; - r[3] = x[3] - x13 * ecfp_twom224; - r[2] = x[2] - x12 * ecfp_twom224; - r[1] = x[1] - x11 * ecfp_twom224; - r[0] = x[0] - x10 * ecfp_twom224; - - /* - * Tidy up just r[ECFP_NUMDOUBLES-2] so that the number of reductions - * is accurate plus or minus one. (Rather than tidy all to make it - * totally accurate) */ - q = r[ECFP_NUMDOUBLES - 2] + group->alpha[ECFP_NUMDOUBLES - 1]; - q -= group->alpha[ECFP_NUMDOUBLES - 1]; - r[ECFP_NUMDOUBLES - 2] -= q; - r[ECFP_NUMDOUBLES - 1] += q; - - /* Tidy up the excess bits on r[ECFP_NUMDOUBLES-1] using reduction */ - /* Use ecfp_beta so we get a positive res */ - q = r[ECFP_NUMDOUBLES - 1] - ecfp_beta_224; - q += group->bitSize_alpha; - q -= group->bitSize_alpha; - - r[ECFP_NUMDOUBLES - 1] -= q; - r[0] -= q * ecfp_twom224; - r[4] += q * ecfp_twom128; - - ecfp_tidyShort(r, group); -} - -/* Sets group to use optimized calculations in this file */ -mp_err -ec_group_set_nistp224_fp(ECGroup *group) -{ - - EC_group_fp *fpg; - - /* Allocate memory for floating point group data */ - fpg = (EC_group_fp *) malloc(sizeof(EC_group_fp)); - if (fpg == NULL) { - return MP_MEM; - } - - fpg->numDoubles = ECFP_NUMDOUBLES; - fpg->primeBitSize = ECFP_BSIZE; - fpg->orderBitSize = 224; - fpg->doubleBitSize = 24; - fpg->numInts = (ECFP_BSIZE + ECL_BITS - 1) / ECL_BITS; - fpg->aIsM3 = 1; - fpg->ecfp_singleReduce = &ecfp224_singleReduce; - fpg->ecfp_reduce = &ecfp224_reduce; - fpg->ecfp_tidy = &ecfp_tidy; - - fpg->pt_add_jac_aff = &ecfp224_pt_add_jac_aff; - fpg->pt_add_jac = &ecfp224_pt_add_jac; - fpg->pt_add_jm_chud = &ecfp224_pt_add_jm_chud; - fpg->pt_add_chud = &ecfp224_pt_add_chud; - fpg->pt_dbl_jac = &ecfp224_pt_dbl_jac; - fpg->pt_dbl_jm = &ecfp224_pt_dbl_jm; - fpg->pt_dbl_aff2chud = &ecfp224_pt_dbl_aff2chud; - fpg->precompute_chud = &ecfp224_precompute_chud; - fpg->precompute_jac = &ecfp224_precompute_jac; - - group->point_mul = &ec_GFp_point_mul_wNAF_fp; - group->points_mul = &ec_pts_mul_basic; - group->extra1 = fpg; - group->extra_free = &ec_GFp_extra_free_fp; - - ec_set_fp_precision(fpg); - fpg->bitSize_alpha = ECFP_TWO224 * fpg->alpha[0]; - - return MP_OKAY; -} diff --git a/nss/lib/freebl/ecl/ecp_fpinc.c b/nss/lib/freebl/ecl/ecp_fpinc.c deleted file mode 100644 index be0f966..0000000 --- a/nss/lib/freebl/ecl/ecp_fpinc.c +++ /dev/null @@ -1,821 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -/* This source file is meant to be included by other source files - * (ecp_fp###.c, where ### is one of 160, 192, 224) and should not - * constitute an independent compilation unit. It requires the following - * preprocessor definitions be made: ECFP_BSIZE - the number of bits in - * the field's prime - * ECFP_NUMDOUBLES - the number of doubles to store one - * multi-precision integer in floating point - -/* Adds a prefix to a given token to give a unique token name. Prefixes - * with "ecfp" + ECFP_BSIZE + "_". e.g. if ECFP_BSIZE = 160, then - * PREFIX(hello) = ecfp160_hello This optimization allows static function - * linking and compiler loop unrolling without code duplication. */ -#ifndef PREFIX -#define PREFIX(b) PREFIX1(ECFP_BSIZE, b) -#define PREFIX1(bsize, b) PREFIX2(bsize, b) -#define PREFIX2(bsize, b) ecfp ## bsize ## _ ## b -#endif - -/* Returns true iff every double in d is 0. (If d == 0 and it is tidied, - * this will be true.) */ -mp_err PREFIX(isZero) (const double *d) { - int i; - - for (i = 0; i < ECFP_NUMDOUBLES; i++) { - if (d[i] != 0) - return MP_NO; - } - return MP_YES; -} - -/* Sets the multi-precision floating point number at t = 0 */ -void PREFIX(zero) (double *t) { - int i; - - for (i = 0; i < ECFP_NUMDOUBLES; i++) { - t[i] = 0; - } -} - -/* Sets the multi-precision floating point number at t = 1 */ -void PREFIX(one) (double *t) { - int i; - - t[0] = 1; - for (i = 1; i < ECFP_NUMDOUBLES; i++) { - t[i] = 0; - } -} - -/* Checks if point P(x, y, z) is at infinity. Uses Jacobian coordinates. */ -mp_err PREFIX(pt_is_inf_jac) (const ecfp_jac_pt * p) { - return PREFIX(isZero) (p->z); -} - -/* Sets the Jacobian point P to be at infinity. */ -void PREFIX(set_pt_inf_jac) (ecfp_jac_pt * p) { - PREFIX(zero) (p->z); -} - -/* Checks if point P(x, y) is at infinity. Uses Affine coordinates. */ -mp_err PREFIX(pt_is_inf_aff) (const ecfp_aff_pt * p) { - if (PREFIX(isZero) (p->x) == MP_YES && PREFIX(isZero) (p->y) == MP_YES) - return MP_YES; - return MP_NO; -} - -/* Sets the affine point P to be at infinity. */ -void PREFIX(set_pt_inf_aff) (ecfp_aff_pt * p) { - PREFIX(zero) (p->x); - PREFIX(zero) (p->y); -} - -/* Checks if point P(x, y, z, a*z^4) is at infinity. Uses Modified - * Jacobian coordinates. */ -mp_err PREFIX(pt_is_inf_jm) (const ecfp_jm_pt * p) { - return PREFIX(isZero) (p->z); -} - -/* Sets the Modified Jacobian point P to be at infinity. */ -void PREFIX(set_pt_inf_jm) (ecfp_jm_pt * p) { - PREFIX(zero) (p->z); -} - -/* Checks if point P(x, y, z, z^2, z^3) is at infinity. Uses Chudnovsky - * Jacobian coordinates */ -mp_err PREFIX(pt_is_inf_chud) (const ecfp_chud_pt * p) { - return PREFIX(isZero) (p->z); -} - -/* Sets the Chudnovsky Jacobian point P to be at infinity. */ -void PREFIX(set_pt_inf_chud) (ecfp_chud_pt * p) { - PREFIX(zero) (p->z); -} - -/* Copies a multi-precision floating point number, Setting dest = src */ -void PREFIX(copy) (double *dest, const double *src) { - int i; - - for (i = 0; i < ECFP_NUMDOUBLES; i++) { - dest[i] = src[i]; - } -} - -/* Sets dest = -src */ -void PREFIX(negLong) (double *dest, const double *src) { - int i; - - for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) { - dest[i] = -src[i]; - } -} - -/* Sets r = -p p = (x, y, z, z2, z3) r = (x, -y, z, z2, z3) Uses - * Chudnovsky Jacobian coordinates. */ -/* TODO reverse order */ -void PREFIX(pt_neg_chud) (const ecfp_chud_pt * p, ecfp_chud_pt * r) { - int i; - - PREFIX(copy) (r->x, p->x); - PREFIX(copy) (r->z, p->z); - PREFIX(copy) (r->z2, p->z2); - PREFIX(copy) (r->z3, p->z3); - for (i = 0; i < ECFP_NUMDOUBLES; i++) { - r->y[i] = -p->y[i]; - } -} - -/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x, - * y can point to the same data. Componentwise adds first ECFP_NUMDOUBLES - * doubles of x and y and stores the result in r. */ -void PREFIX(addShort) (double *r, const double *x, const double *y) { - int i; - - for (i = 0; i < ECFP_NUMDOUBLES; i++) { - *r++ = *x++ + *y++; - } -} - -/* Computes r = x + y. Does not tidy or reduce. Any combinations of r, x, - * y can point to the same data. Componentwise adds first - * 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */ -void PREFIX(addLong) (double *r, const double *x, const double *y) { - int i; - - for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) { - *r++ = *x++ + *y++; - } -} - -/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x, - * y can point to the same data. Componentwise subtracts first - * ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */ -void PREFIX(subtractShort) (double *r, const double *x, const double *y) { - int i; - - for (i = 0; i < ECFP_NUMDOUBLES; i++) { - *r++ = *x++ - *y++; - } -} - -/* Computes r = x - y. Does not tidy or reduce. Any combinations of r, x, - * y can point to the same data. Componentwise subtracts first - * 2*ECFP_NUMDOUBLES doubles of x and y and stores the result in r. */ -void PREFIX(subtractLong) (double *r, const double *x, const double *y) { - int i; - - for (i = 0; i < 2 * ECFP_NUMDOUBLES; i++) { - *r++ = *x++ - *y++; - } -} - -/* Computes r = x*y. Both x and y should be tidied and reduced, - * r must be different (point to different memory) than x and y. - * Does not tidy or reduce. */ -void PREFIX(multiply)(double *r, const double *x, const double *y) { - int i, j; - - for(j=0;j<ECFP_NUMDOUBLES-1;j++) { - r[j] = x[0] * y[j]; - r[j+(ECFP_NUMDOUBLES-1)] = x[ECFP_NUMDOUBLES-1] * y[j]; - } - r[ECFP_NUMDOUBLES-1] = x[0] * y[ECFP_NUMDOUBLES-1]; - r[ECFP_NUMDOUBLES-1] += x[ECFP_NUMDOUBLES-1] * y[0]; - r[2*ECFP_NUMDOUBLES-2] = x[ECFP_NUMDOUBLES-1] * y[ECFP_NUMDOUBLES-1]; - r[2*ECFP_NUMDOUBLES-1] = 0; - - for(i=1;i<ECFP_NUMDOUBLES-1;i++) { - for(j=0;j<ECFP_NUMDOUBLES;j++) { - r[i+j] += (x[i] * y[j]); - } - } -} - -/* Computes the square of x and stores the result in r. x should be - * tidied & reduced, r will be neither tidied nor reduced. - * r should point to different memory than x */ -void PREFIX(square) (double *r, const double *x) { - PREFIX(multiply) (r, x, x); -} - -/* Perform a point doubling in Jacobian coordinates. Input and output - * should be multi-precision floating point integers. */ -void PREFIX(pt_dbl_jac) (const ecfp_jac_pt * dp, ecfp_jac_pt * dr, - const EC_group_fp * group) { - double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES], - M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity */ - if (PREFIX(pt_is_inf_jac) (dp) == MP_YES) { - /* Set r = pt at infinity */ - PREFIX(set_pt_inf_jac) (dr); - goto CLEANUP; - } - - /* Perform typical point doubling operations */ - - /* TODO? is it worthwhile to do optimizations for when pz = 1? */ - - if (group->aIsM3) { - /* When a = -3, M = 3(px - pz^2)(px + pz^2) */ - PREFIX(square) (t1, dp->z); - group->ecfp_reduce(t1, t1, group); /* 2^23 since the negative - * rounding buys another bit */ - PREFIX(addShort) (t0, dp->x, t1); /* 2*2^23 */ - PREFIX(subtractShort) (t1, dp->x, t1); /* 2 * 2^23 */ - PREFIX(multiply) (M, t0, t1); /* 40 * 2^46 */ - PREFIX(addLong) (t0, M, M); /* 80 * 2^46 */ - PREFIX(addLong) (M, t0, M); /* 120 * 2^46 < 2^53 */ - group->ecfp_reduce(M, M, group); - } else { - /* Generic case */ - /* M = 3 (px^2) + a*(pz^4) */ - PREFIX(square) (t0, dp->x); - PREFIX(addLong) (M, t0, t0); - PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */ - PREFIX(square) (M, dp->z); - group->ecfp_reduce(M, M, group); - PREFIX(square) (t1, M); - group->ecfp_reduce(t1, t1, group); - PREFIX(multiply) (M, t1, group->curvea); /* M = a(pz^4) */ - PREFIX(addLong) (M, M, t0); - group->ecfp_reduce(M, M, group); - } - - /* rz = 2 * py * pz */ - PREFIX(multiply) (t1, dp->y, dp->z); - PREFIX(addLong) (t1, t1, t1); - group->ecfp_reduce(dr->z, t1, group); - - /* t0 = 2y^2 */ - PREFIX(square) (t0, dp->y); - group->ecfp_reduce(t0, t0, group); - PREFIX(addShort) (t0, t0, t0); - - /* S = 4 * px * py^2 = 2 * px * t0 */ - PREFIX(multiply) (S, dp->x, t0); - PREFIX(addLong) (S, S, S); - group->ecfp_reduce(S, S, group); - - /* rx = M^2 - 2 * S */ - PREFIX(square) (t1, M); - PREFIX(subtractShort) (t1, t1, S); - PREFIX(subtractShort) (t1, t1, S); - group->ecfp_reduce(dr->x, t1, group); - - /* ry = M * (S - rx) - 8 * py^4 */ - PREFIX(square) (t1, t0); /* t1 = 4y^4 */ - PREFIX(subtractShort) (S, S, dr->x); - PREFIX(multiply) (t0, M, S); - PREFIX(subtractLong) (t0, t0, t1); - PREFIX(subtractLong) (t0, t0, t1); - group->ecfp_reduce(dr->y, t0, group); - - CLEANUP: - return; -} - -/* Perform a point addition using coordinate system Jacobian + Affine -> - * Jacobian. Input and output should be multi-precision floating point - * integers. */ -void PREFIX(pt_add_jac_aff) (const ecfp_jac_pt * p, const ecfp_aff_pt * q, - ecfp_jac_pt * r, const EC_group_fp * group) { - /* Temporary storage */ - double A[2 * ECFP_NUMDOUBLES], B[2 * ECFP_NUMDOUBLES], - C[2 * ECFP_NUMDOUBLES], C2[2 * ECFP_NUMDOUBLES], - D[2 * ECFP_NUMDOUBLES], C3[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity for p or q */ - if (PREFIX(pt_is_inf_aff) (q) == MP_YES) { - PREFIX(copy) (r->x, p->x); - PREFIX(copy) (r->y, p->y); - PREFIX(copy) (r->z, p->z); - goto CLEANUP; - } else if (PREFIX(pt_is_inf_jac) (p) == MP_YES) { - PREFIX(copy) (r->x, q->x); - PREFIX(copy) (r->y, q->y); - /* Since the affine point is not infinity, we can set r->z = 1 */ - PREFIX(one) (r->z); - goto CLEANUP; - } - - /* Calculates c = qx * pz^2 - px d = (qy * b - py) rx = d^2 - c^3 + 2 - * (px * c^2) ry = d * (c-rx) - py*c^3 rz = c * pz */ - - /* A = pz^2, B = pz^3 */ - PREFIX(square) (A, p->z); - group->ecfp_reduce(A, A, group); - PREFIX(multiply) (B, A, p->z); - group->ecfp_reduce(B, B, group); - - /* C = qx * A - px */ - PREFIX(multiply) (C, q->x, A); - PREFIX(subtractShort) (C, C, p->x); - group->ecfp_reduce(C, C, group); - - /* D = qy * B - py */ - PREFIX(multiply) (D, q->y, B); - PREFIX(subtractShort) (D, D, p->y); - group->ecfp_reduce(D, D, group); - - /* C2 = C^2, C3 = C^3 */ - PREFIX(square) (C2, C); - group->ecfp_reduce(C2, C2, group); - PREFIX(multiply) (C3, C2, C); - group->ecfp_reduce(C3, C3, group); - - /* rz = A = pz * C */ - PREFIX(multiply) (A, p->z, C); - group->ecfp_reduce(r->z, A, group); - - /* C = px * C^2, untidied, unreduced */ - PREFIX(multiply) (C, p->x, C2); - - /* A = D^2, untidied, unreduced */ - PREFIX(square) (A, D); - - /* rx = B = A - C3 - C - C = D^2 - (C^3 + 2 * (px * C^2) */ - PREFIX(subtractShort) (A, A, C3); - PREFIX(subtractLong) (A, A, C); - PREFIX(subtractLong) (A, A, C); - group->ecfp_reduce(r->x, A, group); - - /* B = py * C3, untidied, unreduced */ - PREFIX(multiply) (B, p->y, C3); - - /* C = px * C^2 - rx */ - PREFIX(subtractShort) (C, C, r->x); - group->ecfp_reduce(C, C, group); - - /* ry = A = D * C - py * C^3 */ - PREFIX(multiply) (A, D, C); - PREFIX(subtractLong) (A, A, B); - group->ecfp_reduce(r->y, A, group); - - CLEANUP: - return; -} - -/* Perform a point addition using Jacobian coordinate system. Input and - * output should be multi-precision floating point integers. */ -void PREFIX(pt_add_jac) (const ecfp_jac_pt * p, const ecfp_jac_pt * q, - ecfp_jac_pt * r, const EC_group_fp * group) { - - /* Temporary Storage */ - double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES], - U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES], - S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES], - H3[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity for p, if so set r = q */ - if (PREFIX(pt_is_inf_jac) (p) == MP_YES) { - PREFIX(copy) (r->x, q->x); - PREFIX(copy) (r->y, q->y); - PREFIX(copy) (r->z, q->z); - goto CLEANUP; - } - - /* Check for point at infinity for p, if so set r = q */ - if (PREFIX(pt_is_inf_jac) (q) == MP_YES) { - PREFIX(copy) (r->x, p->x); - PREFIX(copy) (r->y, p->y); - PREFIX(copy) (r->z, p->z); - goto CLEANUP; - } - - /* U = px * qz^2 , S = py * qz^3 */ - PREFIX(square) (t0, q->z); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (U, p->x, t0); - group->ecfp_reduce(U, U, group); - PREFIX(multiply) (t1, t0, q->z); - group->ecfp_reduce(t1, t1, group); - PREFIX(multiply) (t0, p->y, t1); - group->ecfp_reduce(S, t0, group); - - /* H = qx*(pz)^2 - U , R = (qy * pz^3 - S) */ - PREFIX(square) (t0, p->z); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (H, q->x, t0); - PREFIX(subtractShort) (H, H, U); - group->ecfp_reduce(H, H, group); - PREFIX(multiply) (t1, t0, p->z); /* t1 = pz^3 */ - group->ecfp_reduce(t1, t1, group); - PREFIX(multiply) (t0, t1, q->y); /* t0 = qy * pz^3 */ - PREFIX(subtractShort) (t0, t0, S); - group->ecfp_reduce(R, t0, group); - - /* U = U*H^2, H3 = H^3 */ - PREFIX(square) (t0, H); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (t1, U, t0); - group->ecfp_reduce(U, t1, group); - PREFIX(multiply) (H3, t0, H); - group->ecfp_reduce(H3, H3, group); - - /* rz = pz * qz * H */ - PREFIX(multiply) (t0, q->z, H); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (t1, t0, p->z); - group->ecfp_reduce(r->z, t1, group); - - /* rx = R^2 - H^3 - 2 * U */ - PREFIX(square) (t0, R); - PREFIX(subtractShort) (t0, t0, H3); - PREFIX(subtractShort) (t0, t0, U); - PREFIX(subtractShort) (t0, t0, U); - group->ecfp_reduce(r->x, t0, group); - - /* ry = R(U - rx) - S*H3 */ - PREFIX(subtractShort) (t1, U, r->x); - PREFIX(multiply) (t0, t1, R); - PREFIX(multiply) (t1, S, H3); - PREFIX(subtractLong) (t1, t0, t1); - group->ecfp_reduce(r->y, t1, group); - - CLEANUP: - return; -} - -/* Perform a point doubling in Modified Jacobian coordinates. Input and - * output should be multi-precision floating point integers. */ -void PREFIX(pt_dbl_jm) (const ecfp_jm_pt * p, ecfp_jm_pt * r, - const EC_group_fp * group) { - - /* Temporary storage */ - double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES], - M[2 * ECFP_NUMDOUBLES], S[2 * ECFP_NUMDOUBLES], - U[2 * ECFP_NUMDOUBLES], T[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity */ - if (PREFIX(pt_is_inf_jm) (p) == MP_YES) { - /* Set r = pt at infinity by setting rz = 0 */ - PREFIX(set_pt_inf_jm) (r); - goto CLEANUP; - } - - /* M = 3 (px^2) + a*(pz^4) */ - PREFIX(square) (t0, p->x); - PREFIX(addLong) (M, t0, t0); - PREFIX(addLong) (t0, t0, M); /* t0 = 3(px^2) */ - PREFIX(addShort) (t0, t0, p->az4); - group->ecfp_reduce(M, t0, group); - - /* rz = 2 * py * pz */ - PREFIX(multiply) (t1, p->y, p->z); - PREFIX(addLong) (t1, t1, t1); - group->ecfp_reduce(r->z, t1, group); - - /* t0 = 2y^2, U = 8y^4 */ - PREFIX(square) (t0, p->y); - group->ecfp_reduce(t0, t0, group); - PREFIX(addShort) (t0, t0, t0); - PREFIX(square) (U, t0); - group->ecfp_reduce(U, U, group); - PREFIX(addShort) (U, U, U); - - /* S = 4 * px * py^2 = 2 * px * t0 */ - PREFIX(multiply) (S, p->x, t0); - group->ecfp_reduce(S, S, group); - PREFIX(addShort) (S, S, S); - - /* rx = M^2 - 2S */ - PREFIX(square) (T, M); - PREFIX(subtractShort) (T, T, S); - PREFIX(subtractShort) (T, T, S); - group->ecfp_reduce(r->x, T, group); - - /* ry = M * (S - rx) - U */ - PREFIX(subtractShort) (S, S, r->x); - PREFIX(multiply) (t0, M, S); - PREFIX(subtractShort) (t0, t0, U); - group->ecfp_reduce(r->y, t0, group); - - /* ra*z^4 = 2*U*(apz4) */ - PREFIX(multiply) (t1, U, p->az4); - PREFIX(addLong) (t1, t1, t1); - group->ecfp_reduce(r->az4, t1, group); - - CLEANUP: - return; -} - -/* Perform a point doubling using coordinates Affine -> Chudnovsky - * Jacobian. Input and output should be multi-precision floating point - * integers. */ -void PREFIX(pt_dbl_aff2chud) (const ecfp_aff_pt * p, ecfp_chud_pt * r, - const EC_group_fp * group) { - double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES], - M[2 * ECFP_NUMDOUBLES], twoY2[2 * ECFP_NUMDOUBLES], - S[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity for p, if so set r = O */ - if (PREFIX(pt_is_inf_aff) (p) == MP_YES) { - PREFIX(set_pt_inf_chud) (r); - goto CLEANUP; - } - - /* M = 3(px)^2 + a */ - PREFIX(square) (t0, p->x); - PREFIX(addLong) (t1, t0, t0); - PREFIX(addLong) (t1, t1, t0); - PREFIX(addShort) (t1, t1, group->curvea); - group->ecfp_reduce(M, t1, group); - - /* twoY2 = 2*(py)^2, S = 4(px)(py)^2 */ - PREFIX(square) (twoY2, p->y); - PREFIX(addLong) (twoY2, twoY2, twoY2); - group->ecfp_reduce(twoY2, twoY2, group); - PREFIX(multiply) (S, p->x, twoY2); - PREFIX(addLong) (S, S, S); - group->ecfp_reduce(S, S, group); - - /* rx = M^2 - 2S */ - PREFIX(square) (t0, M); - PREFIX(subtractShort) (t0, t0, S); - PREFIX(subtractShort) (t0, t0, S); - group->ecfp_reduce(r->x, t0, group); - - /* ry = M(S-rx) - 8y^4 */ - PREFIX(subtractShort) (t0, S, r->x); - PREFIX(multiply) (t1, t0, M); - PREFIX(square) (t0, twoY2); - PREFIX(subtractLong) (t1, t1, t0); - PREFIX(subtractLong) (t1, t1, t0); - group->ecfp_reduce(r->y, t1, group); - - /* rz = 2py */ - PREFIX(addShort) (r->z, p->y, p->y); - - /* rz2 = rz^2 */ - PREFIX(square) (t0, r->z); - group->ecfp_reduce(r->z2, t0, group); - - /* rz3 = rz^3 */ - PREFIX(multiply) (t0, r->z, r->z2); - group->ecfp_reduce(r->z3, t0, group); - - CLEANUP: - return; -} - -/* Perform a point addition using coordinates: Modified Jacobian + - * Chudnovsky Jacobian -> Modified Jacobian. Input and output should be - * multi-precision floating point integers. */ -void PREFIX(pt_add_jm_chud) (ecfp_jm_pt * p, ecfp_chud_pt * q, - ecfp_jm_pt * r, const EC_group_fp * group) { - - double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES], - U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES], - S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES], - H3[2 * ECFP_NUMDOUBLES], pz2[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity for p, if so set r = q need to convert - * from Chudnovsky form to Modified Jacobian form */ - if (PREFIX(pt_is_inf_jm) (p) == MP_YES) { - PREFIX(copy) (r->x, q->x); - PREFIX(copy) (r->y, q->y); - PREFIX(copy) (r->z, q->z); - PREFIX(square) (t0, q->z2); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (t1, t0, group->curvea); - group->ecfp_reduce(r->az4, t1, group); - goto CLEANUP; - } - /* Check for point at infinity for q, if so set r = p */ - if (PREFIX(pt_is_inf_chud) (q) == MP_YES) { - PREFIX(copy) (r->x, p->x); - PREFIX(copy) (r->y, p->y); - PREFIX(copy) (r->z, p->z); - PREFIX(copy) (r->az4, p->az4); - goto CLEANUP; - } - - /* U = px * qz^2 */ - PREFIX(multiply) (U, p->x, q->z2); - group->ecfp_reduce(U, U, group); - - /* H = qx*(pz)^2 - U */ - PREFIX(square) (t0, p->z); - group->ecfp_reduce(pz2, t0, group); - PREFIX(multiply) (H, pz2, q->x); - group->ecfp_reduce(H, H, group); - PREFIX(subtractShort) (H, H, U); - - /* U = U*H^2, H3 = H^3 */ - PREFIX(square) (t0, H); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (t1, U, t0); - group->ecfp_reduce(U, t1, group); - PREFIX(multiply) (H3, t0, H); - group->ecfp_reduce(H3, H3, group); - - /* S = py * qz^3 */ - PREFIX(multiply) (S, p->y, q->z3); - group->ecfp_reduce(S, S, group); - - /* R = (qy * z1^3 - s) */ - PREFIX(multiply) (t0, pz2, p->z); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (R, t0, q->y); - PREFIX(subtractShort) (R, R, S); - group->ecfp_reduce(R, R, group); - - /* rz = pz * qz * H */ - PREFIX(multiply) (t1, q->z, H); - group->ecfp_reduce(t1, t1, group); - PREFIX(multiply) (t0, p->z, t1); - group->ecfp_reduce(r->z, t0, group); - - /* rx = R^2 - H^3 - 2 * U */ - PREFIX(square) (t0, R); - PREFIX(subtractShort) (t0, t0, H3); - PREFIX(subtractShort) (t0, t0, U); - PREFIX(subtractShort) (t0, t0, U); - group->ecfp_reduce(r->x, t0, group); - - /* ry = R(U - rx) - S*H3 */ - PREFIX(subtractShort) (t1, U, r->x); - PREFIX(multiply) (t0, t1, R); - PREFIX(multiply) (t1, S, H3); - PREFIX(subtractLong) (t1, t0, t1); - group->ecfp_reduce(r->y, t1, group); - - if (group->aIsM3) { /* a == -3 */ - /* a(rz^4) = -3 * ((rz^2)^2) */ - PREFIX(square) (t0, r->z); - group->ecfp_reduce(t0, t0, group); - PREFIX(square) (t1, t0); - PREFIX(addLong) (t0, t1, t1); - PREFIX(addLong) (t0, t0, t1); - PREFIX(negLong) (t0, t0); - group->ecfp_reduce(r->az4, t0, group); - } else { /* Generic case */ - /* a(rz^4) = a * ((rz^2)^2) */ - PREFIX(square) (t0, r->z); - group->ecfp_reduce(t0, t0, group); - PREFIX(square) (t1, t0); - group->ecfp_reduce(t1, t1, group); - PREFIX(multiply) (t0, group->curvea, t1); - group->ecfp_reduce(r->az4, t0, group); - } - CLEANUP: - return; -} - -/* Perform a point addition using Chudnovsky Jacobian coordinates. Input - * and output should be multi-precision floating point integers. */ -void PREFIX(pt_add_chud) (const ecfp_chud_pt * p, const ecfp_chud_pt * q, - ecfp_chud_pt * r, const EC_group_fp * group) { - - /* Temporary Storage */ - double t0[2 * ECFP_NUMDOUBLES], t1[2 * ECFP_NUMDOUBLES], - U[2 * ECFP_NUMDOUBLES], R[2 * ECFP_NUMDOUBLES], - S[2 * ECFP_NUMDOUBLES], H[2 * ECFP_NUMDOUBLES], - H3[2 * ECFP_NUMDOUBLES]; - - /* Check for point at infinity for p, if so set r = q */ - if (PREFIX(pt_is_inf_chud) (p) == MP_YES) { - PREFIX(copy) (r->x, q->x); - PREFIX(copy) (r->y, q->y); - PREFIX(copy) (r->z, q->z); - PREFIX(copy) (r->z2, q->z2); - PREFIX(copy) (r->z3, q->z3); - goto CLEANUP; - } - - /* Check for point at infinity for p, if so set r = q */ - if (PREFIX(pt_is_inf_chud) (q) == MP_YES) { - PREFIX(copy) (r->x, p->x); - PREFIX(copy) (r->y, p->y); - PREFIX(copy) (r->z, p->z); - PREFIX(copy) (r->z2, p->z2); - PREFIX(copy) (r->z3, p->z3); - goto CLEANUP; - } - - /* U = px * qz^2 */ - PREFIX(multiply) (U, p->x, q->z2); - group->ecfp_reduce(U, U, group); - - /* H = qx*(pz)^2 - U */ - PREFIX(multiply) (H, q->x, p->z2); - PREFIX(subtractShort) (H, H, U); - group->ecfp_reduce(H, H, group); - - /* U = U*H^2, H3 = H^3 */ - PREFIX(square) (t0, H); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (t1, U, t0); - group->ecfp_reduce(U, t1, group); - PREFIX(multiply) (H3, t0, H); - group->ecfp_reduce(H3, H3, group); - - /* S = py * qz^3 */ - PREFIX(multiply) (S, p->y, q->z3); - group->ecfp_reduce(S, S, group); - - /* rz = pz * qz * H */ - PREFIX(multiply) (t0, q->z, H); - group->ecfp_reduce(t0, t0, group); - PREFIX(multiply) (t1, t0, p->z); - group->ecfp_reduce(r->z, t1, group); - - /* R = (qy * z1^3 - s) */ - PREFIX(multiply) (t0, q->y, p->z3); - PREFIX(subtractShort) (t0, t0, S); - group->ecfp_reduce(R, t0, group); - - /* rx = R^2 - H^3 - 2 * U */ - PREFIX(square) (t0, R); - PREFIX(subtractShort) (t0, t0, H3); - PREFIX(subtractShort) (t0, t0, U); - PREFIX(subtractShort) (t0, t0, U); - group->ecfp_reduce(r->x, t0, group); - - /* ry = R(U - rx) - S*H3 */ - PREFIX(subtractShort) (t1, U, r->x); - PREFIX(multiply) (t0, t1, R); - PREFIX(multiply) (t1, S, H3); - PREFIX(subtractLong) (t1, t0, t1); - group->ecfp_reduce(r->y, t1, group); - - /* rz2 = rz^2 */ - PREFIX(square) (t0, r->z); - group->ecfp_reduce(r->z2, t0, group); - - /* rz3 = rz^3 */ - PREFIX(multiply) (t0, r->z, r->z2); - group->ecfp_reduce(r->z3, t0, group); - - CLEANUP: - return; -} - -/* Expects out to be an array of size 16 of Chudnovsky Jacobian points. - * Fills in Chudnovsky Jacobian form (x, y, z, z^2, z^3), for -15P, -13P, - * -11P, -9P, -7P, -5P, -3P, -P, P, 3P, 5P, 7P, 9P, 11P, 13P, 15P */ -void PREFIX(precompute_chud) (ecfp_chud_pt * out, const ecfp_aff_pt * p, - const EC_group_fp * group) { - - ecfp_chud_pt p2; - - /* Set out[8] = P */ - PREFIX(copy) (out[8].x, p->x); - PREFIX(copy) (out[8].y, p->y); - PREFIX(one) (out[8].z); - PREFIX(one) (out[8].z2); - PREFIX(one) (out[8].z3); - - /* Set p2 = 2P */ - PREFIX(pt_dbl_aff2chud) (p, &p2, group); - - /* Set 3P, 5P, ..., 15P */ - PREFIX(pt_add_chud) (&out[8], &p2, &out[9], group); - PREFIX(pt_add_chud) (&out[9], &p2, &out[10], group); - PREFIX(pt_add_chud) (&out[10], &p2, &out[11], group); - PREFIX(pt_add_chud) (&out[11], &p2, &out[12], group); - PREFIX(pt_add_chud) (&out[12], &p2, &out[13], group); - PREFIX(pt_add_chud) (&out[13], &p2, &out[14], group); - PREFIX(pt_add_chud) (&out[14], &p2, &out[15], group); - - /* Set -15P, -13P, ..., -P */ - PREFIX(pt_neg_chud) (&out[8], &out[7]); - PREFIX(pt_neg_chud) (&out[9], &out[6]); - PREFIX(pt_neg_chud) (&out[10], &out[5]); - PREFIX(pt_neg_chud) (&out[11], &out[4]); - PREFIX(pt_neg_chud) (&out[12], &out[3]); - PREFIX(pt_neg_chud) (&out[13], &out[2]); - PREFIX(pt_neg_chud) (&out[14], &out[1]); - PREFIX(pt_neg_chud) (&out[15], &out[0]); -} - -/* Expects out to be an array of size 16 of Jacobian points. Fills in - * Jacobian form (x, y, z), for O, P, 2P, ... 15P */ -void PREFIX(precompute_jac) (ecfp_jac_pt * precomp, const ecfp_aff_pt * p, - const EC_group_fp * group) { - int i; - - /* fill precomputation table */ - /* set precomp[0] */ - PREFIX(set_pt_inf_jac) (&precomp[0]); - /* set precomp[1] */ - PREFIX(copy) (precomp[1].x, p->x); - PREFIX(copy) (precomp[1].y, p->y); - if (PREFIX(pt_is_inf_aff) (p) == MP_YES) { - PREFIX(zero) (precomp[1].z); - } else { - PREFIX(one) (precomp[1].z); - } - /* set precomp[2] */ - group->pt_dbl_jac(&precomp[1], &precomp[2], group); - - /* set rest of precomp */ - for (i = 3; i < 16; i++) { - group->pt_add_jac_aff(&precomp[i - 1], p, &precomp[i], group); - } -} diff --git a/nss/lib/freebl/ecl/ecp_jac.c b/nss/lib/freebl/ecl/ecp_jac.c index f174b16..535e759 100644 --- a/nss/lib/freebl/ecl/ecp_jac.c +++ b/nss/lib/freebl/ecl/ecp_jac.c @@ -15,22 +15,22 @@ * field-encoded. */ mp_err ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx, - mp_int *ry, mp_int *rz, const ECGroup *group) + mp_int *ry, mp_int *rz, const ECGroup *group) { - mp_err res = MP_OKAY; - - if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) { - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); - } else { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - MP_CHECKOK(mp_set_int(rz, 1)); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth)); - } - } - CLEANUP: - return res; + mp_err res = MP_OKAY; + + if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) { + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); + } else { + MP_CHECKOK(mp_copy(px, rx)); + MP_CHECKOK(mp_copy(py, ry)); + MP_CHECKOK(mp_set_int(rz, 1)); + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth)); + } + } +CLEANUP: + return res; } /* Converts a point P(px, py, pz) from Jacobian projective coordinates to @@ -39,41 +39,41 @@ ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx, * output that is still field-encoded. */ mp_err ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz, - mp_int *rx, mp_int *ry, const ECGroup *group) + mp_int *rx, mp_int *ry, const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int z1, z2, z3; - - MP_DIGITS(&z1) = 0; - MP_DIGITS(&z2) = 0; - MP_DIGITS(&z3) = 0; - MP_CHECKOK(mp_init(&z1)); - MP_CHECKOK(mp_init(&z2)); - MP_CHECKOK(mp_init(&z3)); - - /* if point at infinity, then set point at infinity and exit */ - if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { - MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry)); - goto CLEANUP; - } - - /* transform (px, py, pz) into (px / pz^2, py / pz^3) */ - if (mp_cmp_d(pz, 1) == 0) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - } else { - MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth)); - MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth)); - MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth)); - MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth)); - } - - CLEANUP: - mp_clear(&z1); - mp_clear(&z2); - mp_clear(&z3); - return res; + mp_err res = MP_OKAY; + mp_int z1, z2, z3; + + MP_DIGITS(&z1) = 0; + MP_DIGITS(&z2) = 0; + MP_DIGITS(&z3) = 0; + MP_CHECKOK(mp_init(&z1)); + MP_CHECKOK(mp_init(&z2)); + MP_CHECKOK(mp_init(&z3)); + + /* if point at infinity, then set point at infinity and exit */ + if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { + MP_CHECKOK(ec_GFp_pt_set_inf_aff(rx, ry)); + goto CLEANUP; + } + + /* transform (px, py, pz) into (px / pz^2, py / pz^3) */ + if (mp_cmp_d(pz, 1) == 0) { + MP_CHECKOK(mp_copy(px, rx)); + MP_CHECKOK(mp_copy(py, ry)); + } else { + MP_CHECKOK(group->meth->field_div(NULL, pz, &z1, group->meth)); + MP_CHECKOK(group->meth->field_sqr(&z1, &z2, group->meth)); + MP_CHECKOK(group->meth->field_mul(&z1, &z2, &z3, group->meth)); + MP_CHECKOK(group->meth->field_mul(px, &z2, rx, group->meth)); + MP_CHECKOK(group->meth->field_mul(py, &z3, ry, group->meth)); + } + +CLEANUP: + mp_clear(&z1); + mp_clear(&z2); + mp_clear(&z3); + return res; } /* Checks if point P(px, py, pz) is at infinity. Uses Jacobian @@ -81,7 +81,7 @@ ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz, mp_err ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz) { - return mp_cmp_z(pz); + return mp_cmp_z(pz); } /* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian @@ -89,8 +89,8 @@ ec_GFp_pt_is_inf_jac(const mp_int *px, const mp_int *py, const mp_int *pz) mp_err ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz) { - mp_zero(pz); - return MP_OKAY; + mp_zero(pz); + return MP_OKAY; } /* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is @@ -102,191 +102,191 @@ ec_GFp_pt_set_inf_jac(mp_int *px, mp_int *py, mp_int *pz) * Fields. */ mp_err ec_GFp_pt_add_jac_aff(const mp_int *px, const mp_int *py, const mp_int *pz, - const mp_int *qx, const mp_int *qy, mp_int *rx, - mp_int *ry, mp_int *rz, const ECGroup *group) + const mp_int *qx, const mp_int *qy, mp_int *rx, + mp_int *ry, mp_int *rz, const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int A, B, C, D, C2, C3; - - MP_DIGITS(&A) = 0; - MP_DIGITS(&B) = 0; - MP_DIGITS(&C) = 0; - MP_DIGITS(&D) = 0; - MP_DIGITS(&C2) = 0; - MP_DIGITS(&C3) = 0; - MP_CHECKOK(mp_init(&A)); - MP_CHECKOK(mp_init(&B)); - MP_CHECKOK(mp_init(&C)); - MP_CHECKOK(mp_init(&D)); - MP_CHECKOK(mp_init(&C2)); - MP_CHECKOK(mp_init(&C3)); - - /* If either P or Q is the point at infinity, then return the other - * point */ - if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { - MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group)); - goto CLEANUP; - } - if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - MP_CHECKOK(mp_copy(pz, rz)); - goto CLEANUP; - } - - /* A = qx * pz^2, B = qy * pz^3 */ - MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth)); - MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth)); - MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth)); - MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth)); - - /* C = A - px, D = B - py */ - MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth)); - MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth)); - - if (mp_cmp_z(&C) == 0) { - /* P == Q or P == -Q */ - if (mp_cmp_z(&D) == 0) { - /* P == Q */ - /* It is cheaper to double (qx, qy, 1) than (px, py, pz). */ - MP_DIGIT(&D, 0) = 1; /* Set D to 1. */ - MP_CHECKOK(ec_GFp_pt_dbl_jac(qx, qy, &D, rx, ry, rz, group)); - } else { - /* P == -Q */ - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); - } - goto CLEANUP; - } - - /* C2 = C^2, C3 = C^3 */ - MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth)); - MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth)); - - /* rz = pz * C */ - MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth)); - - /* C = px * C^2 */ - MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth)); - /* A = D^2 */ - MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth)); - - /* rx = D^2 - (C^3 + 2 * (px * C^2)) */ - MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth)); - MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth)); - - /* C3 = py * C^3 */ - MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth)); - - /* ry = D * (px * C^2 - rx) - py * C^3 */ - MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth)); - MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth)); - MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth)); - - CLEANUP: - mp_clear(&A); - mp_clear(&B); - mp_clear(&C); - mp_clear(&D); - mp_clear(&C2); - mp_clear(&C3); - return res; + mp_err res = MP_OKAY; + mp_int A, B, C, D, C2, C3; + + MP_DIGITS(&A) = 0; + MP_DIGITS(&B) = 0; + MP_DIGITS(&C) = 0; + MP_DIGITS(&D) = 0; + MP_DIGITS(&C2) = 0; + MP_DIGITS(&C3) = 0; + MP_CHECKOK(mp_init(&A)); + MP_CHECKOK(mp_init(&B)); + MP_CHECKOK(mp_init(&C)); + MP_CHECKOK(mp_init(&D)); + MP_CHECKOK(mp_init(&C2)); + MP_CHECKOK(mp_init(&C3)); + + /* If either P or Q is the point at infinity, then return the other + * point */ + if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { + MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group)); + goto CLEANUP; + } + if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) { + MP_CHECKOK(mp_copy(px, rx)); + MP_CHECKOK(mp_copy(py, ry)); + MP_CHECKOK(mp_copy(pz, rz)); + goto CLEANUP; + } + + /* A = qx * pz^2, B = qy * pz^3 */ + MP_CHECKOK(group->meth->field_sqr(pz, &A, group->meth)); + MP_CHECKOK(group->meth->field_mul(&A, pz, &B, group->meth)); + MP_CHECKOK(group->meth->field_mul(&A, qx, &A, group->meth)); + MP_CHECKOK(group->meth->field_mul(&B, qy, &B, group->meth)); + + /* C = A - px, D = B - py */ + MP_CHECKOK(group->meth->field_sub(&A, px, &C, group->meth)); + MP_CHECKOK(group->meth->field_sub(&B, py, &D, group->meth)); + + if (mp_cmp_z(&C) == 0) { + /* P == Q or P == -Q */ + if (mp_cmp_z(&D) == 0) { + /* P == Q */ + /* It is cheaper to double (qx, qy, 1) than (px, py, pz). */ + MP_DIGIT(&D, 0) = 1; /* Set D to 1. */ + MP_CHECKOK(ec_GFp_pt_dbl_jac(qx, qy, &D, rx, ry, rz, group)); + } else { + /* P == -Q */ + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); + } + goto CLEANUP; + } + + /* C2 = C^2, C3 = C^3 */ + MP_CHECKOK(group->meth->field_sqr(&C, &C2, group->meth)); + MP_CHECKOK(group->meth->field_mul(&C, &C2, &C3, group->meth)); + + /* rz = pz * C */ + MP_CHECKOK(group->meth->field_mul(pz, &C, rz, group->meth)); + + /* C = px * C^2 */ + MP_CHECKOK(group->meth->field_mul(px, &C2, &C, group->meth)); + /* A = D^2 */ + MP_CHECKOK(group->meth->field_sqr(&D, &A, group->meth)); + + /* rx = D^2 - (C^3 + 2 * (px * C^2)) */ + MP_CHECKOK(group->meth->field_add(&C, &C, rx, group->meth)); + MP_CHECKOK(group->meth->field_add(&C3, rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_sub(&A, rx, rx, group->meth)); + + /* C3 = py * C^3 */ + MP_CHECKOK(group->meth->field_mul(py, &C3, &C3, group->meth)); + + /* ry = D * (px * C^2 - rx) - py * C^3 */ + MP_CHECKOK(group->meth->field_sub(&C, rx, ry, group->meth)); + MP_CHECKOK(group->meth->field_mul(&D, ry, ry, group->meth)); + MP_CHECKOK(group->meth->field_sub(ry, &C3, ry, group->meth)); + +CLEANUP: + mp_clear(&A); + mp_clear(&B); + mp_clear(&C); + mp_clear(&D); + mp_clear(&C2); + mp_clear(&C3); + return res; } -/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses +/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses * Jacobian coordinates. * - * Assumes input is already field-encoded using field_enc, and returns + * Assumes input is already field-encoded using field_enc, and returns * output that is still field-encoded. * - * This routine implements Point Doubling in the Jacobian Projective - * space as described in the paper "Efficient elliptic curve exponentiation + * This routine implements Point Doubling in the Jacobian Projective + * space as described in the paper "Efficient elliptic curve exponentiation * using mixed coordinates", by H. Cohen, A Miyaji, T. Ono. */ mp_err ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, const mp_int *pz, - mp_int *rx, mp_int *ry, mp_int *rz, const ECGroup *group) + mp_int *rx, mp_int *ry, mp_int *rz, const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int t0, t1, M, S; - - MP_DIGITS(&t0) = 0; - MP_DIGITS(&t1) = 0; - MP_DIGITS(&M) = 0; - MP_DIGITS(&S) = 0; - MP_CHECKOK(mp_init(&t0)); - MP_CHECKOK(mp_init(&t1)); - MP_CHECKOK(mp_init(&M)); - MP_CHECKOK(mp_init(&S)); - - /* P == inf or P == -P */ - if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES || mp_cmp_z(py) == 0) { - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); - goto CLEANUP; - } - - if (mp_cmp_d(pz, 1) == 0) { - /* M = 3 * px^2 + a */ - MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth)); - MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth)); - MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth)); - MP_CHECKOK(group->meth-> - field_add(&t0, &group->curvea, &M, group->meth)); - } else if (mp_cmp_int(&group->curvea, -3) == 0) { - /* M = 3 * (px + pz^2) * (px - pz^2) */ - MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth)); - MP_CHECKOK(group->meth->field_add(px, &M, &t0, group->meth)); - MP_CHECKOK(group->meth->field_sub(px, &M, &t1, group->meth)); - MP_CHECKOK(group->meth->field_mul(&t0, &t1, &M, group->meth)); - MP_CHECKOK(group->meth->field_add(&M, &M, &t0, group->meth)); - MP_CHECKOK(group->meth->field_add(&t0, &M, &M, group->meth)); - } else { - /* M = 3 * (px^2) + a * (pz^4) */ - MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth)); - MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth)); - MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth)); - MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&M, &M, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(&M, &group->curvea, &M, group->meth)); - MP_CHECKOK(group->meth->field_add(&M, &t0, &M, group->meth)); - } - - /* rz = 2 * py * pz */ - /* t0 = 4 * py^2 */ - if (mp_cmp_d(pz, 1) == 0) { - MP_CHECKOK(group->meth->field_add(py, py, rz, group->meth)); - MP_CHECKOK(group->meth->field_sqr(rz, &t0, group->meth)); - } else { - MP_CHECKOK(group->meth->field_add(py, py, &t0, group->meth)); - MP_CHECKOK(group->meth->field_mul(&t0, pz, rz, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth)); - } - - /* S = 4 * px * py^2 = px * (2 * py)^2 */ - MP_CHECKOK(group->meth->field_mul(px, &t0, &S, group->meth)); - - /* rx = M^2 - 2 * S */ - MP_CHECKOK(group->meth->field_add(&S, &S, &t1, group->meth)); - MP_CHECKOK(group->meth->field_sqr(&M, rx, group->meth)); - MP_CHECKOK(group->meth->field_sub(rx, &t1, rx, group->meth)); - - /* ry = M * (S - rx) - 8 * py^4 */ - MP_CHECKOK(group->meth->field_sqr(&t0, &t1, group->meth)); - if (mp_isodd(&t1)) { - MP_CHECKOK(mp_add(&t1, &group->meth->irr, &t1)); - } - MP_CHECKOK(mp_div_2(&t1, &t1)); - MP_CHECKOK(group->meth->field_sub(&S, rx, &S, group->meth)); - MP_CHECKOK(group->meth->field_mul(&M, &S, &M, group->meth)); - MP_CHECKOK(group->meth->field_sub(&M, &t1, ry, group->meth)); - - CLEANUP: - mp_clear(&t0); - mp_clear(&t1); - mp_clear(&M); - mp_clear(&S); - return res; + mp_err res = MP_OKAY; + mp_int t0, t1, M, S; + + MP_DIGITS(&t0) = 0; + MP_DIGITS(&t1) = 0; + MP_DIGITS(&M) = 0; + MP_DIGITS(&S) = 0; + MP_CHECKOK(mp_init(&t0)); + MP_CHECKOK(mp_init(&t1)); + MP_CHECKOK(mp_init(&M)); + MP_CHECKOK(mp_init(&S)); + + /* P == inf or P == -P */ + if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES || mp_cmp_z(py) == 0) { + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); + goto CLEANUP; + } + + if (mp_cmp_d(pz, 1) == 0) { + /* M = 3 * px^2 + a */ + MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth)); + MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth)); + MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth)); + MP_CHECKOK(group->meth->field_add(&t0, &group->curvea, &M, group->meth)); + } else if (MP_SIGN(&group->curvea) == MP_NEG && + MP_USED(&group->curvea) == 1 && + MP_DIGIT(&group->curvea, 0) == 3) { + /* M = 3 * (px + pz^2) * (px - pz^2) */ + MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth)); + MP_CHECKOK(group->meth->field_add(px, &M, &t0, group->meth)); + MP_CHECKOK(group->meth->field_sub(px, &M, &t1, group->meth)); + MP_CHECKOK(group->meth->field_mul(&t0, &t1, &M, group->meth)); + MP_CHECKOK(group->meth->field_add(&M, &M, &t0, group->meth)); + MP_CHECKOK(group->meth->field_add(&t0, &M, &M, group->meth)); + } else { + /* M = 3 * (px^2) + a * (pz^4) */ + MP_CHECKOK(group->meth->field_sqr(px, &t0, group->meth)); + MP_CHECKOK(group->meth->field_add(&t0, &t0, &M, group->meth)); + MP_CHECKOK(group->meth->field_add(&t0, &M, &t0, group->meth)); + MP_CHECKOK(group->meth->field_sqr(pz, &M, group->meth)); + MP_CHECKOK(group->meth->field_sqr(&M, &M, group->meth)); + MP_CHECKOK(group->meth->field_mul(&M, &group->curvea, &M, group->meth)); + MP_CHECKOK(group->meth->field_add(&M, &t0, &M, group->meth)); + } + + /* rz = 2 * py * pz */ + /* t0 = 4 * py^2 */ + if (mp_cmp_d(pz, 1) == 0) { + MP_CHECKOK(group->meth->field_add(py, py, rz, group->meth)); + MP_CHECKOK(group->meth->field_sqr(rz, &t0, group->meth)); + } else { + MP_CHECKOK(group->meth->field_add(py, py, &t0, group->meth)); + MP_CHECKOK(group->meth->field_mul(&t0, pz, rz, group->meth)); + MP_CHECKOK(group->meth->field_sqr(&t0, &t0, group->meth)); + } + + /* S = 4 * px * py^2 = px * (2 * py)^2 */ + MP_CHECKOK(group->meth->field_mul(px, &t0, &S, group->meth)); + + /* rx = M^2 - 2 * S */ + MP_CHECKOK(group->meth->field_add(&S, &S, &t1, group->meth)); + MP_CHECKOK(group->meth->field_sqr(&M, rx, group->meth)); + MP_CHECKOK(group->meth->field_sub(rx, &t1, rx, group->meth)); + + /* ry = M * (S - rx) - 8 * py^4 */ + MP_CHECKOK(group->meth->field_sqr(&t0, &t1, group->meth)); + if (mp_isodd(&t1)) { + MP_CHECKOK(mp_add(&t1, &group->meth->irr, &t1)); + } + MP_CHECKOK(mp_div_2(&t1, &t1)); + MP_CHECKOK(group->meth->field_sub(&S, rx, &S, group->meth)); + MP_CHECKOK(group->meth->field_mul(&M, &S, &M, group->meth)); + MP_CHECKOK(group->meth->field_sub(&M, &t1, ry, group->meth)); + +CLEANUP: + mp_clear(&t0); + mp_clear(&t1); + mp_clear(&M); + mp_clear(&S); + return res; } /* by default, this routine is unused and thus doesn't need to be compiled */ @@ -295,83 +295,81 @@ ec_GFp_pt_dbl_jac(const mp_int *px, const mp_int *py, const mp_int *pz, * a, b and p are the elliptic curve coefficients and the prime that * determines the field GFp. Elliptic curve points P and R can be * identical. Uses mixed Jacobian-affine coordinates. Assumes input is - * already field-encoded using field_enc, and returns output that is still + * already field-encoded using field_enc, and returns output that is still * field-encoded. Uses 4-bit window method. */ mp_err ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) + mp_int *rx, mp_int *ry, const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int precomp[16][2], rz; - int i, ni, d; - - MP_DIGITS(&rz) = 0; - for (i = 0; i < 16; i++) { - MP_DIGITS(&precomp[i][0]) = 0; - MP_DIGITS(&precomp[i][1]) = 0; - } - - ARGCHK(group != NULL, MP_BADARG); - ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); - - /* initialize precomputation table */ - for (i = 0; i < 16; i++) { - MP_CHECKOK(mp_init(&precomp[i][0])); - MP_CHECKOK(mp_init(&precomp[i][1])); - } - - /* fill precomputation table */ - mp_zero(&precomp[0][0]); - mp_zero(&precomp[0][1]); - MP_CHECKOK(mp_copy(px, &precomp[1][0])); - MP_CHECKOK(mp_copy(py, &precomp[1][1])); - for (i = 2; i < 16; i++) { - MP_CHECKOK(group-> - point_add(&precomp[1][0], &precomp[1][1], - &precomp[i - 1][0], &precomp[i - 1][1], - &precomp[i][0], &precomp[i][1], group)); - } - - d = (mpl_significant_bits(n) + 3) / 4; - - /* R = inf */ - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); - - for (i = d - 1; i >= 0; i--) { - /* compute window ni */ - ni = MP_GET_BIT(n, 4 * i + 3); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i + 2); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i + 1); - ni <<= 1; - ni |= MP_GET_BIT(n, 4 * i); - /* R = 2^4 * R */ - MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); - /* R = R + (ni * P) */ - MP_CHECKOK(ec_GFp_pt_add_jac_aff - (rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry, - &rz, group)); - } - - /* convert result S to affine coordinates */ - MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); - - CLEANUP: - mp_clear(&rz); - for (i = 0; i < 16; i++) { - mp_clear(&precomp[i][0]); - mp_clear(&precomp[i][1]); - } - return res; + mp_err res = MP_OKAY; + mp_int precomp[16][2], rz; + int i, ni, d; + + MP_DIGITS(&rz) = 0; + for (i = 0; i < 16; i++) { + MP_DIGITS(&precomp[i][0]) = 0; + MP_DIGITS(&precomp[i][1]) = 0; + } + + ARGCHK(group != NULL, MP_BADARG); + ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); + + /* initialize precomputation table */ + for (i = 0; i < 16; i++) { + MP_CHECKOK(mp_init(&precomp[i][0])); + MP_CHECKOK(mp_init(&precomp[i][1])); + } + + /* fill precomputation table */ + mp_zero(&precomp[0][0]); + mp_zero(&precomp[0][1]); + MP_CHECKOK(mp_copy(px, &precomp[1][0])); + MP_CHECKOK(mp_copy(py, &precomp[1][1])); + for (i = 2; i < 16; i++) { + MP_CHECKOK(group->point_add(&precomp[1][0], &precomp[1][1], + &precomp[i - 1][0], &precomp[i - 1][1], + &precomp[i][0], &precomp[i][1], group)); + } + + d = (mpl_significant_bits(n) + 3) / 4; + + /* R = inf */ + MP_CHECKOK(mp_init(&rz)); + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); + + for (i = d - 1; i >= 0; i--) { + /* compute window ni */ + ni = MP_GET_BIT(n, 4 * i + 3); + ni <<= 1; + ni |= MP_GET_BIT(n, 4 * i + 2); + ni <<= 1; + ni |= MP_GET_BIT(n, 4 * i + 1); + ni <<= 1; + ni |= MP_GET_BIT(n, 4 * i); + /* R = 2^4 * R */ + MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); + MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); + MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); + MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); + /* R = R + (ni * P) */ + MP_CHECKOK(ec_GFp_pt_add_jac_aff(rx, ry, &rz, &precomp[ni][0], &precomp[ni][1], rx, ry, + &rz, group)); + } + + /* convert result S to affine coordinates */ + MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); + +CLEANUP: + mp_clear(&rz); + for (i = 0; i < 16; i++) { + mp_clear(&precomp[i][0]); + mp_clear(&precomp[i][1]); + } + return res; } #endif -/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + +/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G + * k2 * P(x, y), where G is the generator (base point) of the group of * points on the elliptic curve. Allows k1 = NULL or { k2, P } = NULL. * Uses mixed Jacobian-affine coordinates. Input and output values are @@ -380,150 +378,136 @@ ec_GFp_pt_mul_jac(const mp_int *n, const mp_int *px, const mp_int *py, * Software Implementation of the NIST Elliptic Curves over Prime Fields. */ mp_err ec_GFp_pts_mul_jac(const mp_int *k1, const mp_int *k2, const mp_int *px, - const mp_int *py, mp_int *rx, mp_int *ry, - const ECGroup *group) + const mp_int *py, mp_int *rx, mp_int *ry, + const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int precomp[4][4][2]; - mp_int rz; - const mp_int *a, *b; - unsigned int i, j; - int ai, bi, d; - - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - MP_DIGITS(&precomp[i][j][0]) = 0; - MP_DIGITS(&precomp[i][j][1]) = 0; - } - } - MP_DIGITS(&rz) = 0; - - ARGCHK(group != NULL, MP_BADARG); - ARGCHK(!((k1 == NULL) - && ((k2 == NULL) || (px == NULL) - || (py == NULL))), MP_BADARG); - - /* if some arguments are not defined used ECPoint_mul */ - if (k1 == NULL) { - return ECPoint_mul(group, k2, px, py, rx, ry); - } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { - return ECPoint_mul(group, k1, NULL, NULL, rx, ry); - } - - /* initialize precomputation table */ - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - MP_CHECKOK(mp_init(&precomp[i][j][0])); - MP_CHECKOK(mp_init(&precomp[i][j][1])); - } - } - - /* fill precomputation table */ - /* assign {k1, k2} = {a, b} such that len(a) >= len(b) */ - if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) { - a = k2; - b = k1; - if (group->meth->field_enc) { - MP_CHECKOK(group->meth-> - field_enc(px, &precomp[1][0][0], group->meth)); - MP_CHECKOK(group->meth-> - field_enc(py, &precomp[1][0][1], group->meth)); - } else { - MP_CHECKOK(mp_copy(px, &precomp[1][0][0])); - MP_CHECKOK(mp_copy(py, &precomp[1][0][1])); - } - MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0])); - MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1])); - } else { - a = k1; - b = k2; - MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0])); - MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1])); - if (group->meth->field_enc) { - MP_CHECKOK(group->meth-> - field_enc(px, &precomp[0][1][0], group->meth)); - MP_CHECKOK(group->meth-> - field_enc(py, &precomp[0][1][1], group->meth)); - } else { - MP_CHECKOK(mp_copy(px, &precomp[0][1][0])); - MP_CHECKOK(mp_copy(py, &precomp[0][1][1])); - } - } - /* precompute [*][0][*] */ - mp_zero(&precomp[0][0][0]); - mp_zero(&precomp[0][0][1]); - MP_CHECKOK(group-> - point_dbl(&precomp[1][0][0], &precomp[1][0][1], - &precomp[2][0][0], &precomp[2][0][1], group)); - MP_CHECKOK(group-> - point_add(&precomp[1][0][0], &precomp[1][0][1], - &precomp[2][0][0], &precomp[2][0][1], - &precomp[3][0][0], &precomp[3][0][1], group)); - /* precompute [*][1][*] */ - for (i = 1; i < 4; i++) { - MP_CHECKOK(group-> - point_add(&precomp[0][1][0], &precomp[0][1][1], - &precomp[i][0][0], &precomp[i][0][1], - &precomp[i][1][0], &precomp[i][1][1], group)); - } - /* precompute [*][2][*] */ - MP_CHECKOK(group-> - point_dbl(&precomp[0][1][0], &precomp[0][1][1], - &precomp[0][2][0], &precomp[0][2][1], group)); - for (i = 1; i < 4; i++) { - MP_CHECKOK(group-> - point_add(&precomp[0][2][0], &precomp[0][2][1], - &precomp[i][0][0], &precomp[i][0][1], - &precomp[i][2][0], &precomp[i][2][1], group)); - } - /* precompute [*][3][*] */ - MP_CHECKOK(group-> - point_add(&precomp[0][1][0], &precomp[0][1][1], - &precomp[0][2][0], &precomp[0][2][1], - &precomp[0][3][0], &precomp[0][3][1], group)); - for (i = 1; i < 4; i++) { - MP_CHECKOK(group-> - point_add(&precomp[0][3][0], &precomp[0][3][1], - &precomp[i][0][0], &precomp[i][0][1], - &precomp[i][3][0], &precomp[i][3][1], group)); - } - - d = (mpl_significant_bits(a) + 1) / 2; - - /* R = inf */ - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); - - for (i = d; i-- > 0;) { - ai = MP_GET_BIT(a, 2 * i + 1); - ai <<= 1; - ai |= MP_GET_BIT(a, 2 * i); - bi = MP_GET_BIT(b, 2 * i + 1); - bi <<= 1; - bi |= MP_GET_BIT(b, 2 * i); - /* R = 2^2 * R */ - MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); - MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); - /* R = R + (ai * A + bi * B) */ - MP_CHECKOK(ec_GFp_pt_add_jac_aff - (rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1], - rx, ry, &rz, group)); - } - - MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); - - if (group->meth->field_dec) { - MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); - } - - CLEANUP: - mp_clear(&rz); - for (i = 0; i < 4; i++) { - for (j = 0; j < 4; j++) { - mp_clear(&precomp[i][j][0]); - mp_clear(&precomp[i][j][1]); - } - } - return res; + mp_err res = MP_OKAY; + mp_int precomp[4][4][2]; + mp_int rz; + const mp_int *a, *b; + unsigned int i, j; + int ai, bi, d; + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + MP_DIGITS(&precomp[i][j][0]) = 0; + MP_DIGITS(&precomp[i][j][1]) = 0; + } + } + MP_DIGITS(&rz) = 0; + + ARGCHK(group != NULL, MP_BADARG); + ARGCHK(!((k1 == NULL) && ((k2 == NULL) || (px == NULL) || (py == NULL))), MP_BADARG); + + /* if some arguments are not defined used ECPoint_mul */ + if (k1 == NULL) { + return ECPoint_mul(group, k2, px, py, rx, ry); + } else if ((k2 == NULL) || (px == NULL) || (py == NULL)) { + return ECPoint_mul(group, k1, NULL, NULL, rx, ry); + } + + /* initialize precomputation table */ + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + MP_CHECKOK(mp_init(&precomp[i][j][0])); + MP_CHECKOK(mp_init(&precomp[i][j][1])); + } + } + + /* fill precomputation table */ + /* assign {k1, k2} = {a, b} such that len(a) >= len(b) */ + if (mpl_significant_bits(k1) < mpl_significant_bits(k2)) { + a = k2; + b = k1; + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(px, &precomp[1][0][0], group->meth)); + MP_CHECKOK(group->meth->field_enc(py, &precomp[1][0][1], group->meth)); + } else { + MP_CHECKOK(mp_copy(px, &precomp[1][0][0])); + MP_CHECKOK(mp_copy(py, &precomp[1][0][1])); + } + MP_CHECKOK(mp_copy(&group->genx, &precomp[0][1][0])); + MP_CHECKOK(mp_copy(&group->geny, &precomp[0][1][1])); + } else { + a = k1; + b = k2; + MP_CHECKOK(mp_copy(&group->genx, &precomp[1][0][0])); + MP_CHECKOK(mp_copy(&group->geny, &precomp[1][0][1])); + if (group->meth->field_enc) { + MP_CHECKOK(group->meth->field_enc(px, &precomp[0][1][0], group->meth)); + MP_CHECKOK(group->meth->field_enc(py, &precomp[0][1][1], group->meth)); + } else { + MP_CHECKOK(mp_copy(px, &precomp[0][1][0])); + MP_CHECKOK(mp_copy(py, &precomp[0][1][1])); + } + } + /* precompute [*][0][*] */ + mp_zero(&precomp[0][0][0]); + mp_zero(&precomp[0][0][1]); + MP_CHECKOK(group->point_dbl(&precomp[1][0][0], &precomp[1][0][1], + &precomp[2][0][0], &precomp[2][0][1], group)); + MP_CHECKOK(group->point_add(&precomp[1][0][0], &precomp[1][0][1], + &precomp[2][0][0], &precomp[2][0][1], + &precomp[3][0][0], &precomp[3][0][1], group)); + /* precompute [*][1][*] */ + for (i = 1; i < 4; i++) { + MP_CHECKOK(group->point_add(&precomp[0][1][0], &precomp[0][1][1], + &precomp[i][0][0], &precomp[i][0][1], + &precomp[i][1][0], &precomp[i][1][1], group)); + } + /* precompute [*][2][*] */ + MP_CHECKOK(group->point_dbl(&precomp[0][1][0], &precomp[0][1][1], + &precomp[0][2][0], &precomp[0][2][1], group)); + for (i = 1; i < 4; i++) { + MP_CHECKOK(group->point_add(&precomp[0][2][0], &precomp[0][2][1], + &precomp[i][0][0], &precomp[i][0][1], + &precomp[i][2][0], &precomp[i][2][1], group)); + } + /* precompute [*][3][*] */ + MP_CHECKOK(group->point_add(&precomp[0][1][0], &precomp[0][1][1], + &precomp[0][2][0], &precomp[0][2][1], + &precomp[0][3][0], &precomp[0][3][1], group)); + for (i = 1; i < 4; i++) { + MP_CHECKOK(group->point_add(&precomp[0][3][0], &precomp[0][3][1], + &precomp[i][0][0], &precomp[i][0][1], + &precomp[i][3][0], &precomp[i][3][1], group)); + } + + d = (mpl_significant_bits(a) + 1) / 2; + + /* R = inf */ + MP_CHECKOK(mp_init(&rz)); + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); + + for (i = d; i-- > 0;) { + ai = MP_GET_BIT(a, 2 * i + 1); + ai <<= 1; + ai |= MP_GET_BIT(a, 2 * i); + bi = MP_GET_BIT(b, 2 * i + 1); + bi <<= 1; + bi |= MP_GET_BIT(b, 2 * i); + /* R = 2^2 * R */ + MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); + MP_CHECKOK(ec_GFp_pt_dbl_jac(rx, ry, &rz, rx, ry, &rz, group)); + /* R = R + (ai * A + bi * B) */ + MP_CHECKOK(ec_GFp_pt_add_jac_aff(rx, ry, &rz, &precomp[ai][bi][0], &precomp[ai][bi][1], + rx, ry, &rz, group)); + } + + MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); + + if (group->meth->field_dec) { + MP_CHECKOK(group->meth->field_dec(rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_dec(ry, ry, group->meth)); + } + +CLEANUP: + mp_clear(&rz); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + mp_clear(&precomp[i][j][0]); + mp_clear(&precomp[i][j][1]); + } + } + return res; } diff --git a/nss/lib/freebl/ecl/ecp_jm.c b/nss/lib/freebl/ecl/ecp_jm.c index 2d56412..a1106ce 100644 --- a/nss/lib/freebl/ecl/ecp_jm.c +++ b/nss/lib/freebl/ecl/ecp_jm.c @@ -9,76 +9,74 @@ #define MAX_SCRATCH 6 -/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses +/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses * Modified Jacobian coordinates. * - * Assumes input is already field-encoded using field_enc, and returns + * Assumes input is already field-encoded using field_enc, and returns * output that is still field-encoded. * */ static mp_err ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz, - const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz, - mp_int *raz4, mp_int scratch[], const ECGroup *group) + const mp_int *paz4, mp_int *rx, mp_int *ry, mp_int *rz, + mp_int *raz4, mp_int scratch[], const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int *t0, *t1, *M, *S; + mp_err res = MP_OKAY; + mp_int *t0, *t1, *M, *S; - t0 = &scratch[0]; - t1 = &scratch[1]; - M = &scratch[2]; - S = &scratch[3]; + t0 = &scratch[0]; + t1 = &scratch[1]; + M = &scratch[2]; + S = &scratch[3]; #if MAX_SCRATCH < 4 #error "Scratch array defined too small " #endif - /* Check for point at infinity */ - if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { - /* Set r = pt at infinity by setting rz = 0 */ + /* Check for point at infinity */ + if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { + /* Set r = pt at infinity by setting rz = 0 */ - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); - goto CLEANUP; - } + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz)); + goto CLEANUP; + } - /* M = 3 (px^2) + a*(pz^4) */ - MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth)); - MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth)); - MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth)); - MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth)); + /* M = 3 (px^2) + a*(pz^4) */ + MP_CHECKOK(group->meth->field_sqr(px, t0, group->meth)); + MP_CHECKOK(group->meth->field_add(t0, t0, M, group->meth)); + MP_CHECKOK(group->meth->field_add(t0, M, t0, group->meth)); + MP_CHECKOK(group->meth->field_add(t0, paz4, M, group->meth)); - /* rz = 2 * py * pz */ - MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth)); - MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth)); + /* rz = 2 * py * pz */ + MP_CHECKOK(group->meth->field_mul(py, pz, S, group->meth)); + MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth)); - /* t0 = 2y^2 , t1 = 8y^4 */ - MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth)); - MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth)); - MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth)); - MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth)); + /* t0 = 2y^2 , t1 = 8y^4 */ + MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth)); + MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth)); + MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth)); + MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth)); - /* S = 4 * px * py^2 = 2 * px * t0 */ - MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth)); - MP_CHECKOK(group->meth->field_add(S, S, S, group->meth)); + /* S = 4 * px * py^2 = 2 * px * t0 */ + MP_CHECKOK(group->meth->field_mul(px, t0, S, group->meth)); + MP_CHECKOK(group->meth->field_add(S, S, S, group->meth)); + /* rx = M^2 - 2S */ + MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth)); + MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth)); + MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth)); - /* rx = M^2 - 2S */ - MP_CHECKOK(group->meth->field_sqr(M, rx, group->meth)); - MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth)); - MP_CHECKOK(group->meth->field_sub(rx, S, rx, group->meth)); + /* ry = M * (S - rx) - t1 */ + MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth)); + MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth)); + MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth)); - /* ry = M * (S - rx) - t1 */ - MP_CHECKOK(group->meth->field_sub(S, rx, S, group->meth)); - MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth)); - MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth)); + /* ra*z^4 = 2*t1*(apz4) */ + MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth)); + MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth)); - /* ra*z^4 = 2*t1*(apz4) */ - MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth)); - MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth)); - - - CLEANUP: - return res; +CLEANUP: + return res; } /* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is @@ -88,84 +86,82 @@ ec_GFp_pt_dbl_jm(const mp_int *px, const mp_int *py, const mp_int *pz, * field-encoded. */ static mp_err ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz, - const mp_int *paz4, const mp_int *qx, - const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz, - mp_int *raz4, mp_int scratch[], const ECGroup *group) + const mp_int *paz4, const mp_int *qx, + const mp_int *qy, mp_int *rx, mp_int *ry, mp_int *rz, + mp_int *raz4, mp_int scratch[], const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int *A, *B, *C, *D, *C2, *C3; + mp_err res = MP_OKAY; + mp_int *A, *B, *C, *D, *C2, *C3; - A = &scratch[0]; - B = &scratch[1]; - C = &scratch[2]; - D = &scratch[3]; - C2 = &scratch[4]; - C3 = &scratch[5]; + A = &scratch[0]; + B = &scratch[1]; + C = &scratch[2]; + D = &scratch[3]; + C2 = &scratch[4]; + C3 = &scratch[5]; #if MAX_SCRATCH < 6 #error "Scratch array defined too small " #endif - /* If either P or Q is the point at infinity, then return the other - * point */ - if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { - MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group)); - MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth)); - MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(raz4, &group->curvea, raz4, group->meth)); - goto CLEANUP; - } - if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) { - MP_CHECKOK(mp_copy(px, rx)); - MP_CHECKOK(mp_copy(py, ry)); - MP_CHECKOK(mp_copy(pz, rz)); - MP_CHECKOK(mp_copy(paz4, raz4)); - goto CLEANUP; - } - - /* A = qx * pz^2, B = qy * pz^3 */ - MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth)); - MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth)); - MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth)); - MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth)); - - /* C = A - px, D = B - py */ - MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth)); - MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth)); - - /* C2 = C^2, C3 = C^3 */ - MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth)); - MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth)); - - /* rz = pz * C */ - MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth)); - - /* C = px * C^2 */ - MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth)); - /* A = D^2 */ - MP_CHECKOK(group->meth->field_sqr(D, A, group->meth)); - - /* rx = D^2 - (C^3 + 2 * (px * C^2)) */ - MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth)); - MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth)); - MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth)); - - /* C3 = py * C^3 */ - MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth)); - - /* ry = D * (px * C^2 - rx) - py * C^3 */ - MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth)); - MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth)); - MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth)); - - /* raz4 = a * rz^4 */ - MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth)); - MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth)); - MP_CHECKOK(group->meth-> - field_mul(raz4, &group->curvea, raz4, group->meth)); + /* If either P or Q is the point at infinity, then return the other + * point */ + if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { + MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group)); + MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth)); + MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth)); + MP_CHECKOK(group->meth->field_mul(raz4, &group->curvea, raz4, group->meth)); + goto CLEANUP; + } + if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) { + MP_CHECKOK(mp_copy(px, rx)); + MP_CHECKOK(mp_copy(py, ry)); + MP_CHECKOK(mp_copy(pz, rz)); + MP_CHECKOK(mp_copy(paz4, raz4)); + goto CLEANUP; + } + + /* A = qx * pz^2, B = qy * pz^3 */ + MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth)); + MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth)); + MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth)); + MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth)); + + /* C = A - px, D = B - py */ + MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth)); + MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth)); + + /* C2 = C^2, C3 = C^3 */ + MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth)); + MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth)); + + /* rz = pz * C */ + MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth)); + + /* C = px * C^2 */ + MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth)); + /* A = D^2 */ + MP_CHECKOK(group->meth->field_sqr(D, A, group->meth)); + + /* rx = D^2 - (C^3 + 2 * (px * C^2)) */ + MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth)); + MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth)); + MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth)); + + /* C3 = py * C^3 */ + MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth)); + + /* ry = D * (px * C^2 - rx) - py * C^3 */ + MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth)); + MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth)); + MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth)); + + /* raz4 = a * rz^4 */ + MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth)); + MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth)); + MP_CHECKOK(group->meth->field_mul(raz4, &group->curvea, raz4, group->meth)); CLEANUP: - return res; + return res; } /* Computes R = nP where R is (rx, ry) and P is the base point. Elliptic @@ -174,116 +170,114 @@ CLEANUP: * additions. Assumes input is already field-encoded using field_enc, and * returns output that is still field-encoded. Uses 5-bit window NAF * method (algorithm 11) for scalar-point multiplication from Brown, - * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic + * Hankerson, Lopez, Menezes. Software Implementation of the NIST Elliptic * Curves Over Prime Fields. */ mp_err ec_GFp_pt_mul_jm_wNAF(const mp_int *n, const mp_int *px, const mp_int *py, - mp_int *rx, mp_int *ry, const ECGroup *group) + mp_int *rx, mp_int *ry, const ECGroup *group) { - mp_err res = MP_OKAY; - mp_int precomp[16][2], rz, tpx, tpy; - mp_int raz4; - mp_int scratch[MAX_SCRATCH]; - signed char *naf = NULL; - int i, orderBitSize; - - MP_DIGITS(&rz) = 0; - MP_DIGITS(&raz4) = 0; - MP_DIGITS(&tpx) = 0; - MP_DIGITS(&tpy) = 0; - for (i = 0; i < 16; i++) { - MP_DIGITS(&precomp[i][0]) = 0; - MP_DIGITS(&precomp[i][1]) = 0; - } - for (i = 0; i < MAX_SCRATCH; i++) { - MP_DIGITS(&scratch[i]) = 0; - } - - ARGCHK(group != NULL, MP_BADARG); - ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); - - /* initialize precomputation table */ - MP_CHECKOK(mp_init(&tpx)); - MP_CHECKOK(mp_init(&tpy));; - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(mp_init(&raz4)); - - for (i = 0; i < 16; i++) { - MP_CHECKOK(mp_init(&precomp[i][0])); - MP_CHECKOK(mp_init(&precomp[i][1])); - } - for (i = 0; i < MAX_SCRATCH; i++) { - MP_CHECKOK(mp_init(&scratch[i])); - } - - /* Set out[8] = P */ - MP_CHECKOK(mp_copy(px, &precomp[8][0])); - MP_CHECKOK(mp_copy(py, &precomp[8][1])); - - /* Set (tpx, tpy) = 2P */ - MP_CHECKOK(group-> - point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy, - group)); - - /* Set 3P, 5P, ..., 15P */ - for (i = 8; i < 15; i++) { - MP_CHECKOK(group-> - point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy, - &precomp[i + 1][0], &precomp[i + 1][1], - group)); - } - - /* Set -15P, -13P, ..., -P */ - for (i = 0; i < 8; i++) { - MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0])); - MP_CHECKOK(group->meth-> - field_neg(&precomp[15 - i][1], &precomp[i][1], - group->meth)); - } - - /* R = inf */ - MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); - - orderBitSize = mpl_significant_bits(&group->order); - - /* Allocate memory for NAF */ - naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1)); - if (naf == NULL) { - res = MP_MEM; - goto CLEANUP; - } - - /* Compute 5NAF */ - ec_compute_wNAF(naf, orderBitSize, n, 5); - - /* wNAF method */ - for (i = orderBitSize; i >= 0; i--) { - /* R = 2R */ - ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz, - &raz4, scratch, group); - if (naf[i] != 0) { - ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4, - &precomp[(naf[i] + 15) / 2][0], - &precomp[(naf[i] + 15) / 2][1], rx, ry, - &rz, &raz4, scratch, group); - } - } - - /* convert result S to affine coordinates */ - MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); - - CLEANUP: - for (i = 0; i < MAX_SCRATCH; i++) { - mp_clear(&scratch[i]); - } - for (i = 0; i < 16; i++) { - mp_clear(&precomp[i][0]); - mp_clear(&precomp[i][1]); - } - mp_clear(&tpx); - mp_clear(&tpy); - mp_clear(&rz); - mp_clear(&raz4); - free(naf); - return res; + mp_err res = MP_OKAY; + mp_int precomp[16][2], rz, tpx, tpy; + mp_int raz4; + mp_int scratch[MAX_SCRATCH]; + signed char *naf = NULL; + int i, orderBitSize; + + MP_DIGITS(&rz) = 0; + MP_DIGITS(&raz4) = 0; + MP_DIGITS(&tpx) = 0; + MP_DIGITS(&tpy) = 0; + for (i = 0; i < 16; i++) { + MP_DIGITS(&precomp[i][0]) = 0; + MP_DIGITS(&precomp[i][1]) = 0; + } + for (i = 0; i < MAX_SCRATCH; i++) { + MP_DIGITS(&scratch[i]) = 0; + } + + ARGCHK(group != NULL, MP_BADARG); + ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG); + + /* initialize precomputation table */ + MP_CHECKOK(mp_init(&tpx)); + MP_CHECKOK(mp_init(&tpy)); + ; + MP_CHECKOK(mp_init(&rz)); + MP_CHECKOK(mp_init(&raz4)); + + for (i = 0; i < 16; i++) { + MP_CHECKOK(mp_init(&precomp[i][0])); + MP_CHECKOK(mp_init(&precomp[i][1])); + } + for (i = 0; i < MAX_SCRATCH; i++) { + MP_CHECKOK(mp_init(&scratch[i])); + } + + /* Set out[8] = P */ + MP_CHECKOK(mp_copy(px, &precomp[8][0])); + MP_CHECKOK(mp_copy(py, &precomp[8][1])); + + /* Set (tpx, tpy) = 2P */ + MP_CHECKOK(group->point_dbl(&precomp[8][0], &precomp[8][1], &tpx, &tpy, + group)); + + /* Set 3P, 5P, ..., 15P */ + for (i = 8; i < 15; i++) { + MP_CHECKOK(group->point_add(&precomp[i][0], &precomp[i][1], &tpx, &tpy, + &precomp[i + 1][0], &precomp[i + 1][1], + group)); + } + + /* Set -15P, -13P, ..., -P */ + for (i = 0; i < 8; i++) { + MP_CHECKOK(mp_copy(&precomp[15 - i][0], &precomp[i][0])); + MP_CHECKOK(group->meth->field_neg(&precomp[15 - i][1], &precomp[i][1], + group->meth)); + } + + /* R = inf */ + MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, &rz)); + + orderBitSize = mpl_significant_bits(&group->order); + + /* Allocate memory for NAF */ + naf = (signed char *)malloc(sizeof(signed char) * (orderBitSize + 1)); + if (naf == NULL) { + res = MP_MEM; + goto CLEANUP; + } + + /* Compute 5NAF */ + ec_compute_wNAF(naf, orderBitSize, n, 5); + + /* wNAF method */ + for (i = orderBitSize; i >= 0; i--) { + /* R = 2R */ + ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz, + &raz4, scratch, group); + if (naf[i] != 0) { + ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4, + &precomp[(naf[i] + 15) / 2][0], + &precomp[(naf[i] + 15) / 2][1], rx, ry, + &rz, &raz4, scratch, group); + } + } + + /* convert result S to affine coordinates */ + MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); + +CLEANUP: + for (i = 0; i < MAX_SCRATCH; i++) { + mp_clear(&scratch[i]); + } + for (i = 0; i < 16; i++) { + mp_clear(&precomp[i][0]); + mp_clear(&precomp[i][1]); + } + mp_clear(&tpx); + mp_clear(&tpy); + mp_clear(&rz); + mp_clear(&raz4); + free(naf); + return res; } diff --git a/nss/lib/freebl/ecl/ecp_mont.c b/nss/lib/freebl/ecl/ecp_mont.c index 6b8462e..779685b 100644 --- a/nss/lib/freebl/ecl/ecp_mont.c +++ b/nss/lib/freebl/ecl/ecp_mont.c @@ -18,38 +18,38 @@ GFMethod * GFMethod_consGFp_mont(const mp_int *irr) { - mp_err res = MP_OKAY; - GFMethod *meth = NULL; - mp_mont_modulus *mmm; - - meth = GFMethod_consGFp(irr); - if (meth == NULL) - return NULL; - - mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus)); - if (mmm == NULL) { - res = MP_MEM; - goto CLEANUP; - } - - meth->field_mul = &ec_GFp_mul_mont; - meth->field_sqr = &ec_GFp_sqr_mont; - meth->field_div = &ec_GFp_div_mont; - meth->field_enc = &ec_GFp_enc_mont; - meth->field_dec = &ec_GFp_dec_mont; - meth->extra1 = mmm; - meth->extra2 = NULL; - meth->extra_free = &ec_GFp_extra_free_mont; - - mmm->N = meth->irr; - mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0)); - - CLEANUP: - if (res != MP_OKAY) { - GFMethod_free(meth); - return NULL; - } - return meth; + mp_err res = MP_OKAY; + GFMethod *meth = NULL; + mp_mont_modulus *mmm; + + meth = GFMethod_consGFp(irr); + if (meth == NULL) + return NULL; + + mmm = (mp_mont_modulus *)malloc(sizeof(mp_mont_modulus)); + if (mmm == NULL) { + res = MP_MEM; + goto CLEANUP; + } + + meth->field_mul = &ec_GFp_mul_mont; + meth->field_sqr = &ec_GFp_sqr_mont; + meth->field_div = &ec_GFp_div_mont; + meth->field_enc = &ec_GFp_enc_mont; + meth->field_dec = &ec_GFp_dec_mont; + meth->extra1 = mmm; + meth->extra2 = NULL; + meth->extra_free = &ec_GFp_extra_free_mont; + + mmm->N = meth->irr; + mmm->n0prime = 0 - s_mp_invmod_radix(MP_DIGIT(&meth->irr, 0)); + +CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; } /* Wrapper functions for generic prime field arithmetic. */ @@ -57,60 +57,59 @@ GFMethod_consGFp_mont(const mp_int *irr) /* Field multiplication using Montgomery reduction. */ mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; + mp_err res = MP_OKAY; #ifdef MP_MONT_USE_MP_MUL - /* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont - * is not implemented and we have to use mp_mul and s_mp_redc directly - */ - MP_CHECKOK(mp_mul(a, b, r)); - MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1)); + /* if MP_MONT_USE_MP_MUL is defined, then the function s_mp_mul_mont + * is not implemented and we have to use mp_mul and s_mp_redc directly + */ + MP_CHECKOK(mp_mul(a, b, r)); + MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *)meth->extra1)); #else - mp_int s; - - MP_DIGITS(&s) = 0; - /* s_mp_mul_mont doesn't allow source and destination to be the same */ - if ((a == r) || (b == r)) { - MP_CHECKOK(mp_init(&s)); - MP_CHECKOK(s_mp_mul_mont - (a, b, &s, (mp_mont_modulus *) meth->extra1)); - MP_CHECKOK(mp_copy(&s, r)); - mp_clear(&s); - } else { - return s_mp_mul_mont(a, b, r, (mp_mont_modulus *) meth->extra1); - } + mp_int s; + + MP_DIGITS(&s) = 0; + /* s_mp_mul_mont doesn't allow source and destination to be the same */ + if ((a == r) || (b == r)) { + MP_CHECKOK(mp_init(&s)); + MP_CHECKOK(s_mp_mul_mont(a, b, &s, (mp_mont_modulus *)meth->extra1)); + MP_CHECKOK(mp_copy(&s, r)); + mp_clear(&s); + } else { + return s_mp_mul_mont(a, b, r, (mp_mont_modulus *)meth->extra1); + } #endif - CLEANUP: - return res; +CLEANUP: + return res; } /* Field squaring using Montgomery reduction. */ mp_err ec_GFp_sqr_mont(const mp_int *a, mp_int *r, const GFMethod *meth) { - return ec_GFp_mul_mont(a, a, r, meth); + return ec_GFp_mul_mont(a, a, r, meth); } /* Field division using Montgomery reduction. */ mp_err ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r, - const GFMethod *meth) + const GFMethod *meth) { - mp_err res = MP_OKAY; - - /* if A=aZ represents a encoded in montgomery coordinates with Z and # - * and \ respectively represent multiplication and division in - * montgomery coordinates, then A\B = (a/b)Z = (A/B)Z and Binv = - * (1/b)Z = (1/B)(Z^2) where B # Binv = Z */ - MP_CHECKOK(ec_GFp_div(a, b, r, meth)); - MP_CHECKOK(ec_GFp_enc_mont(r, r, meth)); - if (a == NULL) { - MP_CHECKOK(ec_GFp_enc_mont(r, r, meth)); - } - CLEANUP: - return res; + mp_err res = MP_OKAY; + + /* if A=aZ represents a encoded in montgomery coordinates with Z and # + * and \ respectively represent multiplication and division in + * montgomery coordinates, then A\B = (a/b)Z = (A/B)Z and Binv = + * (1/b)Z = (1/B)(Z^2) where B # Binv = Z */ + MP_CHECKOK(ec_GFp_div(a, b, r, meth)); + MP_CHECKOK(ec_GFp_enc_mont(r, r, meth)); + if (a == NULL) { + MP_CHECKOK(ec_GFp_enc_mont(r, r, meth)); + } +CLEANUP: + return res; } /* Encode a field element in Montgomery form. See s_mp_to_mont in @@ -118,29 +117,29 @@ ec_GFp_div_mont(const mp_int *a, const mp_int *b, mp_int *r, mp_err ec_GFp_enc_mont(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_mont_modulus *mmm; - mp_err res = MP_OKAY; - - mmm = (mp_mont_modulus *) meth->extra1; - MP_CHECKOK(mp_copy(a, r)); - MP_CHECKOK(s_mp_lshd(r, MP_USED(&mmm->N))); - MP_CHECKOK(mp_mod(r, &mmm->N, r)); - CLEANUP: - return res; + mp_mont_modulus *mmm; + mp_err res = MP_OKAY; + + mmm = (mp_mont_modulus *)meth->extra1; + MP_CHECKOK(mp_copy(a, r)); + MP_CHECKOK(s_mp_lshd(r, MP_USED(&mmm->N))); + MP_CHECKOK(mp_mod(r, &mmm->N, r)); +CLEANUP: + return res; } /* Decode a field element from Montgomery form. */ mp_err ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth) { - mp_err res = MP_OKAY; - - if (a != r) { - MP_CHECKOK(mp_copy(a, r)); - } - MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *) meth->extra1)); - CLEANUP: - return res; + mp_err res = MP_OKAY; + + if (a != r) { + MP_CHECKOK(mp_copy(a, r)); + } + MP_CHECKOK(s_mp_redc(r, (mp_mont_modulus *)meth->extra1)); +CLEANUP: + return res; } /* Free the memory allocated to the extra fields of Montgomery GFMethod @@ -148,8 +147,8 @@ ec_GFp_dec_mont(const mp_int *a, mp_int *r, const GFMethod *meth) void ec_GFp_extra_free_mont(GFMethod *meth) { - if (meth->extra1 != NULL) { - free(meth->extra1); - meth->extra1 = NULL; - } + if (meth->extra1 != NULL) { + free(meth->extra1); + meth->extra1 = NULL; + } } diff --git a/nss/lib/freebl/ecl/tests/ec2_test.c b/nss/lib/freebl/ecl/tests/ec2_test.c deleted file mode 100644 index 1b4d8c3..0000000 --- a/nss/lib/freebl/ecl/tests/ec2_test.c +++ /dev/null @@ -1,482 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "mpi.h" -#include "mplogic.h" -#include "mpprime.h" -#include "mp_gf2m.h" -#include "ecl.h" -#include "ecl-curve.h" -#include "ec2.h" -#include <stdio.h> -#include <strings.h> -#include <assert.h> - -#include <time.h> -#include <sys/time.h> -#include <sys/resource.h> - -/* Time k repetitions of operation op. */ -#define M_TimeOperation(op, k) { \ - double dStart, dNow, dUserTime; \ - struct rusage ru; \ - int i; \ - getrusage(RUSAGE_SELF, &ru); \ - dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - for (i = 0; i < k; i++) { \ - { op; } \ - }; \ - getrusage(RUSAGE_SELF, &ru); \ - dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - dUserTime = dNow-dStart; \ - if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \ -} - -/* Test curve using generic field arithmetic. */ -#define ECTEST_GENERIC_GF2M(name_c, name) \ - printf("Testing %s using generic implementation...\n", name_c); \ - params = EC_GetNamedCurveParams(name); \ - if (params == NULL) { \ - printf(" Error: could not construct params.\n"); \ - res = MP_NO; \ - goto CLEANUP; \ - } \ - ECGroup_free(group); \ - group = ECGroup_fromHex(params); \ - if (group == NULL) { \ - printf(" Error: could not construct group.\n"); \ - res = MP_NO; \ - goto CLEANUP; \ - } \ - MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 1) ); \ - printf("... okay.\n"); - -/* Test curve using specific field arithmetic. */ -#define ECTEST_NAMED_GF2M(name_c, name) \ - printf("Testing %s using specific implementation...\n", name_c); \ - ECGroup_free(group); \ - group = ECGroup_fromName(name); \ - if (group == NULL) { \ - printf(" Warning: could not construct group.\n"); \ - printf("... failed; continuing with remaining tests.\n"); \ - } else { \ - MP_CHECKOK( ectest_curve_GF2m(group, ectestPrint, ectestTime, 0) ); \ - printf("... okay.\n"); \ - } - -/* Performs basic tests of elliptic curve cryptography over binary - * polynomial fields. If tests fail, then it prints an error message, - * aborts, and returns an error code. Otherwise, returns 0. */ -int -ectest_curve_GF2m(ECGroup *group, int ectestPrint, int ectestTime, - int generic) -{ - - mp_int one, order_1, gx, gy, rx, ry, n; - int size; - mp_err res; - char s[1000]; - - /* initialize values */ - MP_CHECKOK(mp_init(&one)); - MP_CHECKOK(mp_init(&order_1)); - MP_CHECKOK(mp_init(&gx)); - MP_CHECKOK(mp_init(&gy)); - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&n)); - - MP_CHECKOK(mp_set_int(&one, 1)); - MP_CHECKOK(mp_sub(&group->order, &one, &order_1)); - - /* encode base point */ - if (group->meth->field_dec) { - MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth)); - MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth)); - } else { - MP_CHECKOK(mp_copy(&group->genx, &gx)); - MP_CHECKOK(mp_copy(&group->geny, &gy)); - } - - if (ectestPrint) { - /* output base point */ - printf(" base point P:\n"); - MP_CHECKOK(mp_toradix(&gx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&gy, s, 16)); - printf(" %s\n", s); - if (group->meth->field_enc) { - printf(" base point P (encoded):\n"); - MP_CHECKOK(mp_toradix(&group->genx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&group->geny, s, 16)); - printf(" %s\n", s); - } - } - -#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ec_GF2m_pt_mul_aff - (&order_1, &group->genx, &group->geny, &rx, &ry, group)); - if (ectestPrint) { - printf(" (order-1)*P (affine):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth)); - if ((mp_cmp(&rx, &group->genx) != 0) - || (mp_cmp(&ry, &group->geny) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } -#endif - - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ec_GF2m_pt_mul_mont - (&order_1, &group->genx, &group->geny, &rx, &ry, group)); - if (ectestPrint) { - printf(" (order-1)*P (montgomery):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth)); - if ((mp_cmp(&rx, &group->genx) != 0) - || (mp_cmp(&ry, &group->geny) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } - -#ifdef ECL_ENABLE_GF2M_PROJ - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ec_GF2m_pt_mul_proj - (&order_1, &group->genx, &group->geny, &rx, &ry, group)); - if (ectestPrint) { - printf(" (order-1)*P (projective):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(group->meth->field_add(&ry, &rx, &ry, group->meth)); - if ((mp_cmp(&rx, &group->genx) != 0) - || (mp_cmp(&ry, &group->geny) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } -#endif - - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry)); - if (ectestPrint) { - printf(" (order-1)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth)); - if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } - - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry)); - if (ectestPrint) { - printf(" (order-1)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth)); - if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } - -#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ec_GF2m_pt_mul_aff - (&group->order, &group->genx, &group->geny, &rx, &ry, - group)); - if (ectestPrint) { - printf(" (order)*P (affine):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } -#endif - - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ec_GF2m_pt_mul_mont - (&group->order, &group->genx, &group->geny, &rx, &ry, - group)); - if (ectestPrint) { - printf(" (order)*P (montgomery):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } - -#ifdef ECL_ENABLE_GF2M_PROJ - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ec_GF2m_pt_mul_proj - (&group->order, &group->genx, &group->geny, &rx, &ry, - group)); - if (ectestPrint) { - printf(" (order)*P (projective):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } -#endif - - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry)); - if (ectestPrint) { - printf(" (order)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } - - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry)); - if (ectestPrint) { - printf(" (order)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GF2m_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } - - /* check that (order-1)P + (order-1)P + P == (order-1)P */ - MP_CHECKOK(ECPoints_mul - (group, &order_1, &order_1, &gx, &gy, &rx, &ry)); - MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry)); - if (ectestPrint) { - printf - (" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(ec_GF2m_add(&ry, &rx, &ry, group->meth)); - if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } - - /* test validate_point function */ - if (ECPoint_validate(group, &gx, &gy) != MP_YES) { - printf(" Error: validate point on base point failed.\n"); - res = MP_NO; - goto CLEANUP; - } - MP_CHECKOK(mp_add_d(&gy, 1, &ry)); - if (ECPoint_validate(group, &gx, &ry) != MP_NO) { - printf(" Error: validate point on invalid point passed.\n"); - res = MP_NO; - goto CLEANUP; - } - - if (ectestTime) { - /* compute random scalar */ - size = mpl_significant_bits(&group->meth->irr); - if (size < MP_OKAY) { - goto CLEANUP; - } - MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); - MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth)); - /* timed test */ - if (generic) { -#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF - M_TimeOperation(MP_CHECKOK - (ec_GF2m_pt_mul_aff - (&n, &group->genx, &group->geny, &rx, &ry, - group)), 100); -#endif - M_TimeOperation(MP_CHECKOK - (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), - 100); - M_TimeOperation(MP_CHECKOK - (ECPoints_mul - (group, &n, &n, &gx, &gy, &rx, &ry)), 100); - } else { - M_TimeOperation(MP_CHECKOK - (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), - 100); - M_TimeOperation(MP_CHECKOK - (ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)), - 100); - M_TimeOperation(MP_CHECKOK - (ECPoints_mul - (group, &n, &n, &gx, &gy, &rx, &ry)), 100); - } - } - - CLEANUP: - mp_clear(&one); - mp_clear(&order_1); - mp_clear(&gx); - mp_clear(&gy); - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&n); - if (res != MP_OKAY) { - printf(" Error: exiting with error value %i\n", res); - } - return res; -} - -/* Prints help information. */ -void -printUsage() -{ - printf("Usage: ecp_test [--print] [--time]\n"); - printf - (" --print Print out results of each point arithmetic test.\n"); - printf - (" --time Benchmark point operations and print results.\n"); -} - -/* Performs tests of elliptic curve cryptography over binary polynomial - * fields. If tests fail, then it prints an error message, aborts, and - * returns an error code. Otherwise, returns 0. */ -int -main(int argv, char **argc) -{ - - int ectestTime = 0; - int ectestPrint = 0; - int i; - ECGroup *group = NULL; - ECCurveParams *params = NULL; - mp_err res; - - /* read command-line arguments */ - for (i = 1; i < argv; i++) { - if ((strcasecmp(argc[i], "time") == 0) - || (strcasecmp(argc[i], "-time") == 0) - || (strcasecmp(argc[i], "--time") == 0)) { - ectestTime = 1; - } else if ((strcasecmp(argc[i], "print") == 0) - || (strcasecmp(argc[i], "-print") == 0) - || (strcasecmp(argc[i], "--print") == 0)) { - ectestPrint = 1; - } else { - printUsage(); - return 0; - } - } - - /* generic arithmetic tests */ - ECTEST_GENERIC_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1); - - /* specific arithmetic tests */ - ECTEST_NAMED_GF2M("NIST-K163", ECCurve_NIST_K163); - ECTEST_NAMED_GF2M("NIST-B163", ECCurve_NIST_B163); - ECTEST_NAMED_GF2M("NIST-K233", ECCurve_NIST_K233); - ECTEST_NAMED_GF2M("NIST-B233", ECCurve_NIST_B233); - ECTEST_NAMED_GF2M("NIST-K283", ECCurve_NIST_K283); - ECTEST_NAMED_GF2M("NIST-B283", ECCurve_NIST_B283); - ECTEST_NAMED_GF2M("NIST-K409", ECCurve_NIST_K409); - ECTEST_NAMED_GF2M("NIST-B409", ECCurve_NIST_B409); - ECTEST_NAMED_GF2M("NIST-K571", ECCurve_NIST_K571); - ECTEST_NAMED_GF2M("NIST-B571", ECCurve_NIST_B571); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V1", ECCurve_X9_62_CHAR2_PNB163V1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V2", ECCurve_X9_62_CHAR2_PNB163V2); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB163V3", ECCurve_X9_62_CHAR2_PNB163V3); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB176V1", ECCurve_X9_62_CHAR2_PNB176V1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V1", ECCurve_X9_62_CHAR2_TNB191V1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V2", ECCurve_X9_62_CHAR2_TNB191V2); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB191V3", ECCurve_X9_62_CHAR2_TNB191V3); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB208W1", ECCurve_X9_62_CHAR2_PNB208W1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V1", ECCurve_X9_62_CHAR2_TNB239V1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V2", ECCurve_X9_62_CHAR2_TNB239V2); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB239V3", ECCurve_X9_62_CHAR2_TNB239V3); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB272W1", ECCurve_X9_62_CHAR2_PNB272W1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB304W1", ECCurve_X9_62_CHAR2_PNB304W1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB359V1", ECCurve_X9_62_CHAR2_TNB359V1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2PNB368W1", ECCurve_X9_62_CHAR2_PNB368W1); - ECTEST_NAMED_GF2M("ANSI X9.62 C2TNB431R1", ECCurve_X9_62_CHAR2_TNB431R1); - ECTEST_NAMED_GF2M("SECT-113R1", ECCurve_SECG_CHAR2_113R1); - ECTEST_NAMED_GF2M("SECT-113R2", ECCurve_SECG_CHAR2_113R2); - ECTEST_NAMED_GF2M("SECT-131R1", ECCurve_SECG_CHAR2_131R1); - ECTEST_NAMED_GF2M("SECT-131R2", ECCurve_SECG_CHAR2_131R2); - ECTEST_NAMED_GF2M("SECT-163K1", ECCurve_SECG_CHAR2_163K1); - ECTEST_NAMED_GF2M("SECT-163R1", ECCurve_SECG_CHAR2_163R1); - ECTEST_NAMED_GF2M("SECT-163R2", ECCurve_SECG_CHAR2_163R2); - ECTEST_NAMED_GF2M("SECT-193R1", ECCurve_SECG_CHAR2_193R1); - ECTEST_NAMED_GF2M("SECT-193R2", ECCurve_SECG_CHAR2_193R2); - ECTEST_NAMED_GF2M("SECT-233K1", ECCurve_SECG_CHAR2_233K1); - ECTEST_NAMED_GF2M("SECT-233R1", ECCurve_SECG_CHAR2_233R1); - ECTEST_NAMED_GF2M("SECT-239K1", ECCurve_SECG_CHAR2_239K1); - ECTEST_NAMED_GF2M("SECT-283K1", ECCurve_SECG_CHAR2_283K1); - ECTEST_NAMED_GF2M("SECT-283R1", ECCurve_SECG_CHAR2_283R1); - ECTEST_NAMED_GF2M("SECT-409K1", ECCurve_SECG_CHAR2_409K1); - ECTEST_NAMED_GF2M("SECT-409R1", ECCurve_SECG_CHAR2_409R1); - ECTEST_NAMED_GF2M("SECT-571K1", ECCurve_SECG_CHAR2_571K1); - ECTEST_NAMED_GF2M("SECT-571R1", ECCurve_SECG_CHAR2_571R1); - ECTEST_NAMED_GF2M("WTLS-1 (113)", ECCurve_WTLS_1); - ECTEST_NAMED_GF2M("WTLS-3 (163)", ECCurve_WTLS_3); - ECTEST_NAMED_GF2M("WTLS-4 (113)", ECCurve_WTLS_4); - ECTEST_NAMED_GF2M("WTLS-5 (163)", ECCurve_WTLS_5); - ECTEST_NAMED_GF2M("WTLS-10 (233)", ECCurve_WTLS_10); - ECTEST_NAMED_GF2M("WTLS-11 (233)", ECCurve_WTLS_11); - - CLEANUP: - EC_FreeCurveParams(params); - ECGroup_free(group); - if (res != MP_OKAY) { - printf("Error: exiting with error value %i\n", res); - } - return res; -} diff --git a/nss/lib/freebl/ecl/tests/ec_naft.c b/nss/lib/freebl/ecl/tests/ec_naft.c index 833daea..61ef15c 100644 --- a/nss/lib/freebl/ecl/tests/ec_naft.c +++ b/nss/lib/freebl/ecl/tests/ec_naft.c @@ -14,7 +14,7 @@ #include <sys/time.h> #include <sys/resource.h> -/* Returns 2^e as an integer. This is meant to be used for small powers of +/* Returns 2^e as an integer. This is meant to be used for small powers of * two. */ int ec_twoTo(int e); @@ -22,96 +22,100 @@ int ec_twoTo(int e); #define BITSIZE 160 /* Time k repetitions of operation op. */ -#define M_TimeOperation(op, k) { \ - double dStart, dNow, dUserTime; \ - struct rusage ru; \ - int i; \ - getrusage(RUSAGE_SELF, &ru); \ - dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - for (i = 0; i < k; i++) { \ - { op; } \ - }; \ - getrusage(RUSAGE_SELF, &ru); \ - dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - dUserTime = dNow-dStart; \ - if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \ -} - -/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D. +#define M_TimeOperation(op, k) \ + { \ + double dStart, dNow, dUserTime; \ + struct rusage ru; \ + int i; \ + getrusage(RUSAGE_SELF, &ru); \ + dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \ + for (i = 0; i < k; i++) { \ + { \ + op; \ + } \ + }; \ + getrusage(RUSAGE_SELF, &ru); \ + dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \ + dUserTime = dNow - dStart; \ + if (dUserTime) \ + printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \ + } + +/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D. * Hankerson, J. Hernandez and A. Menezes, "Software implementation of * elliptic curve cryptography over binary fields", Proc. CHES 2000. */ mp_err main(void) { - signed char naf[BITSIZE + 1]; - ECGroup *group = NULL; - mp_int k; - mp_int *scalar; - int i, count; - int res; - int w = 5; - char s[1000]; - - /* Get a 160 bit scalar to compute wNAF from */ - group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1); - scalar = &group->genx; - - /* Compute wNAF representation of scalar */ - ec_compute_wNAF(naf, BITSIZE, scalar, w); - - /* Verify correctness of representation */ - mp_init(&k); /* init k to 0 */ - - for (i = BITSIZE; i >= 0; i--) { - mp_add(&k, &k, &k); - /* digits in mp_???_d are unsigned */ - if (naf[i] >= 0) { - mp_add_d(&k, naf[i], &k); - } else { - mp_sub_d(&k, -naf[i], &k); - } - } - - if (mp_cmp(&k, scalar) != 0) { - printf("Error: incorrect NAF value.\n"); - MP_CHECKOK(mp_toradix(&k, s, 16)); - printf("NAF value %s\n", s); - MP_CHECKOK(mp_toradix(scalar, s, 16)); - printf("original value %s\n", s); - goto CLEANUP; - } - - /* Verify digits of representation are valid */ - for (i = 0; i <= BITSIZE; i++) { - if (naf[i] % 2 == 0 && naf[i] != 0) { - printf("Error: Even non-zero digit found.\n"); - goto CLEANUP; - } - if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) { - printf("Error: Magnitude of naf digit too large.\n"); - goto CLEANUP; - } - } - - /* Verify sparsity of representation */ - count = w - 1; - for (i = 0; i <= BITSIZE; i++) { - if (naf[i] != 0) { - if (count < w - 1) { - printf("Error: Sparsity failed.\n"); - goto CLEANUP; - } - count = 0; - } else - count++; - } - - /* Check timing */ - M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000); - - printf("Test passed.\n"); - CLEANUP: - ECGroup_free(group); - return MP_OKAY; + signed char naf[BITSIZE + 1]; + ECGroup *group = NULL; + mp_int k; + mp_int *scalar; + int i, count; + int res; + int w = 5; + char s[1000]; + + /* Get a 160 bit scalar to compute wNAF from */ + group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1); + scalar = &group->genx; + + /* Compute wNAF representation of scalar */ + ec_compute_wNAF(naf, BITSIZE, scalar, w); + + /* Verify correctness of representation */ + mp_init(&k); /* init k to 0 */ + + for (i = BITSIZE; i >= 0; i--) { + mp_add(&k, &k, &k); + /* digits in mp_???_d are unsigned */ + if (naf[i] >= 0) { + mp_add_d(&k, naf[i], &k); + } else { + mp_sub_d(&k, -naf[i], &k); + } + } + + if (mp_cmp(&k, scalar) != 0) { + printf("Error: incorrect NAF value.\n"); + MP_CHECKOK(mp_toradix(&k, s, 16)); + printf("NAF value %s\n", s); + MP_CHECKOK(mp_toradix(scalar, s, 16)); + printf("original value %s\n", s); + goto CLEANUP; + } + + /* Verify digits of representation are valid */ + for (i = 0; i <= BITSIZE; i++) { + if (naf[i] % 2 == 0 && naf[i] != 0) { + printf("Error: Even non-zero digit found.\n"); + goto CLEANUP; + } + if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) { + printf("Error: Magnitude of naf digit too large.\n"); + goto CLEANUP; + } + } + + /* Verify sparsity of representation */ + count = w - 1; + for (i = 0; i <= BITSIZE; i++) { + if (naf[i] != 0) { + if (count < w - 1) { + printf("Error: Sparsity failed.\n"); + goto CLEANUP; + } + count = 0; + } else + count++; + } + + /* Check timing */ + M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000); + + printf("Test passed.\n"); +CLEANUP: + ECGroup_free(group); + return MP_OKAY; } diff --git a/nss/lib/freebl/ecl/tests/ecp_fpt.c b/nss/lib/freebl/ecl/tests/ecp_fpt.c deleted file mode 100644 index 3c91796..0000000 --- a/nss/lib/freebl/ecl/tests/ecp_fpt.c +++ /dev/null @@ -1,1088 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "ecp_fp.h" -#include "mpprime.h" - -#include <stdio.h> -#include <time.h> -#include <sys/time.h> -#include <sys/resource.h> - -/* Time k repetitions of operation op. */ -#define M_TimeOperation(op, k) { \ - double dStart, dNow, dUserTime; \ - struct rusage ru; \ - int i; \ - getrusage(RUSAGE_SELF, &ru); \ - dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - for (i = 0; i < k; i++) { \ - { op; } \ - }; \ - getrusage(RUSAGE_SELF, &ru); \ - dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - dUserTime = dNow-dStart; \ - if (dUserTime) printf(" %-45s\n k: %6i, t: %6.2f sec, k/t: %6.2f ops/sec\n", #op, k, dUserTime, k/dUserTime); \ -} - -/* Test curve using specific floating point field arithmetic. */ -#define M_TestCurve(name_c, name) { \ - printf("Testing %s using specific floating point implementation...\n", name_c); \ - ECGroup_free(ecgroup); \ - ecgroup = ECGroup_fromName(name); \ - if (ecgroup == NULL) { \ - printf(" Warning: could not construct group.\n"); \ - printf("%s failed.\n", name_c); \ - res = MP_NO; \ - goto CLEANUP; \ - } else { \ - MP_CHECKOK( testCurve(ecgroup)); \ - printf("%s passed.\n", name_c); \ - } \ -} - -/* Outputs a floating point double (currently not used) */ -void -d_output(const double *u, int len, char *name, const EC_group_fp * group) -{ - int i; - - printf("%s: ", name); - for (i = 0; i < len; i++) { - printf("+ %.2f * 2^%i ", u[i] / ecfp_exp[i], - group->doubleBitSize * i); - } - printf("\n"); -} - -/* Tests a point p in Jacobian coordinates, comparing against the - * expected affine result (x, y). */ -mp_err -testJacPoint(ecfp_jac_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) -{ - char s[1000]; - mp_int rx, ry, rz; - mp_err res = MP_OKAY; - - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&rz) = 0; - - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&rz)); - - ecfp_fp2i(&rx, p->x, ecgroup); - ecfp_fp2i(&ry, p->y, ecgroup); - ecfp_fp2i(&rz, p->z, ecgroup); - - /* convert result R to affine coordinates */ - ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); - - /* Compare to expected result */ - if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { - printf(" Error: Jacobian Floating Point Incorrect.\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("floating point result\nrx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - MP_CHECKOK(mp_toradix(x, s, 16)); - printf("integer result\nx %s\n", s); - MP_CHECKOK(mp_toradix(y, s, 16)); - printf("y %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - CLEANUP: - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&rz); - - return res; -} - -/* Tests a point p in Chudnovsky Jacobian coordinates, comparing against - * the expected affine result (x, y). */ -mp_err -testChudPoint(ecfp_chud_pt * p, mp_int *x, mp_int *y, ECGroup *ecgroup) -{ - - char s[1000]; - mp_int rx, ry, rz, rz2, rz3, test; - mp_err res = MP_OKAY; - - /* Initialization */ - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&rz) = 0; - MP_DIGITS(&rz2) = 0; - MP_DIGITS(&rz3) = 0; - MP_DIGITS(&test) = 0; - - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(mp_init(&rz2)); - MP_CHECKOK(mp_init(&rz3)); - MP_CHECKOK(mp_init(&test)); - - /* Convert to integers */ - ecfp_fp2i(&rx, p->x, ecgroup); - ecfp_fp2i(&ry, p->y, ecgroup); - ecfp_fp2i(&rz, p->z, ecgroup); - ecfp_fp2i(&rz2, p->z2, ecgroup); - ecfp_fp2i(&rz3, p->z3, ecgroup); - - /* Verify z2, z3 are valid */ - mp_sqrmod(&rz, &ecgroup->meth->irr, &test); - if (mp_cmp(&test, &rz2) != 0) { - printf(" Error: rzp2 not valid\n"); - res = MP_NO; - goto CLEANUP; - } - mp_mulmod(&test, &rz, &ecgroup->meth->irr, &test); - if (mp_cmp(&test, &rz3) != 0) { - printf(" Error: rzp2 not valid\n"); - res = MP_NO; - goto CLEANUP; - } - - /* convert result R to affine coordinates */ - ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); - - /* Compare against expected result */ - if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { - printf(" Error: Chudnovsky Floating Point Incorrect.\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("floating point result\nrx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - MP_CHECKOK(mp_toradix(x, s, 16)); - printf("integer result\nx %s\n", s); - MP_CHECKOK(mp_toradix(y, s, 16)); - printf("y %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - CLEANUP: - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&rz); - mp_clear(&rz2); - mp_clear(&rz3); - mp_clear(&test); - - return res; -} - -/* Tests a point p in Modified Jacobian coordinates, comparing against the - * expected affine result (x, y). */ -mp_err -testJmPoint(ecfp_jm_pt * r, mp_int *x, mp_int *y, ECGroup *ecgroup) -{ - - char s[1000]; - mp_int rx, ry, rz, raz4, test; - mp_err res = MP_OKAY; - - /* Initialization */ - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&rz) = 0; - MP_DIGITS(&raz4) = 0; - MP_DIGITS(&test) = 0; - - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(mp_init(&raz4)); - MP_CHECKOK(mp_init(&test)); - - /* Convert to integer */ - ecfp_fp2i(&rx, r->x, ecgroup); - ecfp_fp2i(&ry, r->y, ecgroup); - ecfp_fp2i(&rz, r->z, ecgroup); - ecfp_fp2i(&raz4, r->az4, ecgroup); - - /* Verify raz4 = rz^4 * a */ - mp_sqrmod(&rz, &ecgroup->meth->irr, &test); - mp_sqrmod(&test, &ecgroup->meth->irr, &test); - mp_mulmod(&test, &ecgroup->curvea, &ecgroup->meth->irr, &test); - if (mp_cmp(&test, &raz4) != 0) { - printf(" Error: a*z^4 not valid\n"); - MP_CHECKOK(mp_toradix(&ecgroup->curvea, s, 16)); - printf("a %s\n", s); - MP_CHECKOK(mp_toradix(&rz, s, 16)); - printf("rz %s\n", s); - MP_CHECKOK(mp_toradix(&raz4, s, 16)); - printf("raz4 %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - /* convert result R to affine coordinates */ - ec_GFp_pt_jac2aff(&rx, &ry, &rz, &rx, &ry, ecgroup); - - /* Compare against expected result */ - if ((mp_cmp(&rx, x) != 0) || (mp_cmp(&ry, y) != 0)) { - printf(" Error: Modified Jacobian Floating Point Incorrect.\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("floating point result\nrx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - MP_CHECKOK(mp_toradix(x, s, 16)); - printf("integer result\nx %s\n", s); - MP_CHECKOK(mp_toradix(y, s, 16)); - printf("y %s\n", s); - res = MP_NO; - goto CLEANUP; - } - CLEANUP: - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&rz); - mp_clear(&raz4); - mp_clear(&test); - - return res; -} - -/* Tests point addition of Jacobian + Affine -> Jacobian */ -mp_err -testPointAddJacAff(ECGroup *ecgroup) -{ - mp_err res; - mp_int pz, rx2, ry2, rz2; - ecfp_jac_pt p, r; - ecfp_aff_pt q; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - /* Init */ - MP_DIGITS(&pz) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&rz2) = 0; - MP_CHECKOK(mp_init(&pz)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&rz2)); - - MP_CHECKOK(mp_set_int(&pz, 5)); - - /* Set p */ - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(p.z, &pz, ecgroup); - /* Set q */ - ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); - ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); - - /* Do calculations */ - group->pt_add_jac_aff(&p, &q, &r, group); - - /* Do calculation in integer to compare against */ - MP_CHECKOK(ec_GFp_pt_add_jac_aff - (&ecgroup->genx, &ecgroup->geny, &pz, &ecgroup->geny, - &ecgroup->genx, &rx2, &ry2, &rz2, ecgroup)); - /* convert result R to affine coordinates */ - ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); - - MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Addition - Jacobian & Affine\n"); - else - printf("TEST FAILED - Point Addition - Jacobian & Affine\n"); - - mp_clear(&pz); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&rz2); - - return res; -} - -/* Tests point addition in Jacobian coordinates */ -mp_err -testPointAddJac(ECGroup *ecgroup) -{ - mp_err res; - mp_int pz, qz, qx, qy, rx2, ry2, rz2; - ecfp_jac_pt p, q, r; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - /* Init */ - MP_DIGITS(&pz) = 0; - MP_DIGITS(&qx) = 0; - MP_DIGITS(&qy) = 0; - MP_DIGITS(&qz) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&rz2) = 0; - MP_CHECKOK(mp_init(&pz)); - MP_CHECKOK(mp_init(&qx)); - MP_CHECKOK(mp_init(&qy)); - MP_CHECKOK(mp_init(&qz)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&rz2)); - - MP_CHECKOK(mp_set_int(&pz, 5)); - MP_CHECKOK(mp_set_int(&qz, 105)); - - /* Set p */ - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(p.z, &pz, ecgroup); - /* Set q */ - ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); - ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); - ecfp_i2fp(q.z, &qz, ecgroup); - - /* Do calculations */ - group->pt_add_jac(&p, &q, &r, group); - - /* Do calculation in integer to compare against */ - ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, - ecgroup); - MP_CHECKOK(ec_GFp_pt_add_jac_aff - (&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, &rx2, &ry2, - &rz2, ecgroup)); - /* convert result R to affine coordinates */ - ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); - - MP_CHECKOK(testJacPoint(&r, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Addition - Jacobian\n"); - else - printf("TEST FAILED - Point Addition - Jacobian\n"); - - mp_clear(&pz); - mp_clear(&qx); - mp_clear(&qy); - mp_clear(&qz); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&rz2); - - return res; -} - -/* Tests point addition in Chudnovsky Jacobian Coordinates */ -mp_err -testPointAddChud(ECGroup *ecgroup) -{ - mp_err res; - mp_int rx2, ry2, ix, iy, iz, test, pz, qx, qy, qz; - ecfp_chud_pt p, q, r; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - MP_DIGITS(&qx) = 0; - MP_DIGITS(&qy) = 0; - MP_DIGITS(&qz) = 0; - MP_DIGITS(&pz) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&ix) = 0; - MP_DIGITS(&iy) = 0; - MP_DIGITS(&iz) = 0; - MP_DIGITS(&test) = 0; - - MP_CHECKOK(mp_init(&qx)); - MP_CHECKOK(mp_init(&qy)); - MP_CHECKOK(mp_init(&qz)); - MP_CHECKOK(mp_init(&pz)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&ix)); - MP_CHECKOK(mp_init(&iy)); - MP_CHECKOK(mp_init(&iz)); - MP_CHECKOK(mp_init(&test)); - - /* Test Chudnovsky form addition */ - /* Set p */ - MP_CHECKOK(mp_set_int(&pz, 5)); - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(p.z, &pz, ecgroup); - mp_sqrmod(&pz, &ecgroup->meth->irr, &test); - ecfp_i2fp(p.z2, &test, ecgroup); - mp_mulmod(&test, &pz, &ecgroup->meth->irr, &test); - ecfp_i2fp(p.z3, &test, ecgroup); - - /* Set q */ - MP_CHECKOK(mp_set_int(&qz, 105)); - ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); - ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); - ecfp_i2fp(q.z, &qz, ecgroup); - mp_sqrmod(&qz, &ecgroup->meth->irr, &test); - ecfp_i2fp(q.z2, &test, ecgroup); - mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); - ecfp_i2fp(q.z3, &test, ecgroup); - - group->pt_add_chud(&p, &q, &r, group); - - /* Calculate addition to compare against */ - ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, - ecgroup); - ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, - &ix, &iy, &iz, ecgroup); - ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); - - MP_CHECKOK(testChudPoint(&r, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Addition - Chudnovsky Jacobian\n"); - else - printf("TEST FAILED - Point Addition - Chudnovsky Jacobian\n"); - - mp_clear(&qx); - mp_clear(&qy); - mp_clear(&qz); - mp_clear(&pz); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&ix); - mp_clear(&iy); - mp_clear(&iz); - mp_clear(&test); - - return res; -} - -/* Tests point addition in Modified Jacobian + Chudnovsky Jacobian -> - * Modified Jacobian coordinates. */ -mp_err -testPointAddJmChud(ECGroup *ecgroup) -{ - mp_err res; - mp_int rx2, ry2, ix, iy, iz, test, pz, paz4, qx, qy, qz; - ecfp_chud_pt q; - ecfp_jm_pt p, r; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - MP_DIGITS(&qx) = 0; - MP_DIGITS(&qy) = 0; - MP_DIGITS(&qz) = 0; - MP_DIGITS(&pz) = 0; - MP_DIGITS(&paz4) = 0; - MP_DIGITS(&iz) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&ix) = 0; - MP_DIGITS(&iy) = 0; - MP_DIGITS(&iz) = 0; - MP_DIGITS(&test) = 0; - - MP_CHECKOK(mp_init(&qx)); - MP_CHECKOK(mp_init(&qy)); - MP_CHECKOK(mp_init(&qz)); - MP_CHECKOK(mp_init(&pz)); - MP_CHECKOK(mp_init(&paz4)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&ix)); - MP_CHECKOK(mp_init(&iy)); - MP_CHECKOK(mp_init(&iz)); - MP_CHECKOK(mp_init(&test)); - - /* Test Modified Jacobian form addition */ - /* Set p */ - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); - /* paz4 = az^4 */ - MP_CHECKOK(mp_set_int(&pz, 5)); - mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); - mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); - mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); - ecfp_i2fp(p.z, &pz, ecgroup); - ecfp_i2fp(p.az4, &paz4, ecgroup); - - /* Set q */ - MP_CHECKOK(mp_set_int(&qz, 105)); - ecfp_i2fp(q.x, &ecgroup->geny, ecgroup); - ecfp_i2fp(q.y, &ecgroup->genx, ecgroup); - ecfp_i2fp(q.z, &qz, ecgroup); - mp_sqrmod(&qz, &ecgroup->meth->irr, &test); - ecfp_i2fp(q.z2, &test, ecgroup); - mp_mulmod(&test, &qz, &ecgroup->meth->irr, &test); - ecfp_i2fp(q.z3, &test, ecgroup); - - /* Do calculation */ - group->pt_add_jm_chud(&p, &q, &r, group); - - /* Calculate addition to compare against */ - ec_GFp_pt_jac2aff(&ecgroup->geny, &ecgroup->genx, &qz, &qx, &qy, - ecgroup); - ec_GFp_pt_add_jac_aff(&ecgroup->genx, &ecgroup->geny, &pz, &qx, &qy, - &ix, &iy, &iz, ecgroup); - ec_GFp_pt_jac2aff(&ix, &iy, &iz, &rx2, &ry2, ecgroup); - - MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf - (" Test Passed - Point Addition - Modified & Chudnovsky Jacobian\n"); - else - printf - ("TEST FAILED - Point Addition - Modified & Chudnovsky Jacobian\n"); - - mp_clear(&qx); - mp_clear(&qy); - mp_clear(&qz); - mp_clear(&pz); - mp_clear(&paz4); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&ix); - mp_clear(&iy); - mp_clear(&iz); - mp_clear(&test); - - return res; -} - -/* Tests point doubling in Modified Jacobian coordinates */ -mp_err -testPointDoubleJm(ECGroup *ecgroup) -{ - mp_err res; - mp_int pz, paz4, rx2, ry2, rz2, raz4; - ecfp_jm_pt p, r; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - MP_DIGITS(&pz) = 0; - MP_DIGITS(&paz4) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&rz2) = 0; - MP_DIGITS(&raz4) = 0; - - MP_CHECKOK(mp_init(&pz)); - MP_CHECKOK(mp_init(&paz4)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&rz2)); - MP_CHECKOK(mp_init(&raz4)); - - /* Set p */ - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); - - /* paz4 = az^4 */ - MP_CHECKOK(mp_set_int(&pz, 5)); - mp_sqrmod(&pz, &ecgroup->meth->irr, &paz4); - mp_sqrmod(&paz4, &ecgroup->meth->irr, &paz4); - mp_mulmod(&paz4, &ecgroup->curvea, &ecgroup->meth->irr, &paz4); - - ecfp_i2fp(p.z, &pz, ecgroup); - ecfp_i2fp(p.az4, &paz4, ecgroup); - - group->pt_dbl_jm(&p, &r, group); - - M_TimeOperation(group->pt_dbl_jm(&p, &r, group), 100000); - - /* Calculate doubling to compare against */ - ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, - &rz2, ecgroup); - ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); - - /* Do comparison and check az^4 */ - MP_CHECKOK(testJmPoint(&r, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Doubling - Modified Jacobian\n"); - else - printf("TEST FAILED - Point Doubling - Modified Jacobian\n"); - mp_clear(&pz); - mp_clear(&paz4); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&rz2); - mp_clear(&raz4); - - return res; - -} - -/* Tests point doubling in Chudnovsky Jacobian coordinates */ -mp_err -testPointDoubleChud(ECGroup *ecgroup) -{ - mp_err res; - mp_int px, py, pz, rx2, ry2, rz2; - ecfp_aff_pt p; - ecfp_chud_pt p2; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&rz2) = 0; - MP_DIGITS(&px) = 0; - MP_DIGITS(&py) = 0; - MP_DIGITS(&pz) = 0; - - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&rz2)); - MP_CHECKOK(mp_init(&px)); - MP_CHECKOK(mp_init(&py)); - MP_CHECKOK(mp_init(&pz)); - - /* Set p2 = 2P */ - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); - - group->pt_dbl_aff2chud(&p, &p2, group); - - /* Calculate doubling to compare against */ - MP_CHECKOK(mp_set_int(&pz, 1)); - ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, - &rz2, ecgroup); - ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); - - /* Do comparison and check az^4 */ - MP_CHECKOK(testChudPoint(&p2, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Doubling - Chudnovsky Jacobian\n"); - else - printf("TEST FAILED - Point Doubling - Chudnovsky Jacobian\n"); - - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&rz2); - mp_clear(&px); - mp_clear(&py); - mp_clear(&pz); - - return res; -} - -/* Test point doubling in Jacobian coordinates */ -mp_err -testPointDoubleJac(ECGroup *ecgroup) -{ - mp_err res; - mp_int pz, rx, ry, rz, rx2, ry2, rz2; - ecfp_jac_pt p, p2; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - MP_DIGITS(&pz) = 0; - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&rz) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&rz2) = 0; - - MP_CHECKOK(mp_init(&pz)); - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&rz)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&rz2)); - - MP_CHECKOK(mp_set_int(&pz, 5)); - - /* Set p2 = 2P */ - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(p.z, &pz, ecgroup); - ecfp_i2fp(group->curvea, &ecgroup->curvea, ecgroup); - - group->pt_dbl_jac(&p, &p2, group); - M_TimeOperation(group->pt_dbl_jac(&p, &p2, group), 100000); - - /* Calculate doubling to compare against */ - ec_GFp_pt_dbl_jac(&ecgroup->genx, &ecgroup->geny, &pz, &rx2, &ry2, - &rz2, ecgroup); - ec_GFp_pt_jac2aff(&rx2, &ry2, &rz2, &rx2, &ry2, ecgroup); - - /* Do comparison */ - MP_CHECKOK(testJacPoint(&p2, &rx2, &ry2, ecgroup)); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Doubling - Jacobian\n"); - else - printf("TEST FAILED - Point Doubling - Jacobian\n"); - - mp_clear(&pz); - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&rz); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&rz2); - - return res; -} - -/* Tests a point multiplication (various algorithms) */ -mp_err -testPointMul(ECGroup *ecgroup) -{ - mp_err res; - char s[1000]; - mp_int rx, ry, order_1; - - /* Init */ - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&order_1) = 0; - - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&order_1)); - - MP_CHECKOK(mp_set_int(&order_1, 1)); - MP_CHECKOK(mp_sub(&ecgroup->order, &order_1, &order_1)); - - /* Test Algorithm 1: Jacobian-Affine Double & Add */ - ec_GFp_pt_mul_jac_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, - &ry, ecgroup); - MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); - if ((mp_cmp(&rx, &ecgroup->genx) != 0) - || (mp_cmp(&ry, &ecgroup->geny) != 0)) { - printf - (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected (- base point)).\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("rx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - ec_GFp_pt_mul_jac_fp(&ecgroup->order, &ecgroup->genx, &ecgroup->geny, - &rx, &ry, ecgroup); - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf - (" Error: ec_GFp_pt_mul_jac_fp invalid result (expected point at infinity.\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("rx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - /* Test Algorithm 2: 4-bit Window in Jacobian */ - ec_GFp_point_mul_jac_4w_fp(&order_1, &ecgroup->genx, &ecgroup->geny, - &rx, &ry, ecgroup); - MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); - if ((mp_cmp(&rx, &ecgroup->genx) != 0) - || (mp_cmp(&ry, &ecgroup->geny) != 0)) { - printf - (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected (- base point)).\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("rx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - ec_GFp_point_mul_jac_4w_fp(&ecgroup->order, &ecgroup->genx, - &ecgroup->geny, &rx, &ry, ecgroup); - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf - (" Error: ec_GFp_point_mul_jac_4w_fp invalid result (expected point at infinity.\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("rx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - /* Test Algorithm 3: wNAF with modified Jacobian coordinates */ - ec_GFp_point_mul_wNAF_fp(&order_1, &ecgroup->genx, &ecgroup->geny, &rx, - &ry, ecgroup); - MP_CHECKOK(ecgroup->meth->field_neg(&ry, &ry, ecgroup->meth)); - if ((mp_cmp(&rx, &ecgroup->genx) != 0) - || (mp_cmp(&ry, &ecgroup->geny) != 0)) { - printf - (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected (- base point)).\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("rx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - ec_GFp_point_mul_wNAF_fp(&ecgroup->order, &ecgroup->genx, - &ecgroup->geny, &rx, &ry, ecgroup); - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf - (" Error: ec_GFp_pt_mul_wNAF_fp invalid result (expected point at infinity.\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf("rx %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf("ry %s\n", s); - res = MP_NO; - goto CLEANUP; - } - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Multiplication\n"); - else - printf("TEST FAILED - Point Multiplication\n"); - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&order_1); - - return res; -} - -/* Tests point multiplication with a random scalar repeatedly, comparing - * for consistency within different algorithms. */ -mp_err -testPointMulRandom(ECGroup *ecgroup) -{ - mp_err res; - mp_int rx, ry, rx2, ry2, n; - int i, size; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&rx2) = 0; - MP_DIGITS(&ry2) = 0; - MP_DIGITS(&n) = 0; - - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&rx2)); - MP_CHECKOK(mp_init(&ry2)); - MP_CHECKOK(mp_init(&n)); - - for (i = 0; i < 100; i++) { - /* compute random scalar */ - size = mpl_significant_bits(&ecgroup->meth->irr); - if (size < MP_OKAY) { - res = MP_NO; - goto CLEANUP; - } - MP_CHECKOK(mpp_random_size(&n, group->orderBitSize)); - MP_CHECKOK(mp_mod(&n, &ecgroup->order, &n)); - - ec_GFp_pt_mul_jac(&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, - ecgroup); - ec_GFp_pt_mul_jac_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx2, - &ry2, ecgroup); - - if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { - printf - (" Error: different results for Point Multiplication - Double & Add.\n"); - res = MP_NO; - goto CLEANUP; - } - - ec_GFp_point_mul_wNAF_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, - &ry, ecgroup); - if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { - printf - (" Error: different results for Point Multiplication - wNAF.\n"); - res = MP_NO; - goto CLEANUP; - } - - ec_GFp_point_mul_jac_4w_fp(&n, &ecgroup->genx, &ecgroup->geny, &rx, - &ry, ecgroup); - if ((mp_cmp(&rx, &rx2) != 0) || (mp_cmp(&ry, &ry2) != 0)) { - printf - (" Error: different results for Point Multiplication - 4 bit window.\n"); - res = MP_NO; - goto CLEANUP; - } - - } - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Random Multiplication\n"); - else - printf("TEST FAILED - Point Random Multiplication\n"); - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&rx2); - mp_clear(&ry2); - mp_clear(&n); - - return res; -} - -/* Tests the time required for a point multiplication */ -mp_err -testPointMulTime(ECGroup *ecgroup) -{ - mp_err res = MP_OKAY; - mp_int rx, ry, n; - int size; - - MP_DIGITS(&rx) = 0; - MP_DIGITS(&ry) = 0; - MP_DIGITS(&n) = 0; - - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&n)); - - /* compute random scalar */ - size = mpl_significant_bits(&ecgroup->meth->irr); - if (size < MP_OKAY) { - res = MP_NO; - goto CLEANUP; - } - - MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); - MP_CHECKOK(ecgroup->meth->field_mod(&n, &n, ecgroup->meth)); - - M_TimeOperation(ec_GFp_pt_mul_jac_fp - (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, - ecgroup), 1000); - - M_TimeOperation(ec_GFp_point_mul_jac_4w_fp - (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, - ecgroup), 1000); - - M_TimeOperation(ec_GFp_point_mul_wNAF_fp - (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, - ecgroup), 1000); - - M_TimeOperation(ec_GFp_pt_mul_jac - (&n, &ecgroup->genx, &ecgroup->geny, &rx, &ry, - ecgroup), 100); - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Point Multiplication Timing\n"); - else - printf("TEST FAILED - Point Multiplication Timing\n"); - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&n); - - return res; -} - -/* Tests pre computation of Chudnovsky Jacobian points used in wNAF form */ -mp_err -testPreCompute(ECGroup *ecgroup) -{ - ecfp_chud_pt precomp[16]; - ecfp_aff_pt p; - EC_group_fp *group = (EC_group_fp *) ecgroup->extra1; - int i; - mp_err res; - - mp_int x, y, ny, x2, y2; - - MP_DIGITS(&x) = 0; - MP_DIGITS(&y) = 0; - MP_DIGITS(&ny) = 0; - MP_DIGITS(&x2) = 0; - MP_DIGITS(&y2) = 0; - - MP_CHECKOK(mp_init(&x)); - MP_CHECKOK(mp_init(&y)); - MP_CHECKOK(mp_init(&ny)); - MP_CHECKOK(mp_init(&x2)); - MP_CHECKOK(mp_init(&y2)); - - ecfp_i2fp(p.x, &ecgroup->genx, ecgroup); - ecfp_i2fp(p.y, &ecgroup->geny, ecgroup); - ecfp_i2fp(group->curvea, &(ecgroup->curvea), ecgroup); - - /* Perform precomputation */ - group->precompute_chud(precomp, &p, group); - - M_TimeOperation(group->precompute_chud(precomp, &p, group), 10000); - - /* Calculate addition to compare against */ - MP_CHECKOK(mp_copy(&ecgroup->genx, &x)); - MP_CHECKOK(mp_copy(&ecgroup->geny, &y)); - MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); - - ec_GFp_pt_dbl_aff(&x, &y, &x2, &y2, ecgroup); - - for (i = 0; i < 8; i++) { - MP_CHECKOK(testChudPoint(&precomp[8 + i], &x, &y, ecgroup)); - MP_CHECKOK(testChudPoint(&precomp[7 - i], &x, &ny, ecgroup)); - ec_GFp_pt_add_aff(&x, &y, &x2, &y2, &x, &y, ecgroup); - MP_CHECKOK(ecgroup->meth->field_neg(&y, &ny, ecgroup->meth)); - } - - CLEANUP: - if (res == MP_OKAY) - printf(" Test Passed - Precomputation\n"); - else - printf("TEST FAILED - Precomputation\n"); - - mp_clear(&x); - mp_clear(&y); - mp_clear(&ny); - mp_clear(&x2); - mp_clear(&y2); - return res; -} - -/* Given a curve using floating point arithmetic, test it. This method - * specifies which of the above tests to run. */ -mp_err -testCurve(ECGroup *ecgroup) -{ - int res = MP_OKAY; - - MP_CHECKOK(testPointAddJacAff(ecgroup)); - MP_CHECKOK(testPointAddJac(ecgroup)); - MP_CHECKOK(testPointAddChud(ecgroup)); - MP_CHECKOK(testPointAddJmChud(ecgroup)); - MP_CHECKOK(testPointDoubleJac(ecgroup)); - MP_CHECKOK(testPointDoubleChud(ecgroup)); - MP_CHECKOK(testPointDoubleJm(ecgroup)); - MP_CHECKOK(testPreCompute(ecgroup)); - MP_CHECKOK(testPointMul(ecgroup)); - MP_CHECKOK(testPointMulRandom(ecgroup)); - MP_CHECKOK(testPointMulTime(ecgroup)); - CLEANUP: - return res; -} - -/* Tests a number of curves optimized using floating point arithmetic */ -int -main(void) -{ - mp_err res = MP_OKAY; - ECGroup *ecgroup = NULL; - - /* specific arithmetic tests */ - M_TestCurve("SECG-160R1", ECCurve_SECG_PRIME_160R1); - M_TestCurve("SECG-192R1", ECCurve_SECG_PRIME_192R1); - M_TestCurve("SEGC-224R1", ECCurve_SECG_PRIME_224R1); - - CLEANUP: - ECGroup_free(ecgroup); - if (res != MP_OKAY) { - printf("Error: exiting with error value %i\n", res); - } - return res; -} diff --git a/nss/lib/freebl/ecl/tests/ecp_test.c b/nss/lib/freebl/ecl/tests/ecp_test.c index e9a448e..dcec4d7 100644 --- a/nss/lib/freebl/ecl/tests/ecp_test.c +++ b/nss/lib/freebl/ecl/tests/ecp_test.c @@ -17,336 +17,322 @@ #include <sys/resource.h> /* Time k repetitions of operation op. */ -#define M_TimeOperation(op, k) { \ - double dStart, dNow, dUserTime; \ - struct rusage ru; \ - int i; \ - getrusage(RUSAGE_SELF, &ru); \ - dStart = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - for (i = 0; i < k; i++) { \ - { op; } \ - }; \ - getrusage(RUSAGE_SELF, &ru); \ - dNow = (double)ru.ru_utime.tv_sec+(double)ru.ru_utime.tv_usec*0.000001; \ - dUserTime = dNow-dStart; \ - if (dUserTime) printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \ -} +#define M_TimeOperation(op, k) \ + { \ + double dStart, dNow, dUserTime; \ + struct rusage ru; \ + int i; \ + getrusage(RUSAGE_SELF, &ru); \ + dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \ + for (i = 0; i < k; i++) { \ + { \ + op; \ + } \ + }; \ + getrusage(RUSAGE_SELF, &ru); \ + dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \ + dUserTime = dNow - dStart; \ + if (dUserTime) \ + printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \ + } /* Test curve using generic field arithmetic. */ -#define ECTEST_GENERIC_GFP(name_c, name) \ - printf("Testing %s using generic implementation...\n", name_c); \ - params = EC_GetNamedCurveParams(name); \ - if (params == NULL) { \ - printf(" Error: could not construct params.\n"); \ - res = MP_NO; \ - goto CLEANUP; \ - } \ - ECGroup_free(group); \ - group = ECGroup_fromHex(params); \ - if (group == NULL) { \ - printf(" Error: could not construct group.\n"); \ - res = MP_NO; \ - goto CLEANUP; \ - } \ - MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 1) ); \ - printf("... okay.\n"); +#define ECTEST_GENERIC_GFP(name_c, name) \ + printf("Testing %s using generic implementation...\n", name_c); \ + params = EC_GetNamedCurveParams(name); \ + if (params == NULL) { \ + printf(" Error: could not construct params.\n"); \ + res = MP_NO; \ + goto CLEANUP; \ + } \ + ECGroup_free(group); \ + group = ECGroup_fromHex(params); \ + if (group == NULL) { \ + printf(" Error: could not construct group.\n"); \ + res = MP_NO; \ + goto CLEANUP; \ + } \ + MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 1)); \ + printf("... okay.\n"); /* Test curve using specific field arithmetic. */ -#define ECTEST_NAMED_GFP(name_c, name) \ - printf("Testing %s using specific implementation...\n", name_c); \ - ECGroup_free(group); \ - group = ECGroup_fromName(name); \ - if (group == NULL) { \ - printf(" Warning: could not construct group.\n"); \ - printf("... failed; continuing with remaining tests.\n"); \ - } else { \ - MP_CHECKOK( ectest_curve_GFp(group, ectestPrint, ectestTime, 0) ); \ - printf("... okay.\n"); \ - } +#define ECTEST_NAMED_GFP(name_c, name) \ + printf("Testing %s using specific implementation...\n", name_c); \ + ECGroup_free(group); \ + group = ECGroup_fromName(name); \ + if (group == NULL) { \ + printf(" Warning: could not construct group.\n"); \ + printf("... failed; continuing with remaining tests.\n"); \ + } else { \ + MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 0)); \ + printf("... okay.\n"); \ + } /* Performs basic tests of elliptic curve cryptography over prime fields. * If tests fail, then it prints an error message, aborts, and returns an * error code. Otherwise, returns 0. */ int ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime, - int generic) + int generic) { - mp_int one, order_1, gx, gy, rx, ry, n; - int size; - mp_err res; - char s[1000]; + mp_int one, order_1, gx, gy, rx, ry, n; + int size; + mp_err res; + char s[1000]; - /* initialize values */ - MP_CHECKOK(mp_init(&one)); - MP_CHECKOK(mp_init(&order_1)); - MP_CHECKOK(mp_init(&gx)); - MP_CHECKOK(mp_init(&gy)); - MP_CHECKOK(mp_init(&rx)); - MP_CHECKOK(mp_init(&ry)); - MP_CHECKOK(mp_init(&n)); + /* initialize values */ + MP_CHECKOK(mp_init(&one)); + MP_CHECKOK(mp_init(&order_1)); + MP_CHECKOK(mp_init(&gx)); + MP_CHECKOK(mp_init(&gy)); + MP_CHECKOK(mp_init(&rx)); + MP_CHECKOK(mp_init(&ry)); + MP_CHECKOK(mp_init(&n)); - MP_CHECKOK(mp_set_int(&one, 1)); - MP_CHECKOK(mp_sub(&group->order, &one, &order_1)); + MP_CHECKOK(mp_set_int(&one, 1)); + MP_CHECKOK(mp_sub(&group->order, &one, &order_1)); - /* encode base point */ - if (group->meth->field_dec) { - MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth)); - MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth)); - } else { - MP_CHECKOK(mp_copy(&group->genx, &gx)); - MP_CHECKOK(mp_copy(&group->geny, &gy)); - } - if (ectestPrint) { - /* output base point */ - printf(" base point P:\n"); - MP_CHECKOK(mp_toradix(&gx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&gy, s, 16)); - printf(" %s\n", s); - if (group->meth->field_enc) { - printf(" base point P (encoded):\n"); - MP_CHECKOK(mp_toradix(&group->genx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&group->geny, s, 16)); - printf(" %s\n", s); - } - } + /* encode base point */ + if (group->meth->field_dec) { + MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth)); + MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth)); + } else { + MP_CHECKOK(mp_copy(&group->genx, &gx)); + MP_CHECKOK(mp_copy(&group->geny, &gy)); + } + if (ectestPrint) { + /* output base point */ + printf(" base point P:\n"); + MP_CHECKOK(mp_toradix(&gx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&gy, s, 16)); + printf(" %s\n", s); + if (group->meth->field_enc) { + printf(" base point P (encoded):\n"); + MP_CHECKOK(mp_toradix(&group->genx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&group->geny, s, 16)); + printf(" %s\n", s); + } + } #ifdef ECL_ENABLE_GFP_PT_MUL_AFF - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ec_GFp_pt_mul_aff - (&order_1, &group->genx, &group->geny, &rx, &ry, group)); - if (ectestPrint) { - printf(" (order-1)*P (affine):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth)); - if ((mp_cmp(&rx, &group->genx) != 0) - || (mp_cmp(&ry, &group->geny) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order - 1 and check for negative of base + * point */ + MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group)); + if (ectestPrint) { + printf(" (order-1)*P (affine):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth)); + if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) { + printf(" Error: invalid result (expected (- base point)).\n"); + res = MP_NO; + goto CLEANUP; + } #endif #ifdef ECL_ENABLE_GFP_PT_MUL_AFF - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ec_GFp_pt_mul_jac - (&order_1, &group->genx, &group->geny, &rx, &ry, group)); - if (ectestPrint) { - printf(" (order-1)*P (jacobian):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth)); - if ((mp_cmp(&rx, &group->genx) != 0) - || (mp_cmp(&ry, &group->geny) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order - 1 and check for negative of base + * point */ + MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group)); + if (ectestPrint) { + printf(" (order-1)*P (jacobian):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth)); + if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) { + printf(" Error: invalid result (expected (- base point)).\n"); + res = MP_NO; + goto CLEANUP; + } #endif - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry)); - if (ectestPrint) { - printf(" (order-1)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); - if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order - 1 and check for negative of base + * point */ + MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry)); + if (ectestPrint) { + printf(" (order-1)*P (ECPoint_mul):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); + if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { + printf(" Error: invalid result (expected (- base point)).\n"); + res = MP_NO; + goto CLEANUP; + } - /* multiply base point by order - 1 and check for negative of base - * point */ - MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry)); - if (ectestPrint) { - printf(" (order-1)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); - if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order - 1 and check for negative of base + * point */ + MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry)); + if (ectestPrint) { + printf(" (order-1)*P (ECPoint_mul):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); + if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { + printf(" Error: invalid result (expected (- base point)).\n"); + res = MP_NO; + goto CLEANUP; + } #ifdef ECL_ENABLE_GFP_PT_MUL_AFF - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ec_GFp_pt_mul_aff - (&group->order, &group->genx, &group->geny, &rx, &ry, - group)); - if (ectestPrint) { - printf(" (order)*P (affine):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order and check for point at infinity */ + MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry, + group)); + if (ectestPrint) { + printf(" (order)*P (affine):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { + printf(" Error: invalid result (expected point at infinity).\n"); + res = MP_NO; + goto CLEANUP; + } #endif #ifdef ECL_ENABLE_GFP_PT_MUL_JAC - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ec_GFp_pt_mul_jac - (&group->order, &group->genx, &group->geny, &rx, &ry, - group)); - if (ectestPrint) { - printf(" (order)*P (jacobian):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order and check for point at infinity */ + MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry, + group)); + if (ectestPrint) { + printf(" (order)*P (jacobian):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { + printf(" Error: invalid result (expected point at infinity).\n"); + res = MP_NO; + goto CLEANUP; + } #endif - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry)); - if (ectestPrint) { - printf(" (order)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order and check for point at infinity */ + MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry)); + if (ectestPrint) { + printf(" (order)*P (ECPoint_mul):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { + printf(" Error: invalid result (expected point at infinity).\n"); + res = MP_NO; + goto CLEANUP; + } - /* multiply base point by order and check for point at infinity */ - MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry)); - if (ectestPrint) { - printf(" (order)*P (ECPoint_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { - printf(" Error: invalid result (expected point at infinity).\n"); - res = MP_NO; - goto CLEANUP; - } + /* multiply base point by order and check for point at infinity */ + MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry)); + if (ectestPrint) { + printf(" (order)*P (ECPoint_mul):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) { + printf(" Error: invalid result (expected point at infinity).\n"); + res = MP_NO; + goto CLEANUP; + } - /* check that (order-1)P + (order-1)P + P == (order-1)P */ - MP_CHECKOK(ECPoints_mul - (group, &order_1, &order_1, &gx, &gy, &rx, &ry)); - MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry)); - if (ectestPrint) { - printf - (" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n"); - MP_CHECKOK(mp_toradix(&rx, s, 16)); - printf(" %s\n", s); - MP_CHECKOK(mp_toradix(&ry, s, 16)); - printf(" %s\n", s); - } - MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); - if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { - printf(" Error: invalid result (expected (- base point)).\n"); - res = MP_NO; - goto CLEANUP; - } + /* check that (order-1)P + (order-1)P + P == (order-1)P */ + MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry)); + MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry)); + if (ectestPrint) { + printf(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n"); + MP_CHECKOK(mp_toradix(&rx, s, 16)); + printf(" %s\n", s); + MP_CHECKOK(mp_toradix(&ry, s, 16)); + printf(" %s\n", s); + } + MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry)); + if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) { + printf(" Error: invalid result (expected (- base point)).\n"); + res = MP_NO; + goto CLEANUP; + } - /* test validate_point function */ - if (ECPoint_validate(group, &gx, &gy) != MP_YES) { - printf(" Error: validate point on base point failed.\n"); - res = MP_NO; - goto CLEANUP; - } - MP_CHECKOK(mp_add_d(&gy, 1, &ry)); - if (ECPoint_validate(group, &gx, &ry) != MP_NO) { - printf(" Error: validate point on invalid point passed.\n"); - res = MP_NO; - goto CLEANUP; - } + /* test validate_point function */ + if (ECPoint_validate(group, &gx, &gy) != MP_YES) { + printf(" Error: validate point on base point failed.\n"); + res = MP_NO; + goto CLEANUP; + } + MP_CHECKOK(mp_add_d(&gy, 1, &ry)); + if (ECPoint_validate(group, &gx, &ry) != MP_NO) { + printf(" Error: validate point on invalid point passed.\n"); + res = MP_NO; + goto CLEANUP; + } - if (ectestTime) { - /* compute random scalar */ - size = mpl_significant_bits(&group->meth->irr); - if (size < MP_OKAY) { - goto CLEANUP; - } - MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); - MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth)); - /* timed test */ - if (generic) { + if (ectestTime) { + /* compute random scalar */ + size = mpl_significant_bits(&group->meth->irr); + if (size < MP_OKAY) { + goto CLEANUP; + } + MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS)); + MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth)); + /* timed test */ + if (generic) { #ifdef ECL_ENABLE_GFP_PT_MUL_AFF - M_TimeOperation(MP_CHECKOK - (ec_GFp_pt_mul_aff - (&n, &group->genx, &group->geny, &rx, &ry, - group)), 100); + M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry, + group)), + 100); #endif - M_TimeOperation(MP_CHECKOK - (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), - 100); - M_TimeOperation(MP_CHECKOK - (ECPoints_mul - (group, &n, &n, &gx, &gy, &rx, &ry)), 100); - } else { - M_TimeOperation(MP_CHECKOK - (ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), - 100); - M_TimeOperation(MP_CHECKOK - (ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)), - 100); - M_TimeOperation(MP_CHECKOK - (ECPoints_mul - (group, &n, &n, &gx, &gy, &rx, &ry)), 100); - } - } + M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), + 100); + M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100); + } else { + M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)), + 100); + M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)), + 100); + M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100); + } + } - CLEANUP: - mp_clear(&one); - mp_clear(&order_1); - mp_clear(&gx); - mp_clear(&gy); - mp_clear(&rx); - mp_clear(&ry); - mp_clear(&n); - if (res != MP_OKAY) { - printf(" Error: exiting with error value %i\n", res); - } - return res; +CLEANUP: + mp_clear(&one); + mp_clear(&order_1); + mp_clear(&gx); + mp_clear(&gy); + mp_clear(&rx); + mp_clear(&ry); + mp_clear(&n); + if (res != MP_OKAY) { + printf(" Error: exiting with error value %i\n", res); + } + return res; } /* Prints help information. */ void printUsage() { - printf("Usage: ecp_test [--print] [--time]\n"); - printf - (" --print Print out results of each point arithmetic test.\n"); - printf - (" --time Benchmark point operations and print results.\n"); + printf("Usage: ecp_test [--print] [--time]\n"); + printf(" --print Print out results of each point arithmetic test.\n"); + printf(" --time Benchmark point operations and print results.\n"); } /* Performs tests of elliptic curve cryptography over prime fields If @@ -356,71 +342,68 @@ int main(int argv, char **argc) { - int ectestTime = 0; - int ectestPrint = 0; - int i; - ECGroup *group = NULL; - ECCurveParams *params = NULL; - mp_err res; + int ectestTime = 0; + int ectestPrint = 0; + int i; + ECGroup *group = NULL; + ECCurveParams *params = NULL; + mp_err res; - /* read command-line arguments */ - for (i = 1; i < argv; i++) { - if ((strcasecmp(argc[i], "time") == 0) - || (strcasecmp(argc[i], "-time") == 0) - || (strcasecmp(argc[i], "--time") == 0)) { - ectestTime = 1; - } else if ((strcasecmp(argc[i], "print") == 0) - || (strcasecmp(argc[i], "-print") == 0) - || (strcasecmp(argc[i], "--print") == 0)) { - ectestPrint = 1; - } else { - printUsage(); - return 0; - } - } + /* read command-line arguments */ + for (i = 1; i < argv; i++) { + if ((strcasecmp(argc[i], "time") == 0) || (strcasecmp(argc[i], "-time") == 0) || (strcasecmp(argc[i], "--time") == 0)) { + ectestTime = 1; + } else if ((strcasecmp(argc[i], "print") == 0) || (strcasecmp(argc[i], "-print") == 0) || (strcasecmp(argc[i], "--print") == 0)) { + ectestPrint = 1; + } else { + printUsage(); + return 0; + } + } - /* generic arithmetic tests */ - ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1); + /* generic arithmetic tests */ + ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1); - /* specific arithmetic tests */ - ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192); - ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224); - ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256); - ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384); - ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3); - ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1); - ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1); - ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2); - ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1); - ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2); - ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1); - ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1); - ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2); - ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1); - ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1); - ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1); - ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1); - ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1); - ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1); - ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1); - ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1); - ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6); - ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7); - ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8); - ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9); - ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12); + /* specific arithmetic tests */ + ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192); + ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224); + ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256); + ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384); + ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3); + ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1); + ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1); + ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2); + ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1); + ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2); + ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1); + ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1); + ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2); + ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1); + ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1); + ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1); + ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1); + ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1); + ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1); + ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1); + ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1); + ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6); + ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7); + ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8); + ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9); + ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12); + ECTEST_NAMED_GFP("Curve25519", ECCurve25519); - CLEANUP: - EC_FreeCurveParams(params); - ECGroup_free(group); - if (res != MP_OKAY) { - printf("Error: exiting with error value %i\n", res); - } - return res; +CLEANUP: + EC_FreeCurveParams(params); + ECGroup_free(group); + if (res != MP_OKAY) { + printf("Error: exiting with error value %i\n", res); + } + return res; } diff --git a/nss/lib/freebl/ecl/uint128.c b/nss/lib/freebl/ecl/uint128.c new file mode 100644 index 0000000..22cbd02 --- /dev/null +++ b/nss/lib/freebl/ecl/uint128.c @@ -0,0 +1,87 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "uint128.h" + +/* helper functions */ +uint64_t +mask51(uint128_t x) +{ + return x.lo & MASK51; +} + +uint64_t +mask_lower(uint128_t x) +{ + return x.lo; +} + +uint128_t +mask51full(uint128_t x) +{ + uint128_t ret = { x.lo & MASK51, 0 }; + return ret; +} + +uint128_t +init128x(uint64_t x) +{ + uint128_t ret = { x, 0 }; + return ret; +} + +/* arithmetic */ + +uint128_t +add128(uint128_t a, uint128_t b) +{ + uint128_t ret; + ret.lo = a.lo + b.lo; + ret.hi = a.hi + b.hi + (ret.lo < b.lo); + return ret; +} + +/* out = 19 * a */ +uint128_t +mul12819(uint128_t a) +{ + uint128_t ret = lshift128(a, 4); + ret = add128(ret, a); + ret = add128(ret, a); + ret = add128(ret, a); + return ret; +} + +uint128_t +mul6464(uint64_t a, uint64_t b) +{ + uint128_t ret; + uint64_t t0 = ((uint64_t)(uint32_t)a) * ((uint64_t)(uint32_t)b); + uint64_t t1 = (a >> 32) * ((uint64_t)(uint32_t)b) + (t0 >> 32); + uint64_t t2 = (b >> 32) * ((uint64_t)(uint32_t)a) + ((uint32_t)t1); + ret.lo = (((uint64_t)((uint32_t)t2)) << 32) + ((uint32_t)t0); + ret.hi = (a >> 32) * (b >> 32); + ret.hi += (t2 >> 32) + (t1 >> 32); + return ret; +} + +/* only defined for n < 64 */ +uint128_t +rshift128(uint128_t x, uint8_t n) +{ + uint128_t ret; + ret.lo = (x.lo >> n) + (x.hi << (64 - n)); + ret.hi = x.hi >> n; + return ret; +} + +/* only defined for n < 64 */ +uint128_t +lshift128(uint128_t x, uint8_t n) +{ + uint128_t ret; + ret.hi = (x.hi << n) + (x.lo >> (64 - n)); + ret.lo = x.lo << n; + return ret; +} diff --git a/nss/lib/freebl/ecl/uint128.h b/nss/lib/freebl/ecl/uint128.h new file mode 100644 index 0000000..a3a71e6 --- /dev/null +++ b/nss/lib/freebl/ecl/uint128.h @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdint.h> + +#define MASK51 0x7ffffffffffffULL + +#ifdef HAVE_INT128_SUPPORT +typedef unsigned __int128 uint128_t; +#define add128(a, b) (a) + (b) +#define mul6464(a, b) (uint128_t)(a) * (uint128_t)(b) +#define mul12819(a) (uint128_t)(a) * 19 +#define rshift128(x, n) (x) >> (n) +#define lshift128(x, n) (x) << (n) +#define mask51(x) (x) & 0x7ffffffffffff +#define mask_lower(x) (uint64_t)(x) +#define mask51full(x) (x) & 0x7ffffffffffff +#define init128x(x) (x) +#else /* uint128_t for Windows and 32 bit intel systems */ +struct uint128_t_str { + uint64_t lo; + uint64_t hi; +}; +typedef struct uint128_t_str uint128_t; +uint128_t add128(uint128_t a, uint128_t b); +uint128_t mul6464(uint64_t a, uint64_t b); +uint128_t mul12819(uint128_t a); +uint128_t rshift128(uint128_t x, uint8_t n); +uint128_t lshift128(uint128_t x, uint8_t n); +uint64_t mask51(uint128_t x); +uint64_t mask_lower(uint128_t x); +uint128_t mask51full(uint128_t x); +uint128_t init128x(uint64_t x); +#endif |