summaryrefslogtreecommitdiff
path: root/security/nss/lib/freebl/ecl/ecp_224.c
diff options
context:
space:
mode:
authornelsonb%netscape.com <devnull@localhost>2003-12-06 06:41:51 +0000
committernelsonb%netscape.com <devnull@localhost>2003-12-06 06:41:51 +0000
commitab5a12f0b4b478fe51179fef6b13515eecc08e90 (patch)
tree6a3368a53e481a2d140009850fac7eb13ae39977 /security/nss/lib/freebl/ecl/ecp_224.c
parentb6c9daf28b6890a04b30759dafbfe596084ae614 (diff)
parent4a8a6c26b6278cb6359fabd743efc45e94bfc878 (diff)
downloadnss-hg-ab5a12f0b4b478fe51179fef6b13515eecc08e90.tar.gz
NSC_Finalize will now destroy 3 softoken free lists and one more
global pointer. Plugs some memory leaks. Bugscape bug 54301. r=wtc
Diffstat (limited to 'security/nss/lib/freebl/ecl/ecp_224.c')
-rw-r--r--security/nss/lib/freebl/ecl/ecp_224.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/security/nss/lib/freebl/ecl/ecp_224.c b/security/nss/lib/freebl/ecl/ecp_224.c
new file mode 100644
index 000000000..6e6e81ce4
--- /dev/null
+++ b/security/nss/lib/freebl/ecl/ecp_224.c
@@ -0,0 +1,305 @@
+/*
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the elliptic curve math library for prime
+ * field curves.
+ *
+ * The Initial Developer of the Original Code is Sun Microsystems, Inc.
+ * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003
+ * Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ */
+
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#include <stdlib.h>
+
+/* 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. */
+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);
+
+ /* s is a statically-allocated mp_int of exactly the size we need */
+ mp_int s;
+
+#ifdef ECL_THIRTY_TWO_BIT
+ mp_digit sa[8];
+ mp_digit a13 = 0, a12 = 0, a11 = 0, a10, a9 = 0, a8, a7;
+
+ MP_SIGN(&s) = MP_ZPOS;
+ MP_ALLOC(&s) = 8;
+ MP_USED(&s) = 7;
+ MP_DIGITS(&s) = sa;
+#else
+ mp_digit sa[4];
+ mp_digit a6 = 0, a5 = 0, a4 = 0, a3 = 0;
+
+ MP_SIGN(&s) = MP_ZPOS;
+ MP_ALLOC(&s) = 4;
+ MP_USED(&s) = 4;
+ MP_DIGITS(&s) = sa;
+#endif
+
+ /* reduction not needed if a is not larger than field size */
+#ifdef ECL_THIRTY_TWO_BIT
+ if (a_used < 8) {
+#else
+ if (a_used < 4) {
+#endif
+ return mp_copy(a, r);
+ }
+#ifdef ECL_THIRTY_TWO_BIT
+ /* for polynomials larger than twice the field size, use regular
+ * reduction */
+ if (a_used > 14) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+ /* copy out upper words of a */
+ switch (a_used) {
+ 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);
+ case 8:
+ a7 = MP_DIGIT(a, 7);
+ }
+ /* set the lower words of r */
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r, 8));
+ MP_DIGIT(r, 6) = MP_DIGIT(a, 6);
+ MP_DIGIT(r, 5) = MP_DIGIT(a, 5);
+ MP_DIGIT(r, 4) = MP_DIGIT(a, 4);
+ MP_DIGIT(r, 3) = MP_DIGIT(a, 3);
+ MP_DIGIT(r, 2) = MP_DIGIT(a, 2);
+ MP_DIGIT(r, 1) = MP_DIGIT(a, 1);
+ MP_DIGIT(r, 0) = MP_DIGIT(a, 0);
+ }
+ MP_USED(r) = 7;
+ switch (a_used) {
+ case 14:
+ case 13:
+ case 12:
+ case 11:
+ sa[6] = a10;
+ case 10:
+ sa[5] = a9;
+ case 9:
+ sa[4] = a8;
+ case 8:
+ sa[3] = a7;
+ sa[2] = sa[1] = sa[0] = 0;
+ MP_USED(&s) = a_used - 4;
+ if (MP_USED(&s) > 7)
+ MP_USED(&s) = 7;
+ MP_CHECKOK(mp_add(r, &s, r));
+ }
+ switch (a_used) {
+ case 14:
+ sa[5] = a13;
+ case 13:
+ sa[4] = a12;
+ case 12:
+ sa[3] = a11;
+ sa[2] = sa[1] = sa[0] = 0;
+ MP_USED(&s) = a_used - 8;
+ MP_CHECKOK(mp_add(r, &s, r));
+ }
+ switch (a_used) {
+ case 14:
+ sa[6] = a13;
+ case 13:
+ sa[5] = a12;
+ case 12:
+ sa[4] = a11;
+ case 11:
+ sa[3] = a10;
+ case 10:
+ sa[2] = a9;
+ case 9:
+ sa[1] = a8;
+ case 8:
+ sa[0] = a7;
+ MP_USED(&s) = a_used - 7;
+ MP_CHECKOK(mp_sub(r, &s, r));
+ }
+ switch (a_used) {
+ case 14:
+ sa[2] = a13;
+ case 13:
+ sa[1] = a12;
+ case 12:
+ sa[0] = a11;
+ MP_USED(&s) = a_used - 11;
+ MP_CHECKOK(mp_sub(r, &s, r));
+ }
+ /* there might be 1 or 2 bits left to reduce; use regular
+ * reduction for this */
+ MP_CHECKOK(mp_mod(r, &meth->irr, r));
+ }
+#else
+ /* for polynomials larger than twice the field size, use regular
+ * reduction */
+ if (a_used > 7) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+ /* copy out upper words of a */
+ switch (a_used) {
+ case 7:
+ a6 = MP_DIGIT(a, 6);
+ case 6:
+ a5 = MP_DIGIT(a, 5);
+ case 5:
+ a4 = MP_DIGIT(a, 4);
+ case 4:
+ a3 = MP_DIGIT(a, 3) >> 32;
+ }
+ /* set the lower words of r */
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r, 5));
+ MP_DIGIT(r, 3) = MP_DIGIT(a, 3) & 0xFFFFFFFF;
+ MP_DIGIT(r, 2) = MP_DIGIT(a, 2);
+ MP_DIGIT(r, 1) = MP_DIGIT(a, 1);
+ MP_DIGIT(r, 0) = MP_DIGIT(a, 0);
+ } else {
+ MP_DIGIT(r, 3) &= 0xFFFFFFFF;
+ }
+ MP_USED(r) = 4;
+ switch (a_used) {
+ case 7:
+ case 6:
+ sa[3] = a5 & 0xFFFFFFFF;
+ case 5:
+ sa[2] = a4;
+ case 4:
+ sa[1] = a3 << 32;
+ sa[0] = 0;
+ MP_USED(&s) = a_used - 2;
+ if (MP_USED(&s) == 5)
+ MP_USED(&s) = 4;
+ MP_CHECKOK(mp_add(r, &s, r));
+ }
+ switch (a_used) {
+ case 7:
+ sa[2] = a6;
+ case 6:
+ sa[1] = (a5 >> 32) << 32;
+ sa[0] = 0;
+ MP_USED(&s) = a_used - 4;
+ MP_CHECKOK(mp_add(r, &s, r));
+ }
+ sa[2] = sa[1] = sa[0] = 0;
+ switch (a_used) {
+ case 7:
+ sa[3] = a6 >> 32;
+ sa[2] = a6 << 32;
+ case 6:
+ sa[2] |= a5 >> 32;
+ sa[1] = a5 << 32;
+ case 5:
+ sa[1] |= a4 >> 32;
+ sa[0] = a4 << 32;
+ case 4:
+ sa[0] |= a3;
+ MP_USED(&s) = a_used - 3;
+ MP_CHECKOK(mp_sub(r, &s, r));
+ }
+ sa[0] = 0;
+ switch (a_used) {
+ case 7:
+ sa[1] = a6 >> 32;
+ sa[0] = a6 << 32;
+ case 6:
+ sa[0] |= a5 >> 32;
+ MP_USED(&s) = a_used - 5;
+ MP_CHECKOK(mp_sub(r, &s, r));
+ }
+ /* there might be 1 or 2 bits left to reduce; use regular
+ * reduction for this */
+ MP_CHECKOK(mp_mod(r, &meth->irr, r));
+ }
+#endif
+
+ 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.
+ */
+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. */
+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;
+}
+
+/* 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;
+ }
+ return MP_OKAY;
+}