From 5c2c5888f9fcccd2c7eaff3cd54b93b54eb73096 Mon Sep 17 00:00:00 2001 From: "ian.mcgreer%sun.com" Date: Fri, 17 Oct 2003 13:45:42 +0000 Subject: [PATCH] ECC code landing. Contributed by Sheuling Chang, Stephen Fung, Vipul Gupta, Nils Gura, and Douglas Stebila of Sun Labs --- security/nss/cmd/bltest/blapitest.c | 549 ++++++- security/nss/cmd/bltest/manifest.mn | 6 +- security/nss/cmd/bltest/tests/ecdsa/README | 22 + .../nss/cmd/bltest/tests/ecdsa/ciphertext0 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext1 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext10 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext11 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext12 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext13 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext14 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext15 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext16 | 3 + .../nss/cmd/bltest/tests/ecdsa/ciphertext17 | 3 + .../nss/cmd/bltest/tests/ecdsa/ciphertext18 | 3 + .../nss/cmd/bltest/tests/ecdsa/ciphertext19 | 3 + .../nss/cmd/bltest/tests/ecdsa/ciphertext2 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext20 | 3 + .../nss/cmd/bltest/tests/ecdsa/ciphertext3 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext4 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext5 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext6 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext7 | 1 + .../nss/cmd/bltest/tests/ecdsa/ciphertext8 | 2 + .../nss/cmd/bltest/tests/ecdsa/ciphertext9 | 2 + security/nss/cmd/bltest/tests/ecdsa/key0 | 2 + security/nss/cmd/bltest/tests/ecdsa/key1 | 2 + security/nss/cmd/bltest/tests/ecdsa/key10 | 3 + security/nss/cmd/bltest/tests/ecdsa/key11 | 3 + security/nss/cmd/bltest/tests/ecdsa/key12 | 3 + security/nss/cmd/bltest/tests/ecdsa/key13 | 3 + security/nss/cmd/bltest/tests/ecdsa/key14 | 3 + security/nss/cmd/bltest/tests/ecdsa/key15 | 4 + security/nss/cmd/bltest/tests/ecdsa/key16 | 4 + security/nss/cmd/bltest/tests/ecdsa/key17 | 4 + security/nss/cmd/bltest/tests/ecdsa/key18 | 5 + security/nss/cmd/bltest/tests/ecdsa/key19 | 5 + security/nss/cmd/bltest/tests/ecdsa/key2 | 2 + security/nss/cmd/bltest/tests/ecdsa/key20 | 5 + security/nss/cmd/bltest/tests/ecdsa/key3 | 2 + security/nss/cmd/bltest/tests/ecdsa/key4 | 2 + security/nss/cmd/bltest/tests/ecdsa/key5 | 2 + security/nss/cmd/bltest/tests/ecdsa/key6 | 2 + security/nss/cmd/bltest/tests/ecdsa/key7 | 2 + security/nss/cmd/bltest/tests/ecdsa/key8 | 3 + security/nss/cmd/bltest/tests/ecdsa/key9 | 3 + security/nss/cmd/bltest/tests/ecdsa/numtests | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext0 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext1 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext10 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext11 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext12 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext13 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext14 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext15 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext16 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext17 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext18 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext19 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext2 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext20 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext3 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext4 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext5 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext6 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext7 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext8 | 1 + .../nss/cmd/bltest/tests/ecdsa/plaintext9 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed0 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed1 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed10 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed11 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed12 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed13 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed14 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed15 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed16 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed17 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed18 | 2 + security/nss/cmd/bltest/tests/ecdsa/sigseed19 | 2 + security/nss/cmd/bltest/tests/ecdsa/sigseed2 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed20 | 2 + security/nss/cmd/bltest/tests/ecdsa/sigseed3 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed4 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed5 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed6 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed7 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed8 | 1 + security/nss/cmd/bltest/tests/ecdsa/sigseed9 | 1 + security/nss/cmd/certutil/certutil.c | 102 +- security/nss/cmd/certutil/keystuff.c | 143 +- security/nss/cmd/certutil/manifest.mn | 4 + security/nss/cmd/lib/manifest.mn | 4 + security/nss/cmd/lib/secutil.c | 31 +- security/nss/cmd/pk12util/manifest.mn | 4 + security/nss/cmd/pk12util/pk12util.c | 1 + security/nss/cmd/selfserv/manifest.mn | 4 + security/nss/cmd/selfserv/selfserv.c | 64 +- security/nss/cmd/tstclnt/manifest.mn | 4 + security/nss/cmd/tstclnt/tstclnt.c | 4 +- security/nss/lib/cryptohi/cryptohi.h | 24 +- security/nss/lib/cryptohi/dsautil.c | 112 +- security/nss/lib/cryptohi/manifest.mn | 4 + security/nss/lib/cryptohi/seckey.c | 99 +- security/nss/lib/cryptohi/secsign.c | 25 +- security/nss/lib/cryptohi/secvfy.c | 202 +-- security/nss/lib/freebl/Makefile | 50 +- security/nss/lib/freebl/blapit.h | 9 +- security/nss/lib/freebl/ec.c | 359 ++-- security/nss/lib/freebl/ecl/Makefile | 224 +++ security/nss/lib/freebl/ecl/README | 329 ++++ security/nss/lib/freebl/ecl/README.FP | 316 ++++ security/nss/lib/freebl/ecl/ec2.h | 122 ++ security/nss/lib/freebl/ecl/ec2_163.c | 258 +++ security/nss/lib/freebl/ecl/ec2_193.c | 275 ++++ security/nss/lib/freebl/ecl/ec2_233.c | 298 ++++ security/nss/lib/freebl/ecl/ec2_aff.c | 270 +++ security/nss/lib/freebl/ecl/ec2_mont.c | 276 ++++ security/nss/lib/freebl/ecl/ec2_proj.c | 368 +++++ security/nss/lib/freebl/ecl/ec_naf.c | 101 ++ security/nss/lib/freebl/ecl/ecl-curve.h | 646 ++++++++ security/nss/lib/freebl/ecl/ecl-exp.h | 194 +++ security/nss/lib/freebl/ecl/ecl-priv.h | 216 +++ security/nss/lib/freebl/ecl/ecl.c | 406 +++++ security/nss/lib/freebl/ecl/ecl.h | 82 + security/nss/lib/freebl/ecl/ecl_curve.c | 120 ++ security/nss/lib/freebl/ecl/ecl_gf.c | 337 ++++ security/nss/lib/freebl/ecl/ecl_mult.c | 359 ++++ security/nss/lib/freebl/ecl/ecp.h | 136 ++ security/nss/lib/freebl/ecl/ecp_192.c | 228 +++ security/nss/lib/freebl/ecl/ecp_224.c | 305 ++++ security/nss/lib/freebl/ecl/ecp_aff.c | 284 ++++ security/nss/lib/freebl/ecl/ecp_fp.c | 566 +++++++ security/nss/lib/freebl/ecl/ecp_fp.h | 405 +++++ security/nss/lib/freebl/ecl/ecp_fp160.c | 178 ++ security/nss/lib/freebl/ecl/ecp_fp192.c | 176 ++ security/nss/lib/freebl/ecl/ecp_fp224.c | 189 +++ security/nss/lib/freebl/ecl/ecp_fpinc.c | 854 ++++++++++ security/nss/lib/freebl/ecl/ecp_jac.c | 553 +++++++ security/nss/lib/freebl/ecl/ecp_jm.c | 320 ++++ security/nss/lib/freebl/ecl/ecp_mont.c | 190 +++ security/nss/lib/freebl/ecl/tests/ec2_test.c | 459 ++++++ security/nss/lib/freebl/ecl/tests/ec_naft.c | 149 ++ security/nss/lib/freebl/ecl/tests/ecp_fpt.c | 1122 +++++++++++++ security/nss/lib/freebl/ecl/tests/ecp_test.c | 421 +++++ security/nss/lib/freebl/loader.h | 10 +- security/nss/lib/freebl/manifest.mn | 27 +- security/nss/lib/freebl/mpi/Makefile | 191 +-- security/nss/lib/freebl/mpi/mp_gf2m-priv.h | 101 ++ security/nss/lib/freebl/mpi/mp_gf2m.c | 119 +- security/nss/lib/freebl/mpi/mpi-priv.h | 12 +- security/nss/lib/freebl/mpi/mpi.c | 8 +- security/nss/lib/freebl/mpi/mpmontg.c | 12 +- security/nss/lib/freebl/mpi/target.mk | 220 +++ security/nss/lib/nss/nss.def | 4 + security/nss/lib/pk11wrap/manifest.mn | 4 + security/nss/lib/pk11wrap/pk11cert.c | 16 + security/nss/lib/pk11wrap/pk11func.h | 6 + security/nss/lib/pk11wrap/pk11skey.c | 191 ++- security/nss/lib/pkcs12/manifest.mn | 4 + security/nss/lib/pkcs12/p12d.c | 9 + security/nss/lib/softoken/ecdecode.c | 1460 +++-------------- security/nss/lib/softoken/keydb.c | 148 +- security/nss/lib/softoken/lowcert.c | 34 +- security/nss/lib/softoken/lowkey.c | 114 ++ security/nss/lib/softoken/lowkeyi.h | 10 +- security/nss/lib/softoken/lowkeyti.h | 5 + security/nss/lib/softoken/manifest.mn | 5 + security/nss/lib/softoken/pkcs11.c | 12 +- security/nss/lib/softoken/pkcs11c.c | 148 +- security/nss/lib/softoken/pkcs11u.c | 90 + security/nss/lib/ssl/manifest.mn | 4 + security/nss/lib/ssl/nsskea.c | 11 +- security/nss/lib/ssl/ssl3con.c | 129 +- security/nss/lib/ssl/ssl3prot.h | 10 +- security/nss/lib/ssl/sslsecur.c | 7 +- security/nss/tests/cert/eccert.sh | 889 ++++++++++ security/nss/tests/cert/noeccert.sh | 654 ++++++++ security/nss/tests/fixtests.sh | 104 ++ security/nss/tests/tools/ectools.sh | 210 +++ security/nss/tests/tools/noectools.sh | 189 +++ 180 files changed, 16881 insertions(+), 1993 deletions(-) create mode 100644 security/nss/cmd/bltest/tests/ecdsa/README create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext0 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext1 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext10 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext11 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext12 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext13 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext14 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext15 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext16 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext17 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext18 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext19 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext2 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext20 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext3 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext4 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext5 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext6 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext7 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext8 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/ciphertext9 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key0 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key1 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key10 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key11 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key12 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key13 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key14 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key15 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key16 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key17 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key18 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key19 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key2 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key20 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key3 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key4 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key5 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key6 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key7 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key8 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/key9 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/numtests create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext0 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext1 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext10 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext11 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext12 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext13 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext14 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext15 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext16 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext17 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext18 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext19 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext2 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext20 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext3 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext4 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext5 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext6 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext7 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext8 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/plaintext9 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed0 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed1 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed10 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed11 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed12 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed13 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed14 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed15 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed16 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed17 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed18 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed19 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed2 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed20 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed3 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed4 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed5 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed6 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed7 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed8 create mode 100644 security/nss/cmd/bltest/tests/ecdsa/sigseed9 create mode 100644 security/nss/lib/freebl/ecl/Makefile create mode 100644 security/nss/lib/freebl/ecl/README create mode 100644 security/nss/lib/freebl/ecl/README.FP create mode 100644 security/nss/lib/freebl/ecl/ec2.h create mode 100644 security/nss/lib/freebl/ecl/ec2_163.c create mode 100644 security/nss/lib/freebl/ecl/ec2_193.c create mode 100644 security/nss/lib/freebl/ecl/ec2_233.c create mode 100644 security/nss/lib/freebl/ecl/ec2_aff.c create mode 100644 security/nss/lib/freebl/ecl/ec2_mont.c create mode 100644 security/nss/lib/freebl/ecl/ec2_proj.c create mode 100644 security/nss/lib/freebl/ecl/ec_naf.c create mode 100644 security/nss/lib/freebl/ecl/ecl-curve.h create mode 100644 security/nss/lib/freebl/ecl/ecl-exp.h create mode 100644 security/nss/lib/freebl/ecl/ecl-priv.h create mode 100644 security/nss/lib/freebl/ecl/ecl.c create mode 100644 security/nss/lib/freebl/ecl/ecl.h create mode 100644 security/nss/lib/freebl/ecl/ecl_curve.c create mode 100644 security/nss/lib/freebl/ecl/ecl_gf.c create mode 100644 security/nss/lib/freebl/ecl/ecl_mult.c create mode 100644 security/nss/lib/freebl/ecl/ecp.h create mode 100644 security/nss/lib/freebl/ecl/ecp_192.c create mode 100644 security/nss/lib/freebl/ecl/ecp_224.c create mode 100644 security/nss/lib/freebl/ecl/ecp_aff.c create mode 100644 security/nss/lib/freebl/ecl/ecp_fp.c create mode 100644 security/nss/lib/freebl/ecl/ecp_fp.h create mode 100644 security/nss/lib/freebl/ecl/ecp_fp160.c create mode 100644 security/nss/lib/freebl/ecl/ecp_fp192.c create mode 100644 security/nss/lib/freebl/ecl/ecp_fp224.c create mode 100644 security/nss/lib/freebl/ecl/ecp_fpinc.c create mode 100644 security/nss/lib/freebl/ecl/ecp_jac.c create mode 100644 security/nss/lib/freebl/ecl/ecp_jm.c create mode 100644 security/nss/lib/freebl/ecl/ecp_mont.c create mode 100644 security/nss/lib/freebl/ecl/tests/ec2_test.c create mode 100644 security/nss/lib/freebl/ecl/tests/ec_naft.c create mode 100644 security/nss/lib/freebl/ecl/tests/ecp_fpt.c create mode 100644 security/nss/lib/freebl/ecl/tests/ecp_test.c create mode 100644 security/nss/lib/freebl/mpi/mp_gf2m-priv.h create mode 100644 security/nss/lib/freebl/mpi/target.mk create mode 100644 security/nss/tests/cert/eccert.sh create mode 100755 security/nss/tests/cert/noeccert.sh create mode 100755 security/nss/tests/fixtests.sh create mode 100644 security/nss/tests/tools/ectools.sh create mode 100644 security/nss/tests/tools/noectools.sh diff --git a/security/nss/cmd/bltest/blapitest.c b/security/nss/cmd/bltest/blapitest.c index b3000b257951..336cdd660b5d 100644 --- a/security/nss/cmd/bltest/blapitest.c +++ b/security/nss/cmd/bltest/blapitest.c @@ -17,6 +17,7 @@ * Rights Reserved. * * Contributor(s): + * Douglas Stebila , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -47,6 +48,15 @@ #include "softoken.h" #include "nss.h" +#ifdef NSS_ENABLE_ECC +#include "ecl-curve.h" +SECStatus EC_DecodeParams(const SECItem *encodedParams, + ECParams **ecparams); +SECStatus EC_CopyParams(PRArenaPool *arena, ECParams *dstParams, + const ECParams *srcParams); +SECStatus secoid_Init(void); +#endif + /* Temporary - add debugging ouput on windows for RSA to track QA failure */ #ifdef _WIN32 #define TRACK_BLTEST_BUG @@ -123,11 +133,34 @@ static void Usage() PRINTUSAGE(progName, "-S -m mode", "Sign a buffer"); PRINTUSAGE("", "", "[-i plaintext] [-o signature] [-k key]"); PRINTUSAGE("", "", "[-b bufsize]"); +#ifdef NSS_ENABLE_ECC + PRINTUSAGE("", "", "[-n curvename]"); +#endif PRINTUSAGE("", "", "[-p repetitions]"); PRINTUSAGE("", "-m", "cipher mode to use"); PRINTUSAGE("", "-i", "file which contains input buffer"); PRINTUSAGE("", "-o", "file for signature"); PRINTUSAGE("", "-k", "file which contains key"); +#ifdef NSS_ENABLE_ECC + PRINTUSAGE("", "-n", "name of curve for EC key generation; one of:"); + PRINTUSAGE("", "", " sect163k1, nistk163, sect163r1, sect163r2,"); + PRINTUSAGE("", "", " nistb163, sect193r1, sect193r2, sect233k1, nistk233,"); + PRINTUSAGE("", "", " sect233r1, nistb233, sect239k1, sect283k1, nistk283,"); + PRINTUSAGE("", "", " sect283r1, nistb283, sect409k1, nistk409, sect409r1,"); + PRINTUSAGE("", "", " nistb409, sect571k1, nistk571, sect571r1, nistb571,"); + PRINTUSAGE("", "", " secp169k1, secp160r1, secp160r2, secp192k1, secp192r1,"); + PRINTUSAGE("", "", " nistp192, secp224k1, secp224r1, nistp224, secp256k1,"); + PRINTUSAGE("", "", " secp256r1, nistp256, secp384r1, nistp384, secp521r1,"); + PRINTUSAGE("", "", " nistp521, prime192v1, prime192v2, prime192v3,"); + PRINTUSAGE("", "", " prime239v1, prime239v2, prime239v3, c2pnb163v1,"); + PRINTUSAGE("", "", " c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1,"); + PRINTUSAGE("", "", " c2tnb191v2, c2tnb191v3, c2onb191v4, c2onb191v5,"); + PRINTUSAGE("", "", " c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3,"); + PRINTUSAGE("", "", " c2onb239v4, c2onb239v5, c2pnb272w1, c2pnb304w1,"); + PRINTUSAGE("", "", " c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1,"); + PRINTUSAGE("", "", " secp112r2, secp128r1, secp128r2, sect113r1, sect113r2,"); + PRINTUSAGE("", "", " sect131r1, sect131r2"); +#endif PRINTUSAGE("", "-p", "do performance test"); fprintf(stderr, "\n"); PRINTUSAGE(progName, "-V -m mode", "Verify a signed buffer"); @@ -291,23 +324,28 @@ serialize_key(SECItem *it, int ni, PRFileDesc *file) } void -key_from_filedata(PRArenaPool *arena, SECItem *it, int ni, SECItem *filedata) +key_from_filedata(PRArenaPool *arena, SECItem *it, int ns, int ni, SECItem *filedata) { int fpos = 0; - int i; + int i, len; unsigned char *buf = filedata->data; - for (i=0; ilen = (buf[fpos++] & 0xff) << 24; - it->len |= (buf[fpos++] & 0xff) << 16; - it->len |= (buf[fpos++] & 0xff) << 8; - it->len |= (buf[fpos++] & 0xff); - if (it->len > 0) { - it->data = PORT_ArenaAlloc(arena, it->len); - PORT_Memcpy(it->data, &buf[fpos], it->len); - } else { - it->data = NULL; + for (i=0; i 0) { + it->len = len; + it->data = PORT_ArenaAlloc(arena, it->len); + PORT_Memcpy(it->data, &buf[fpos], it->len); + } else { + it->len = 0; + it->data = NULL; + } + it++; } - fpos += it->len; + fpos += len; } } @@ -319,7 +357,7 @@ rsakey_from_filedata(SECItem *filedata) arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); key = (RSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(RSAPrivateKey)); key->arena = arena; - key_from_filedata(arena, &key->version, 9, filedata); + key_from_filedata(arena, &key->version, 0, 9, filedata); return key; } @@ -331,7 +369,7 @@ pqg_from_filedata(SECItem *filedata) arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); pqg = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams)); pqg->arena = arena; - key_from_filedata(arena, &pqg->prime, 3, filedata); + key_from_filedata(arena, &pqg->prime, 0, 3, filedata); return pqg; } @@ -343,10 +381,166 @@ dsakey_from_filedata(SECItem *filedata) arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); key = (DSAPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(DSAPrivateKey)); key->params.arena = arena; - key_from_filedata(arena, &key->params.prime, 5, filedata); + key_from_filedata(arena, &key->params.prime, 0, 5, filedata); return key; } +#ifdef NSS_ENABLE_ECC +static ECPrivateKey * +eckey_from_filedata(SECItem *filedata) +{ + ECPrivateKey *key; + PRArenaPool *arena; + SECStatus rv; + ECParams *tmpECParams = NULL; + arena = PORT_NewArena(BLTEST_DEFAULT_CHUNKSIZE); + key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey)); + /* read and convert params */ + key->ecParams.arena = arena; + key_from_filedata(arena, &key->ecParams.DEREncoding, 0, 1, filedata); + rv = secoid_Init(); + CHECKERROR(rv, __LINE__); + rv = EC_DecodeParams(&key->ecParams.DEREncoding, &tmpECParams); + CHECKERROR(rv, __LINE__); + rv = EC_CopyParams(key->ecParams.arena, &key->ecParams, tmpECParams); + CHECKERROR(rv, __LINE__); + rv = SECOID_Shutdown(); + CHECKERROR(rv, __LINE__); + PORT_FreeArena(tmpECParams->arena, PR_TRUE); + /* read key */ + key_from_filedata(arena, &key->publicValue, 1, 3, filedata); + return key; +} + +typedef struct curveNameTagPairStr { + char *curveName; + SECOidTag curveOidTag; +} CurveNameTagPair; + +#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 +/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ + +static CurveNameTagPair nameTagPair[] = +{ + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, + { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, + { "nistp192", SEC_OID_SECG_EC_SECP192R1}, + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, + { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, + { "nistp256", SEC_OID_SECG_EC_SECP256R1}, + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, + + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, + + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, + + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, + + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, +}; + +static SECKEYECParams * +getECParams(char *curve) +{ + SECKEYECParams *ecparams; + SECOidData *oidData = NULL; + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ + int i, numCurves; + + if (curve != NULL) { + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); + i++) { + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) + curveOidTag = nameTagPair[i].curveOidTag; + } + } + + /* Return NULL if curve name is not recognized */ + if ((curveOidTag == SEC_OID_UNKNOWN) || + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { + fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); + return NULL; + } + + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); + + /* + * ecparams->data needs to contain the ASN encoding of an object ID (OID) + * representing the named curve. The actual OID is in + * oidData->oid.data so we simply prepend 0x06 and OID length + */ + ecparams->data[0] = SEC_ASN1_OBJECT_ID; + ecparams->data[1] = oidData->oid.len; + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); + + return ecparams; +} +#endif /* NSS_ENABLE_ECC */ + static void dump_pqg(PQGParams *pqg) { @@ -363,6 +557,23 @@ dump_dsakey(DSAPrivateKey *key) SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0); } +#ifdef NSS_ENABLE_ECC +static void +dump_ecp(ECParams *ecp) +{ + /* TODO other fields */ + SECU_PrintInteger(stdout, &ecp->base, "BASE POINT:", 0); +} + +static void +dump_eckey(ECPrivateKey *key) +{ + dump_ecp(&key->ecParams); + SECU_PrintInteger(stdout, &key->publicValue, "PUBLIC VALUE:", 0); + SECU_PrintInteger(stdout, &key->privateValue, "PRIVATE VALUE:", 0); +} +#endif + static void dump_rsakey(RSAPrivateKey *key) { @@ -421,7 +632,10 @@ typedef enum { bltestAES_ECB, /* . */ bltestAES_CBC, /* . */ bltestRSA, /* Public Key Ciphers */ - bltestDSA, /* . (Public Key Sig.) */ +#ifdef NSS_ENABLE_ECC + bltestECDSA, /* . (Public Key Sig.) */ +#endif + bltestDSA, /* . */ bltestMD2, /* Hash algorithms */ bltestMD5, /* . */ bltestSHA1, /* . */ @@ -445,6 +659,9 @@ static char *mode_strings[] = "aes_ecb", "aes_cbc", "rsa", +#ifdef NSS_ENABLE_ECC + "ecdsa", +#endif /*"pqg",*/ "dsa", "md2", @@ -488,6 +705,17 @@ typedef struct DSAPrivateKey *dsakey; } bltestDSAParams; +#ifdef NSS_ENABLE_ECC +typedef struct +{ + bltestIO key; + char *curveName; + bltestIO sigseed; + bltestIO sig; /* if doing verify, have additional input */ + ECPrivateKey *eckey; +} bltestECDSAParams; +#endif + typedef struct { bltestIO key; /* unused */ @@ -501,6 +729,9 @@ typedef union bltestRC5Params rc5; bltestRSAParams rsa; bltestDSAParams dsa; +#ifdef NSS_ENABLE_ECC + bltestECDSAParams ecdsa; +#endif bltestHashParams hash; } bltestParams; @@ -560,7 +791,11 @@ PRBool is_sigCipher(bltestCipherMode mode) { /* change as needed! */ +#ifdef NSS_ENABLE_ECC + if (mode >= bltestECDSA && mode <= bltestDSA) +#else if (mode >= bltestDSA && mode <= bltestDSA) +#endif return PR_TRUE; return PR_FALSE; } @@ -829,6 +1064,20 @@ dsa_verifyDigest(void *key, SECItem *output, const SECItem *input) return DSA_VerifyDigest((DSAPublicKey *)key, output, input); } +#ifdef NSS_ENABLE_ECC +SECStatus +ecdsa_signDigest(void *key, SECItem *output, const SECItem *input) +{ + return ECDSA_SignDigest((ECPrivateKey *)key, output, input); +} + +SECStatus +ecdsa_verifyDigest(void *key, SECItem *output, const SECItem *input) +{ + return ECDSA_VerifyDigest((ECPublicKey *)key, output, input); +} +#endif + SECStatus bltest_des_init(bltestCipherInfo *cipherInfo, PRBool encrypt) { @@ -1125,6 +1374,74 @@ bltest_dsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt) return SECSuccess; } +#ifdef NSS_ENABLE_ECC +SECStatus +bltest_ecdsa_init(bltestCipherInfo *cipherInfo, PRBool encrypt) +{ + int i; + ECPrivateKey **dummyKey; + PRIntervalTime time1, time2; + bltestECDSAParams *ecdsap = &cipherInfo->params.ecdsa; + /* ECDSA key gen was done during parameter setup */ + cipherInfo->cx = cipherInfo->params.ecdsa.eckey; + /* For performance testing */ + if (cipherInfo->cxreps > 0) { + /* Create space for n private key objects */ + dummyKey = (ECPrivateKey **)PORT_ZAlloc(cipherInfo->cxreps * + sizeof(ECPrivateKey *)); + /* Time n keygens, storing in the array */ + TIMESTART(); + for (i=0; icxreps; i++) { + EC_NewKey(&ecdsap->eckey->ecParams, &dummyKey[i]); + } + TIMEFINISH(cipherInfo->cxtime, cipherInfo->cxreps); + /* Free the n key objects */ + for (i=0; icxreps; i++) + PORT_FreeArena(dummyKey[i]->ecParams.arena, PR_TRUE); + PORT_Free(dummyKey); + } + if (!cipherInfo->cx && ecdsap->key.buf.len > 0) { + cipherInfo->cx = eckey_from_filedata(&ecdsap->key.buf); + } + if (encrypt) { + cipherInfo->cipher.pubkeyCipher = ecdsa_signDigest; + } else { + /* Have to convert private key to public key. Memory + * is freed with private key's arena */ + ECPublicKey *pubkey; + ECPrivateKey *key = (ECPrivateKey *)cipherInfo->cx; + pubkey = (ECPublicKey *)PORT_ArenaZAlloc(key->ecParams.arena, + sizeof(ECPublicKey)); + pubkey->ecParams.type = key->ecParams.type; + pubkey->ecParams.fieldID.size = key->ecParams.fieldID.size; + pubkey->ecParams.fieldID.type = key->ecParams.fieldID.type; + pubkey->ecParams.fieldID.u.prime.len = key->ecParams.fieldID.u.prime.len; + pubkey->ecParams.fieldID.u.prime.data = key->ecParams.fieldID.u.prime.data; + pubkey->ecParams.fieldID.k1 = key->ecParams.fieldID.k1; + pubkey->ecParams.fieldID.k2 = key->ecParams.fieldID.k2; + pubkey->ecParams.fieldID.k3 = key->ecParams.fieldID.k3; + pubkey->ecParams.curve.a.len = key->ecParams.curve.a.len; + pubkey->ecParams.curve.a.data = key->ecParams.curve.a.data; + pubkey->ecParams.curve.b.len = key->ecParams.curve.b.len; + pubkey->ecParams.curve.b.data = key->ecParams.curve.b.data; + pubkey->ecParams.curve.seed.len = key->ecParams.curve.seed.len; + pubkey->ecParams.curve.seed.data = key->ecParams.curve.seed.data; + pubkey->ecParams.base.len = key->ecParams.base.len; + pubkey->ecParams.base.data = key->ecParams.base.data; + pubkey->ecParams.order.len = key->ecParams.order.len; + pubkey->ecParams.order.data = key->ecParams.order.data; + pubkey->ecParams.cofactor = key->ecParams.cofactor; + pubkey->ecParams.DEREncoding.len = key->ecParams.DEREncoding.len; + pubkey->ecParams.DEREncoding.data = key->ecParams.DEREncoding.data; + pubkey->ecParams.name= key->ecParams.name; + pubkey->publicValue.len = key->publicValue.len; + pubkey->publicValue.data = key->publicValue.data; + cipherInfo->cipher.pubkeyCipher = ecdsa_verifyDigest; + } + return SECSuccess; +} +#endif + /* XXX unfortunately, this is not defined in blapi.h */ SECStatus md2_HashBuf(unsigned char *dest, const unsigned char *src, uint32 src_length) @@ -1374,12 +1691,22 @@ finish: SECStatus pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file, +#ifdef NSS_ENABLE_ECC + int keysize, int exponent, char *curveName) +#else int keysize, int exponent) +#endif { int i; SECStatus rv = SECSuccess; bltestRSAParams *rsap; bltestDSAParams *dsap; +#ifdef NSS_ENABLE_ECC + bltestECDSAParams *ecdsap; + SECItem *tmpECParamsDER; + ECParams *tmpECParams = NULL; + SECItem ecSerialize[3]; +#endif switch (cipherInfo->mode) { case bltestRSA: rsap = &cipherInfo->params.rsa; @@ -1412,6 +1739,37 @@ pubkeyInitKey(bltestCipherInfo *cipherInfo, PRFileDesc *file, dsap->j = PQG_PBITS_TO_INDEX(8*dsap->dsakey->params.prime.len); } break; +#ifdef NSS_ENABLE_ECC + case bltestECDSA: + ecdsap = &cipherInfo->params.ecdsa; + if (curveName != NULL) { + tmpECParamsDER = getECParams(curveName); + rv = secoid_Init(); + CHECKERROR(rv, __LINE__); + rv = EC_DecodeParams(tmpECParamsDER, &tmpECParams) == SECFailure; + CHECKERROR(rv, __LINE__); + rv = EC_NewKey(tmpECParams, &ecdsap->eckey); + CHECKERROR(rv, __LINE__); + ecSerialize[0].type = tmpECParamsDER->type; + ecSerialize[0].data = tmpECParamsDER->data; + ecSerialize[0].len = tmpECParamsDER->len; + ecSerialize[1].type = ecdsap->eckey->publicValue.type; + ecSerialize[1].data = ecdsap->eckey->publicValue.data; + ecSerialize[1].len = ecdsap->eckey->publicValue.len; + ecSerialize[2].type = ecdsap->eckey->privateValue.type; + ecSerialize[2].data = ecdsap->eckey->privateValue.data; + ecSerialize[2].len = ecdsap->eckey->privateValue.len; + serialize_key(&(ecSerialize[0]), 3, file); + free(tmpECParamsDER); + PORT_FreeArena(tmpECParams->arena, PR_TRUE); + rv = SECOID_Shutdown(); + CHECKERROR(rv, __LINE__); + } else { + setupIO(cipherInfo->arena, &cipherInfo->params.key, file, NULL, 0); + ecdsap->eckey = eckey_from_filedata(&cipherInfo->params.key.buf); + } + break; +#endif default: return SECFailure; } @@ -1466,6 +1824,13 @@ cipherInit(bltestCipherInfo *cipherInfo, PRBool encrypt) DSA_SIGNATURE_LEN); return bltest_dsa_init(cipherInfo, encrypt); break; +#ifdef NSS_ENABLE_ECC + case bltestECDSA: + SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, + 2 * MAX_ECKEY_LEN); + return bltest_ecdsa_init(cipherInfo, encrypt); + break; +#endif case bltestMD2: restart = cipherInfo->params.hash.restart; SECITEM_AllocItem(cipherInfo->arena, &cipherInfo->output.buf, @@ -1573,6 +1938,66 @@ dsaOp(bltestCipherInfo *cipherInfo) return rv; } +#ifdef NSS_ENABLE_ECC +SECStatus +ecdsaOp(bltestCipherInfo *cipherInfo) +{ + PRIntervalTime time1, time2; + SECStatus rv = SECSuccess; + int i; + int maxLen = cipherInfo->output.pBuf.len; + SECItem dummyOut = { 0, 0, 0 }; + SECITEM_AllocItem(NULL, &dummyOut, maxLen); + if (cipherInfo->cipher.pubkeyCipher == ecdsa_signDigest) { + if (cipherInfo->params.ecdsa.sigseed.buf.len > 0) { + rv = ECDSA_SignDigestWithSeed((ECPrivateKey *)cipherInfo->cx, + &cipherInfo->output.pBuf, + &cipherInfo->input.pBuf, + cipherInfo->params.ecdsa.sigseed.buf.data, + cipherInfo->params.ecdsa.sigseed.buf.len); + CHECKERROR(rv, __LINE__); + TIMESTART(); + for (i=0; irepetitions; i++) { + rv |= ECDSA_SignDigestWithSeed((ECPrivateKey *)cipherInfo->cx, + &dummyOut, + &cipherInfo->input.pBuf, + cipherInfo->params.ecdsa.sigseed.buf.data, + cipherInfo->params.ecdsa.sigseed.buf.len); + } + TIMEFINISH(cipherInfo->optime, 1.0); + CHECKERROR(rv, __LINE__); + } else { + rv = ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx, + &cipherInfo->output.pBuf, + &cipherInfo->input.pBuf); + CHECKERROR(rv, __LINE__); + TIMESTART(); + for (i=0; irepetitions; i++) { + ECDSA_SignDigest((ECPrivateKey *)cipherInfo->cx, &dummyOut, + &cipherInfo->input.pBuf); + } + TIMEFINISH(cipherInfo->optime, 1.0); + } + bltestCopyIO(cipherInfo->arena, &cipherInfo->params.ecdsa.sig, + &cipherInfo->output); + } else { + rv = ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx, + &cipherInfo->params.ecdsa.sig.buf, + &cipherInfo->input.pBuf); + CHECKERROR(rv, __LINE__); + TIMESTART(); + for (i=0; irepetitions; i++) { + ECDSA_VerifyDigest((ECPublicKey *)cipherInfo->cx, + &cipherInfo->params.ecdsa.sig.buf, + &cipherInfo->input.pBuf); + } + TIMEFINISH(cipherInfo->optime, 1.0); + } + SECITEM_FreeItem(&dummyOut, PR_FALSE); + return rv; +} +#endif + SECStatus cipherDoOp(bltestCipherInfo *cipherInfo) { @@ -1583,6 +2008,10 @@ cipherDoOp(bltestCipherInfo *cipherInfo) unsigned char *dummyOut; if (cipherInfo->mode == bltestDSA) return dsaOp(cipherInfo); +#ifdef NSS_ENABLE_ECC + else if (cipherInfo->mode == bltestECDSA) + return ecdsaOp(cipherInfo); +#endif dummyOut = PORT_Alloc(maxLen); if (is_symmkeyCipher(cipherInfo->mode)) { rv = (*cipherInfo->cipher.symmkeyCipher)(cipherInfo->cx, @@ -1657,6 +2086,9 @@ cipherFinish(bltestCipherInfo *cipherInfo) #endif case bltestRSA: /* keys are alloc'ed within cipherInfo's arena, */ case bltestDSA: /* will be freed with it. */ +#ifdef NSS_ENABLE_ECC + case bltestECDSA: +#endif case bltestMD2: /* hash contexts are ephemeral */ case bltestMD5: case bltestSHA1: @@ -1733,6 +2165,14 @@ print_td: else fprintf(stdout, "%8d", PQG_INDEX_TO_PBITS(info->params.dsa.j)); break; +#ifdef NSS_ENABLE_ECC + case bltestECDSA: + if (td) + fprintf(stdout, "%12s", "ec_curve"); + else + fprintf(stdout, "%12s", ecCurve_map[info->params.ecdsa.eckey->ecParams.name]->text); + break; +#endif case bltestMD2: case bltestMD5: case bltestSHA1: @@ -1877,6 +2317,18 @@ get_params(PRArenaPool *arena, bltestParams *params, sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j); load_file_data(arena, ¶ms->dsa.sig, filename, bltestBase64Encoded); break; +#ifdef NSS_ENABLE_ECC + case bltestECDSA: + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "key", j); + load_file_data(arena, ¶ms->ecdsa.key, filename, bltestBase64Encoded); + params->ecdsa.eckey = eckey_from_filedata(¶ms->key.buf); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "sigseed", j); + load_file_data(arena, ¶ms->ecdsa.sigseed, filename, + bltestBase64Encoded); + sprintf(filename, "%s/tests/%s/%s%d", testdir, modestr, "ciphertext",j); + load_file_data(arena, ¶ms->ecdsa.sig, filename, bltestBase64Encoded); + break; +#endif case bltestMD2: case bltestMD5: case bltestSHA1: @@ -1945,7 +2397,7 @@ blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff, bltestIO pt, ct; bltestCipherMode mode; bltestParams *params; - int i, j, nummodes; + int i, j, nummodes, numtests; char *modestr; char filename[256]; PRFileDesc *file; @@ -1993,7 +2445,12 @@ blapi_selftest(bltestCipherMode *modes, int numModes, int inoff, int outoff, #endif PR_Close(file); /* loop over the tests in the directory */ - for (j=0; j<(int)(item.data[0] - '0'); j++) { /* XXX bug when > 10 */ + numtests = (int) (item.data[0] - '0'); + for (j=1; jkey.mode = bltestBase64Encoded; +#ifdef NSS_ENABLE_ECC + pubkeyInitKey(&cipherInfo, file, keysize, exponent, curveName); +#else pubkeyInitKey(&cipherInfo, file, keysize, exponent); +#endif PR_Close(file); } @@ -2468,9 +2961,17 @@ int main(int argc, char **argv) exit(-1); } file = PR_Open(bltest.options[opt_SigFile].arg, PR_RDONLY, 00660); - memset(&cipherInfo.params.dsa.sig, 0, sizeof(bltestIO)); - cipherInfo.params.dsa.sig.mode = ioMode; - setupIO(cipherInfo.arena, &cipherInfo.params.dsa.sig, file, NULL, 0); + if (cipherInfo.mode == bltestDSA) { + memset(&cipherInfo.params.dsa.sig, 0, sizeof(bltestIO)); + cipherInfo.params.dsa.sig.mode = ioMode; + setupIO(cipherInfo.arena, &cipherInfo.params.dsa.sig, file, NULL, 0); +#ifdef NSS_ENABLE_ECC + } else if (cipherInfo.mode == bltestECDSA) { + memset(&cipherInfo.params.ecdsa.sig, 0, sizeof(bltestIO)); + cipherInfo.params.ecdsa.sig.mode = ioMode; + setupIO(cipherInfo.arena, &cipherInfo.params.ecdsa.sig, file, NULL, 0); +#endif + } } if (bltest.options[opt_PQGFile].activated) { diff --git a/security/nss/cmd/bltest/manifest.mn b/security/nss/cmd/bltest/manifest.mn index 2bbe10999556..3010842e776c 100644 --- a/security/nss/cmd/bltest/manifest.mn +++ b/security/nss/cmd/bltest/manifest.mn @@ -34,7 +34,7 @@ CORE_DEPTH = ../../.. MODULE = nss -REQUIRES = seccmd dbm +REQUIRES = seccmd dbm softoken INCLUDES += -I$(CORE_DEPTH)/nss/lib/softoken @@ -52,3 +52,7 @@ CSRCS = \ blapitest.c \ $(NULL) +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/cmd/bltest/tests/ecdsa/README b/security/nss/cmd/bltest/tests/ecdsa/README new file mode 100644 index 000000000000..764aeec810e4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/README @@ -0,0 +1,22 @@ +0 secp160k1 +1 secp160r1 +2 secp160r2 +3 nistk163 +4 sect163r1 +5 nistb163 +6 secp192k1 +7 nistp192 +8 secp224k1 +9 nistp224 +10 nistk233 +11 nistb233 +12 nistp256 +13 nistk283 +14 nistb283 +15 nistp384 +16 nistk409 +17 nistb409 +18 nistk571 +19 nistb571 +# the following tests are not yet implemented +#20 nistp521 diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext0 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext0 new file mode 100644 index 000000000000..14d8e0ece746 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext0 @@ -0,0 +1 @@ +GoWqve3YezF7HOABQjioFL/3oq32oM9pHsGTQTJE7aFE62nItVqAdg== diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext1 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext1 new file mode 100644 index 000000000000..4484aae6141c --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext1 @@ -0,0 +1 @@ +PM6xHbiwP6Xcb44mg7BHtaJvd8PkxgvHAB1sh2cF0so3naFf0Tj6vQ== diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext10 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext10 new file mode 100644 index 000000000000..a956d53a61cf --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext10 @@ -0,0 +1,2 @@ +AF3bbyED08NTrUgKmag9HiuUbaW0skXA/Bp9RPjRAD6M0rp3nvLDKozI940jxPP1 +nWpHF7VcyCVzJeV6 diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext11 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext11 new file mode 100644 index 000000000000..8cc2c262349d --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext11 @@ -0,0 +1,2 @@ +AOLrxy4FWd29ToUjOwLs6GyQ+dYZN6NkZ8oVO6dsAEXt55ePlCWZbOtmk6v9PrNG +JOsY/MHnGhDeAGRl diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext12 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext12 new file mode 100644 index 000000000000..5a05a78637f4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext12 @@ -0,0 +1,2 @@ +aQHMte9cFByD9Ff3rZOPOtPI75luPoxemmgjXIgh/9jEeoTdDk8xuAYQUkayCfs+ +DpDaGnOLkfAyZ8GcuaCujg== diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext13 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext13 new file mode 100644 index 000000000000..690c00a7156e --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext13 @@ -0,0 +1,2 @@ +AaeVCRJQPbpTqa1+zLd/8xAbkz3KKTr0dlS4tuGC8hc9j5esAeEv+7IklbA3v5Jz +jC+nJy4p81iNO5E9H8nfGGckfQSiFzHG diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext14 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext14 new file mode 100644 index 000000000000..fe527c6256a7 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext14 @@ -0,0 +1,2 @@ +AgU0N7zJPg/1UxmCWD5Z+DqDqkRKjy4heFgayCyopb/u4XErAZArgsjashAxzMKC +PSDJasPT90T5Va8sNtjXtSpHWxc2roV9 diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext15 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext15 new file mode 100644 index 000000000000..d1090942a2e1 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext15 @@ -0,0 +1,2 @@ +NXo8is+7lAoOwWGt7+GBbT/UX8LGs8TXEHBI+tX9311pJ4J3pfBYobgN0ZK6ZBtp +dS6PkrPaQp0S9nrfTOS5uAH95eD1eymRfCbOnjTUKzLuIn53V17vRjdcDtLzrhzX diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext16 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext16 new file mode 100644 index 000000000000..d5fe14482ad0 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext16 @@ -0,0 +1,3 @@ +ADhxjBz/ACTy4GJlL0tYZpyNpC4DsXND9lJuU7x9N7g6gkpJyBPw3vBYU1olw6PH +dnegpgAm4Gh6MCsZB4KBcLwl1wjt4B3p2eqEqDYn5fiie5f4XuRomvI92jR5Sb+I +nBLCHIppt/Q= diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext17 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext17 new file mode 100644 index 000000000000..486bf664f9bb --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext17 @@ -0,0 +1,3 @@ +AGhHQ6kfdZRgu1svQTXEIewvFVglnUy6ANPumyUbM14AEfRkCUNa1uzvhV1sbWYj +qT3egQCA9MTjThDNJeDOvvL6hVVOryUv4+C3RtkpQGCtdml+CSsjVTej8h9JbMds +Dme40b2G6fE= diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext18 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext18 new file mode 100644 index 000000000000..7eeef38118d0 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext18 @@ -0,0 +1,3 @@ +AGBuqk48tufy0bKEWpu+xEHsmi+6KCfdwOSRwLDnpVetGe9AWknHDzeTSwe0QxcE +RsEkUZGDpxfzUlCLSSSU+ErrYY/uyLV2AJTb3prB6A2YNwdmFGeRbDoxeOu7FuQA +3gxBQhR+TGMuskeM+BdHFmFrwvTTdHCGzjTBa5S8mbgEJTfeik/it28T/9i+duZ8 diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext19 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext19 new file mode 100644 index 000000000000..ef8e5f381889 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext19 @@ -0,0 +1,3 @@ +AaiotJfCiWU1d2LFe+t0CcWHDSF7EOlApWYJ+RNRSq8TbkXJIzi6abbb7BovtRwf +i/COYwjS7OnkFQ6x5Pdrb7OZ0dTAdDRXAKtXWSKR20Y4fhnx/HUxisFwKrsCEQ3O +uVtwDG8rh5V8zjBnCEcs5Iy9CsklucibR0PIyglVmW+ZuY42YNebuOC2VUKqHNF7 diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext2 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext2 new file mode 100644 index 000000000000..a3837a410566 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext2 @@ -0,0 +1 @@ +Vli8Hau3xL8oder6ZdM9Y3fMd92jbguiMq6F+9CUjlUQXy5EwAVGeg== diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext20 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext20 new file mode 100644 index 000000000000..67c99244a03d --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext20 @@ -0,0 +1,3 @@ +ALAM5hGnex7TvBbSEzDlfv+n5g7aWyRyZsBbl2Y6wW1plSovbq2GcV6w1ZV1Vlot +70zbqkKyNApvTi3xoD4Ens6pAeLMYDILwaQhnyJZWQv3etbWqUKJZNgfH1IDj03k +n9hbjYLX3y4bc4CnrhOiv5Ab34s7M8wUYcjC+DbHwhLl/S6N diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext3 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext3 new file mode 100644 index 000000000000..e9a480882b4d --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext3 @@ -0,0 +1 @@ +AFohw5TN/dpmqbhp/T4z1Rl1boAUA6r9eEPJbYN0zf+eHZzyvezxqjxU diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext4 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext4 new file mode 100644 index 000000000000..57ce239ab3b9 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext4 @@ -0,0 +1 @@ +AtJdCPXn5yQW34jekhsnsNmaMOeeA3KIVl1d2+7pb6QycUAzYccgwSrp diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext5 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext5 new file mode 100644 index 000000000000..e476c80bfca5 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext5 @@ -0,0 +1 @@ +AzEg0sOGHwxd0o3cv+o9dsRPOzXMAdpgtI6O0uUmVN2+a5qI5FYQlItz diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext6 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext6 new file mode 100644 index 000000000000..bdea7171d0bd --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext6 @@ -0,0 +1 @@ +5+HDXH/ieN8Bzxd3dfxKZoqbbhsm7jyeqWdemt6Xy0kx+7zwSYsh9Ng5KRdy6wtA diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext7 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext7 new file mode 100644 index 000000000000..3273fd9f73a6 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext7 @@ -0,0 +1 @@ +WcS9umnUASP0X6lHvkWJwPY37ZVvAMLBERHLjL3Vzg6QVjwcS8kDVortTFei3aTx diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext8 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext8 new file mode 100644 index 000000000000..636392e4358b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext8 @@ -0,0 +1,2 @@ +ItpmPaGAaoe2feXPbh5+EASLGnEzyYbEnwJ+JFNSOQcoY4a/cMV2rn8FYyBsEDiZ +LPDBU0i2uOg= diff --git a/security/nss/cmd/bltest/tests/ecdsa/ciphertext9 b/security/nss/cmd/bltest/tests/ecdsa/ciphertext9 new file mode 100644 index 000000000000..0c43fa3d796b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/ciphertext9 @@ -0,0 +1,2 @@ +QjzCVGRUjulOLqeBqC5xpY0GWomOrmQUCtImY0czn98a/jHrdgsSRKiMHukBUxM1 +TIRGjkV2L+A= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key0 b/security/nss/cmd/bltest/tests/ecdsa/key0 new file mode 100644 index 000000000000..7c6d61b361d5 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key0 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAAkAAAApBPiF0ntSFtn41JULxlA1l/lHE/zUPGJWkCqtdOryS6yD +WFCoF/IHwHsAAAAUcw+b2b1AJUlmezgu5EjmAGPC0YQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key1 b/security/nss/cmd/bltest/tests/ecdsa/key1 new file mode 100644 index 000000000000..049aa1edbcec --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key1 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAAgAAAApBI80VWK9xatmkFRiDTcdeFQ0T9h3h6iVOinMURyWZw0T +5vZqd8/gvwwAAAAUYOQMjDdtNSL5zY0nVWPWY+UJoqQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key10 b/security/nss/cmd/bltest/tests/ecdsa/key10 new file mode 100644 index 000000000000..3e3341714314 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key10 @@ -0,0 +1,3 @@ +AAAABwYFK4EEABoAAAA9BACmzalMQJBOWV2FoyV0tXSpT07Xajq4bB1SUwSY7QGn +dgGC3GBqjPs9vEpqfMMQ2M9k3+5oubWnexNFhQAAAB4BRha/6sE7VSHl92ZqCj5p +LYtBpK23jzfdVWO8SAY= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key11 b/security/nss/cmd/bltest/tests/ecdsa/key11 new file mode 100644 index 000000000000..6111d52ad7d6 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key11 @@ -0,0 +1,3 @@ +AAAABwYFK4EEABsAAAA9BAD2/x9HSYYVEQ9AU4MivlIKPypJjsm0sTrp8BftlQGv +KaYrKpZCg/CEw3C2kqvke7HAu+10hafK9asRxQAAAB4AXyFCurtsXhahkyJpkb5J +LUg3xVL00vviR0KyFZY= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key12 b/security/nss/cmd/bltest/tests/ecdsa/key12 new file mode 100644 index 000000000000..491fdba1b8c3 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key12 @@ -0,0 +1,3 @@ +AAAACgYIKoZIzj0DAQcAAABBBNGB7n4kH15tKA/SMpetaQVqg6WxIuuUuMQT2tDX +NN5jKZfaxD47NsTjTr3x3D5t1qRBYuL6VtdgIuxBIHGG9dcAAAAgaGjyZBL+LN3a +7NkGiHJBfqh7XKNH0AnPF3vFWpostIQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key13 b/security/nss/cmd/bltest/tests/ecdsa/key13 new file mode 100644 index 000000000000..fc8057a57ebd --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key13 @@ -0,0 +1,3 @@ +AAAABwYFK4EEABAAAABJBAT3klWkt7+1Pr6QGEcvEIZplopwt1alrsJUThDOxvUF +7KvBpQLVjB+DQTwYQnEREb/WFyRgUBuIbII0+zd/g0fLHE4PQ8SNlAAAACQFPsMX +mqSVRreUVasUOIZQFB2jnpwCUyoq+xa9SRril5LeOCY= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key14 b/security/nss/cmd/bltest/tests/ecdsa/key14 new file mode 100644 index 000000000000..2e158236cb22 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key14 @@ -0,0 +1,3 @@ +AAAABwYFK4EEABEAAABJBAf/ei/XCrFrMZLBp5BFkKZ3Odn+ZJu7QIAK32Ubuxmi +xgWTewf2vv+KY5kHwsBYuBXmmnKe9Ak9zGP4Lykvgk5n5J6iUz5ycQAAACQAQHXa +d29OqGxoDNCl9xETW3tAL/2hfZzstNuOPLm5kj4j1Dc= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key15 b/security/nss/cmd/bltest/tests/ecdsa/key15 new file mode 100644 index 000000000000..a062f1f67ba4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key15 @@ -0,0 +1,4 @@ +AAAABwYFK4EEACIAAABhBLWMJG3t4khPYcsl3H492rAqukJ1RqJm27pqpN54rFGG +r2VDwOfqb9tMninq8IyOh42eaaVOEPXXu4Q/ATWBEfrbTRBjTpzAE2SSPuQma0lM +q0RSVECCgdBOKIhB0H6VxAAAADA3WPjUaMWCS9E5KbVDrEcf5CV5tCNNWJQkwjsA +yALMCiXJqRVXwbq42WMuaELMW+g= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key16 b/security/nss/cmd/bltest/tests/ecdsa/key16 new file mode 100644 index 000000000000..d2694ae4128f --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key16 @@ -0,0 +1,4 @@ +AAAABwYFK4EEACQAAABpBADkgknFgTPuirxQxFlqIK+vcARWzlpJR+qmyRyQsBiz +Nh6Ws036xUKY9M8LxMIWXFNM6aIA2wxKsBF+HHD6oy27EAJSJOGbke/9F9Kv5AiW +2RXA4mllUaxCNsuQ36PqUdqv4FeXxWTpAAAANAHTZloqhR0V4bfyaeo2hojcvY3T +NO04ewNryBpsHZ0bhID0EfewYuwQmX00GYNfuV3mJ2w= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key17 b/security/nss/cmd/bltest/tests/ecdsa/key17 new file mode 100644 index 000000000000..30be05774dc7 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key17 @@ -0,0 +1,4 @@ +AAAABwYFK4EEACUAAABpBAAEE/bAmqCjO3FLvN93Q/UjDyDp2sj+F//buuf1hZ0K +1rSOGXMLcBrqVa8R6UJ57F9/Yc0BCTylpJMXjfCr4eDczG4WOQk+5x8kpKQs5Q9U +V3IolHDiQY/Nhn7o4UFn5/mF71T3qUqwAAAANAH/o7jEl9Bw+Arj9uQ7ZHkoPGgx +t92UJg1r/lxa7UUd66iJfRI8n8yQH/sw56D1+CweeII= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key18 b/security/nss/cmd/bltest/tests/ecdsa/key18 new file mode 100644 index 000000000000..bbdcb137110b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key18 @@ -0,0 +1,5 @@ +AAAABwYFK4EEACYAAACRBAffZTrfwIl0dciO2fui3UhZw6r+jnFh7gyER92gXL7+ +LzPgTHagd1vdQiIX4K8Dv76KN0BldiFuX5odP7qC26MUaiURDdWT0AWcPmumSSBH +NXZYLLx5hQjW3BTNwV7v5bmUjezfgtuOCC30dQGs2GMgExAmiWRjTkiPrHg1SFKF +3RklauOyMWauaVpEzh3c+wAAAEgAZvLs4/Rx7tS+QGH92fGGIxPWPbVYOpDKwabY +poV2i1BD5Fxvw+eHlvxVOLmRPqRCPTfOLwAeNbHyt17U/BVZ8+svTChlzuA= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key19 b/security/nss/cmd/bltest/tests/ecdsa/key19 new file mode 100644 index 000000000000..31b4071f2e2e --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key19 @@ -0,0 +1,5 @@ +AAAABwYFK4EEACcAAACRBASpPvOfQVqiMD+cBL/nulFit5pk/5beJ6/KpeIltg4s +6/s7PPggJA59BP7RJwak6rgY3PsRqXVPjyM/1UkUfRUR2BJgOfNTkQe9WF7Y5zXy +TM76cWhOP+sLSoUcscy/HTLCpHqRLLvWZPDzgjrfJqSlydMEDZjWsJRVPk9IfeQ/ +amGiWOhJIQd/bSrAazZn6AAAAEgFz1qZzjHuhuP1boJ7gzndJhQslx1efbESxHSc +wbOpeBpw2MsCAwjtgo3Y8pviFIC8+5MStkFjE8uHQ0ngXc02wm3G0xj8XGQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key2 b/security/nss/cmd/bltest/tests/ecdsa/key2 new file mode 100644 index 000000000000..f4ba6f2f2be5 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key2 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAB4AAAApBGouC+vgvmItzsLO4hXn+AXi3skEE+M19o/QHLfjibbA +p7av8F4tcGgAAAAUmpQDUgnIkiXPBs0moD4jEmJHato= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key20 b/security/nss/cmd/bltest/tests/ecdsa/key20 new file mode 100644 index 000000000000..c4da3486de9b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key20 @@ -0,0 +1,5 @@ +AAAABwYFK4EEACMAAACFBAHLMSpMFVyG6mXE7SZ5O5Bwv4d8/QiAB3BzpXkyrU1W +jJ9O9uOYTXM+cFtF5v56+LsI4yGkaAl9+RF6lFPjrhpIswCmBmEqMBgZpjoz38my +nLHBI9MaFF8AHkRQwD3LJLo4eSZHOVkdIvDYLwicdlgr0zD3Nf76/HB1+0DkBGqE +MyG22gAAAEIAFah7z179UbqqdH68pzdZsP1ChXjtYZ11rBM0+HP7yLirxH3ahKTt +DjsY19GEjz4gKsaLfLiQ1/Dp+VKVLcBKpk0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key3 b/security/nss/cmd/bltest/tests/ecdsa/key3 new file mode 100644 index 000000000000..689e06bda592 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key3 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAAEAAAArBAe4qW9DTVGRVIYYznwJZbn8mWXLugA2A+Mv112Bu+y7 +gxI8E4/fEdLTsQAAABUGEQDNcbxi0JhwALA8FCCxvmWYM3E= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key4 b/security/nss/cmd/bltest/tests/ecdsa/key4 new file mode 100644 index 000000000000..90ecb72c6fde --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key4 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAAIAAAArBAXw45Pc59l1QWmAB1W6M30lyFzQmAH/0FIFKYgEOYIa +dnEXMwKNwaRdsQAAABUCErj052f+Rth5OxAm376LOAQyvBY= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key5 b/security/nss/cmd/bltest/tests/ecdsa/key5 new file mode 100644 index 000000000000..b9d221f8e5f0 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key5 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAA8AAAArBAFhm71N2wsUOYCwDNr/6rFvNX1okAbki1SNlHq2TQDO +Bktd1M0jlApWVQAAABUCILsraWg3Qi5nBsXQ1pGmZk0YuSA= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key6 b/security/nss/cmd/bltest/tests/ecdsa/key6 new file mode 100644 index 000000000000..92fb463dc5d5 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key6 @@ -0,0 +1,2 @@ +AAAABwYFK4EEAB8AAAAxBHOYACoc9XsLk5n8NZZKV2U9CDoMj/VRDvqbf+myloR7 +uBfVNm+uVN33Sa65phAfXQAAABitxs6KZtkqU4tglcdQ1Rmk2U74vjYP0JM= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key7 b/security/nss/cmd/bltest/tests/ecdsa/key7 new file mode 100644 index 000000000000..83fced184459 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key7 @@ -0,0 +1,2 @@ +AAAACgYIKoZIzj0DAQEAAAAxBOyOI+rIs3x+jsChxQqSVblnoZGqhIM1WX0FMfw+ +D8Dz6Y25iPcAQFpIAWh29FxnrgAAABh+uEQYXwMB783sULxE6PEd1t/MNZ9HSHI= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key8 b/security/nss/cmd/bltest/tests/ecdsa/key8 new file mode 100644 index 000000000000..cc7c6103b539 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key8 @@ -0,0 +1,3 @@ +AAAABwYFK4EEACAAAAA5BKQnZoj4VtlPqrJ5dekM4haG+7PjfgO4wNNIqD7JnrKI +gTUd+oUQ41d517xCObyBaHNzdVPty9DvAAAAHIrG9+FE+OJV5UV2l/op7PCDPI4G +qkpgzPIwe7U= diff --git a/security/nss/cmd/bltest/tests/ecdsa/key9 b/security/nss/cmd/bltest/tests/ecdsa/key9 new file mode 100644 index 000000000000..ab8f43bae6ea --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/key9 @@ -0,0 +1,3 @@ +AAAABwYFK4EEACEAAAA5BGCNDWldzQCbI83PMR96tqR6JnIUpvfIO8l6hIf/QfMc +rx2BbrSLoy6EJmP++Jyw5yNyaoVaNYl6AAAAHDnjgcUSIshTSLuejnSsvtvU363b +1NJv4ULUbIs= diff --git a/security/nss/cmd/bltest/tests/ecdsa/numtests b/security/nss/cmd/bltest/tests/ecdsa/numtests new file mode 100644 index 000000000000..aabe6ec3909c --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/numtests @@ -0,0 +1 @@ +21 diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext0 b/security/nss/cmd/bltest/tests/ecdsa/plaintext0 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext0 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext1 b/security/nss/cmd/bltest/tests/ecdsa/plaintext1 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext1 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext10 b/security/nss/cmd/bltest/tests/ecdsa/plaintext10 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext10 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext11 b/security/nss/cmd/bltest/tests/ecdsa/plaintext11 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext11 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext12 b/security/nss/cmd/bltest/tests/ecdsa/plaintext12 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext12 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext13 b/security/nss/cmd/bltest/tests/ecdsa/plaintext13 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext13 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext14 b/security/nss/cmd/bltest/tests/ecdsa/plaintext14 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext14 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext15 b/security/nss/cmd/bltest/tests/ecdsa/plaintext15 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext15 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext16 b/security/nss/cmd/bltest/tests/ecdsa/plaintext16 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext16 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext17 b/security/nss/cmd/bltest/tests/ecdsa/plaintext17 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext17 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext18 b/security/nss/cmd/bltest/tests/ecdsa/plaintext18 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext18 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext19 b/security/nss/cmd/bltest/tests/ecdsa/plaintext19 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext19 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext2 b/security/nss/cmd/bltest/tests/ecdsa/plaintext2 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext2 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext20 b/security/nss/cmd/bltest/tests/ecdsa/plaintext20 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext20 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext3 b/security/nss/cmd/bltest/tests/ecdsa/plaintext3 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext3 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext4 b/security/nss/cmd/bltest/tests/ecdsa/plaintext4 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext4 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext5 b/security/nss/cmd/bltest/tests/ecdsa/plaintext5 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext5 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext6 b/security/nss/cmd/bltest/tests/ecdsa/plaintext6 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext6 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext7 b/security/nss/cmd/bltest/tests/ecdsa/plaintext7 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext7 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext8 b/security/nss/cmd/bltest/tests/ecdsa/plaintext8 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext8 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/plaintext9 b/security/nss/cmd/bltest/tests/ecdsa/plaintext9 new file mode 100644 index 000000000000..48fbdb6fdef4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/plaintext9 @@ -0,0 +1 @@ +qZk+NkcGgWq6PiVxeFDCbJzQ2J0= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed0 b/security/nss/cmd/bltest/tests/ecdsa/sigseed0 new file mode 100644 index 000000000000..05d7fd2d65b4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed0 @@ -0,0 +1 @@ +aHpm2QZI+ZOGfhIfTd+d2wEgVYQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed1 b/security/nss/cmd/bltest/tests/ecdsa/sigseed1 new file mode 100644 index 000000000000..05d7fd2d65b4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed1 @@ -0,0 +1 @@ +aHpm2QZI+ZOGfhIfTd+d2wEgVYQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed10 b/security/nss/cmd/bltest/tests/ecdsa/sigseed10 new file mode 100644 index 000000000000..6983e5f7d654 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed10 @@ -0,0 +1 @@ +fjIzMWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed11 b/security/nss/cmd/bltest/tests/ecdsa/sigseed11 new file mode 100644 index 000000000000..6983e5f7d654 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed11 @@ -0,0 +1 @@ +fjIzMWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed12 b/security/nss/cmd/bltest/tests/ecdsa/sigseed12 new file mode 100644 index 000000000000..92aa40c82a46 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed12 @@ -0,0 +1 @@ +/jI1NmJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDk= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed13 b/security/nss/cmd/bltest/tests/ecdsa/sigseed13 new file mode 100644 index 000000000000..4ac0765848f7 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed13 @@ -0,0 +1 @@ +ATI4MWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBi diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed14 b/security/nss/cmd/bltest/tests/ecdsa/sigseed14 new file mode 100644 index 000000000000..4ac0765848f7 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed14 @@ -0,0 +1 @@ +ATI4MWJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBi diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed15 b/security/nss/cmd/bltest/tests/ecdsa/sigseed15 new file mode 100644 index 000000000000..0975230325ef --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed15 @@ -0,0 +1 @@ +/jM4NGJpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYxMDEx diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed16 b/security/nss/cmd/bltest/tests/ecdsa/sigseed16 new file mode 100644 index 000000000000..36fbf0951355 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed16 @@ -0,0 +1 @@ +fjQwN2JpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYxMDExMTIx diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed17 b/security/nss/cmd/bltest/tests/ecdsa/sigseed17 new file mode 100644 index 000000000000..36fbf0951355 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed17 @@ -0,0 +1 @@ +fjQwN2JpdHNPZlRleHQwMTAyMDMwNDA1MDYwNzA4MDkwYTBiMGMwZDBlMGYxMDExMTIx diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed18 b/security/nss/cmd/bltest/tests/ecdsa/sigseed18 new file mode 100644 index 000000000000..7be8ce6dd98b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed18 @@ -0,0 +1,2 @@ +PjU2NmJpdHNPZlRleHQwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwMTExMjEz +MTQxNTE2MTcxODE5MWExYjE= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed19 b/security/nss/cmd/bltest/tests/ecdsa/sigseed19 new file mode 100644 index 000000000000..7be8ce6dd98b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed19 @@ -0,0 +1,2 @@ +PjU2NmJpdHNPZlRleHQwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwMTExMjEz +MTQxNTE2MTcxODE5MWExYjE= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed2 b/security/nss/cmd/bltest/tests/ecdsa/sigseed2 new file mode 100644 index 000000000000..05d7fd2d65b4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed2 @@ -0,0 +1 @@ +aHpm2QZI+ZOGfhIfTd+d2wEgVYQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed20 b/security/nss/cmd/bltest/tests/ecdsa/sigseed20 new file mode 100644 index 000000000000..f0dddb66c766 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed20 @@ -0,0 +1,2 @@ +/jUyMGJpdHNPZlRleHQwMDAxMDIwMzA0MDUwNjA3MDgwOTBhMGIwYzBkMGUwZjEwMTExMjEz +MTQxNTE2MTcxODE= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed3 b/security/nss/cmd/bltest/tests/ecdsa/sigseed3 new file mode 100644 index 000000000000..05d7fd2d65b4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed3 @@ -0,0 +1 @@ +aHpm2QZI+ZOGfhIfTd+d2wEgVYQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed4 b/security/nss/cmd/bltest/tests/ecdsa/sigseed4 new file mode 100644 index 000000000000..05d7fd2d65b4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed4 @@ -0,0 +1 @@ +aHpm2QZI+ZOGfhIfTd+d2wEgVYQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed5 b/security/nss/cmd/bltest/tests/ecdsa/sigseed5 new file mode 100644 index 000000000000..05d7fd2d65b4 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed5 @@ -0,0 +1 @@ +aHpm2QZI+ZOGfhIfTd+d2wEgVYQ= diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed6 b/security/nss/cmd/bltest/tests/ecdsa/sigseed6 new file mode 100644 index 000000000000..a0687196c423 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed6 @@ -0,0 +1 @@ +/jE5MmJpdHNPZlRleHQwMDAwMDAwMDAw diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed7 b/security/nss/cmd/bltest/tests/ecdsa/sigseed7 new file mode 100644 index 000000000000..a0687196c423 --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed7 @@ -0,0 +1 @@ +/jE5MmJpdHNPZlRleHQwMDAwMDAwMDAw diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed8 b/security/nss/cmd/bltest/tests/ecdsa/sigseed8 new file mode 100644 index 000000000000..01ae2657400b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed8 @@ -0,0 +1 @@ +/jIyNGJpdHNPZlRleHQwMDAwMDAwMDAwMDAwMA== diff --git a/security/nss/cmd/bltest/tests/ecdsa/sigseed9 b/security/nss/cmd/bltest/tests/ecdsa/sigseed9 new file mode 100644 index 000000000000..01ae2657400b --- /dev/null +++ b/security/nss/cmd/bltest/tests/ecdsa/sigseed9 @@ -0,0 +1 @@ +/jIyNGJpdHNPZlRleHQwMDAwMDAwMDAwMDAwMA== diff --git a/security/nss/cmd/certutil/certutil.c b/security/nss/cmd/certutil/certutil.c index 06029c4e18d1..b313089e05e6 100644 --- a/security/nss/cmd/certutil/certutil.c +++ b/security/nss/cmd/certutil/certutil.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -281,7 +285,7 @@ AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, PRFileDesc *inFile, PRBool ascii, PRBool emailcert, void *pwdata) { CERTCertTrust *trust = NULL; - CERTCertificate *cert = NULL, *tempCert = NULL; + CERTCertificate *cert = NULL; SECItem certDER; SECStatus rv; @@ -382,6 +386,12 @@ getSignatureOidTag(KeyType keyType, SECOidTag hashAlgTag) break; } break; +#ifdef NSS_ENABLE_ECC + case ecKey: + /* XXX For now only ECDSA with SHA1 is supported */ + sigTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + break; +#endif /* NSS_ENABLE_ECC */ default: break; } @@ -975,8 +985,15 @@ Usage(char *progName) "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n" "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); +#ifdef NSS_ENABLE_ECC + FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n" + "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); + FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n", + progName); +#else FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n", progName); +#endif /* NSS_ENABLE_ECC */ FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n"); FPS "\t%s -L [-n cert-name] [-X] [-d certdir] [-P dbprefix] [-r] [-a]\n", progName); FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n", @@ -989,7 +1006,7 @@ Usage(char *progName) "\t\t[-X] [-d certdir] [-P dbprefix]\n", progName); FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n" - "\t\t [-k key-type] [-h token-name] [-g key-size]\n" + "\t\t [-k key-type] [-q key-params] [-h token-name] [-g key-size]\n" "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n" "\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n" "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n" @@ -1076,10 +1093,17 @@ static void LongUsage(char *progName) "-G"); FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", + " -k key-type"); + FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n", + " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); +#else FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", " -k key-type"); FPS "%-20s Key size in bits, (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); +#endif /* NSS_ENABLE_ECC */ FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n", " -y exp"); FPS "%-20s Specify the password file\n", @@ -1088,6 +1112,27 @@ static void LongUsage(char *progName) " -z noisefile"); FPS "%-20s read PQG value from pqgfile (dsa only)\n", " -q pqgfile"); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Elliptic curve name (ec only)\n", + " -q curve-name"); + FPS "%-20s One of sect163k1, nistk163, sect163r1, sect163r2,\n", ""); + FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", ""); + FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", ""); + FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", ""); + FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", ""); + FPS "%-20s secp169k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", ""); + FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", ""); + FPS "%-20s secp256r1, nistp256, secp384r1, nistp384, secp521r1,\n", ""); + FPS "%-20s nistp521, prime192v1, prime192v2, prime192v3, \n", ""); + FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", ""); + FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", ""); + FPS "%-20s c2tnb191v2, c2tnb191v3, c2onb191v4, c2onb191v5, \n", ""); + FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", ""); + FPS "%-20s c2onb239v4, c2onb239v5, c2pnb272w1, c2pnb304w1, \n", ""); + FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", ""); + FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", ""); + FPS "%-20s sect131r1, sect131r2\n", ""); +#endif FPS "%-20s Key database directory (default is ~/.netscape)\n", " -d keydir"); FPS "%-20s Cert & Key database prefix\n", @@ -1119,8 +1164,13 @@ static void LongUsage(char *progName) FPS "%-20s Name of token in which to look for keys (default is internal," " use \"all\" to list keys on all tokens)\n", " -h token-name "); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Type of key pair to list (\"all\", \"dsa\", \"ec\", \"rsa\" (default))\n", + " -k key-type"); +#else FPS "%-20s Type of key pair to list (\"all\", \"dsa\", \"rsa\" (default))\n", " -k key-type"); +#endif FPS "%-20s Specify the password file\n", " -f password-file"); FPS "%-20s Key database directory (default is ~/.netscape)\n", @@ -1195,12 +1245,25 @@ static void LongUsage(char *progName) " -s subject"); FPS "%-20s Output the cert request to this file\n", " -o output-req"); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", + " -k key-type"); +#else FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", " -k key-type"); +#endif /* NSS_ENABLE_ECC */ FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); + FPS "%-20s Name of file containing PQG parameters (dsa only)\n", + " -q pqgfile"); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Elliptic curve name (ec only)\n", + " -q curve-name"); + FPS "%-20s See the \"-G\" option for a full list of supported names.\n", + ""); +#endif /* NSS_ENABLE_ECC */ FPS "%-20s Specify the password file\n", " -f pwfile"); FPS "%-20s Key database directory (default is ~/.netscape)\n", @@ -1244,12 +1307,25 @@ static void LongUsage(char *progName) " -c issuer-name"); FPS "%-20s Set the certificate trust attributes (see -A above)\n", " -t trustargs"); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", + " -k key-type"); +#else FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", " -k key-type"); +#endif /* NSS_ENABLE_ECC */ FPS "%-20s Name of token in which to generate key (default is internal)\n", " -h token-name"); FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); + FPS "%-20s Name of file containing PQG parameters (dsa only)\n", + " -q pqgfile"); +#ifdef NSS_ENABLE_ECC + FPS "%-20s Elliptic curve name (ec only)\n", + " -q curve-name"); + FPS "%-20s See the \"-G\" option for a full list of supported names.\n", + ""); +#endif /* NSS_ENABLE_ECC */ FPS "%-20s Self sign\n", " -x"); FPS "%-20s Cert serial number\n", @@ -2335,9 +2411,16 @@ secuCommandFlag certutil_options[] = if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) { PR_fprintf(PR_STDERR, "%s -g: Keysize must be between %d and %d.\n", - MIN_KEY_BITS, MAX_KEY_BITS); + progName, MIN_KEY_BITS, MAX_KEY_BITS); return 255; } +#ifdef NSS_ENABLE_ECC + if (keytype == ecKey) { + PR_fprintf(PR_STDERR, "%s -g: Not for ec keys.\n", progName); + return 255; + } +#endif /* NSS_ENABLE_ECC */ + } /* -h specify token name */ @@ -2379,6 +2462,10 @@ secuCommandFlag certutil_options[] = keytype = rsaKey; } else if (PL_strcmp(arg, "dsa") == 0) { keytype = dsaKey; +#ifdef NSS_ENABLE_ECC + } else if (PL_strcmp(arg, "ec") == 0) { + keytype = ecKey; +#endif /* NSS_ENABLE_ECC */ } else if (PL_strcmp(arg, "all") == 0) { keytype = nullKey; } else { @@ -2403,11 +2490,18 @@ secuCommandFlag certutil_options[] = if (certutil.options[opt_DBPrefix].activated) certPrefix = strdup(certutil.options[opt_DBPrefix].arg); - /* -q PQG file */ + /* -q PQG file or curve name */ if (certutil.options[opt_PQGFile].activated) { +#ifdef NSS_ENABLE_ECC + if ((keytype != dsaKey) && (keytype != ecKey)) { + PR_fprintf(PR_STDERR, "%s -q: specifies a PQG file for DSA keys" \ + " (-k dsa) or a named curve for EC keys (-k ec)\n)", + progName); +#else if (keytype != dsaKey) { PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)", progName); +#endif /* NSS_ENABLE_ECC */ return 255; } } diff --git a/security/nss/cmd/certutil/keystuff.c b/security/nss/cmd/certutil/keystuff.c index 901b64fc4a07..66661c7bcff1 100644 --- a/security/nss/cmd/certutil/keystuff.c +++ b/security/nss/cmd/certutil/keystuff.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -335,6 +339,136 @@ void CERTUTIL_FileForRNG(char *noise) } +#ifdef NSS_ENABLE_ECC +typedef struct curveNameTagPairStr { + char *curveName; + SECOidTag curveOidTag; +} CurveNameTagPair; + +#define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 +/* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ + +static CurveNameTagPair nameTagPair[] = +{ + { "sect163k1", SEC_OID_SECG_EC_SECT163K1}, + { "nistk163", SEC_OID_SECG_EC_SECT163K1}, + { "sect163r1", SEC_OID_SECG_EC_SECT163R1}, + { "sect163r2", SEC_OID_SECG_EC_SECT163R2}, + { "nistb163", SEC_OID_SECG_EC_SECT163R2}, + { "sect193r1", SEC_OID_SECG_EC_SECT193R1}, + { "sect193r2", SEC_OID_SECG_EC_SECT193R2}, + { "sect233k1", SEC_OID_SECG_EC_SECT233K1}, + { "nistk233", SEC_OID_SECG_EC_SECT233K1}, + { "sect233r1", SEC_OID_SECG_EC_SECT233R1}, + { "nistb233", SEC_OID_SECG_EC_SECT233R1}, + { "sect239k1", SEC_OID_SECG_EC_SECT239K1}, + { "sect283k1", SEC_OID_SECG_EC_SECT283K1}, + { "nistk283", SEC_OID_SECG_EC_SECT283K1}, + { "sect283r1", SEC_OID_SECG_EC_SECT283R1}, + { "nistb283", SEC_OID_SECG_EC_SECT283R1}, + { "sect409k1", SEC_OID_SECG_EC_SECT409K1}, + { "nistk409", SEC_OID_SECG_EC_SECT409K1}, + { "sect409r1", SEC_OID_SECG_EC_SECT409R1}, + { "nistb409", SEC_OID_SECG_EC_SECT409R1}, + { "sect571k1", SEC_OID_SECG_EC_SECT571K1}, + { "nistk571", SEC_OID_SECG_EC_SECT571K1}, + { "sect571r1", SEC_OID_SECG_EC_SECT571R1}, + { "nistb571", SEC_OID_SECG_EC_SECT571R1}, + { "secp160k1", SEC_OID_SECG_EC_SECP160K1}, + { "secp160r1", SEC_OID_SECG_EC_SECP160R1}, + { "secp160r2", SEC_OID_SECG_EC_SECP160R2}, + { "secp192k1", SEC_OID_SECG_EC_SECP192K1}, + { "secp192r1", SEC_OID_SECG_EC_SECP192R1}, + { "nistp192", SEC_OID_SECG_EC_SECP192R1}, + { "secp224k1", SEC_OID_SECG_EC_SECP224K1}, + { "secp224r1", SEC_OID_SECG_EC_SECP224R1}, + { "nistp224", SEC_OID_SECG_EC_SECP224R1}, + { "secp256k1", SEC_OID_SECG_EC_SECP256K1}, + { "secp256r1", SEC_OID_SECG_EC_SECP256R1}, + { "nistp256", SEC_OID_SECG_EC_SECP256R1}, + { "secp384r1", SEC_OID_SECG_EC_SECP384R1}, + { "nistp384", SEC_OID_SECG_EC_SECP384R1}, + { "secp521r1", SEC_OID_SECG_EC_SECP521R1}, + { "nistp521", SEC_OID_SECG_EC_SECP521R1}, + + { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, + { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, + { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, + { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, + { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, + { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, + + { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, + { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, + { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, + { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, + { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, + { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, + { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, + { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, + { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, + { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, + { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, + { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, + { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, + { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, + { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, + { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, + { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, + { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, + { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, + { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, + + { "secp112r1", SEC_OID_SECG_EC_SECP112R1}, + { "secp112r2", SEC_OID_SECG_EC_SECP112R2}, + { "secp128r1", SEC_OID_SECG_EC_SECP128R1}, + { "secp128r2", SEC_OID_SECG_EC_SECP128R2}, + + { "sect113r1", SEC_OID_SECG_EC_SECT113R1}, + { "sect113r2", SEC_OID_SECG_EC_SECT113R2}, + { "sect131r1", SEC_OID_SECG_EC_SECT131R1}, + { "sect131r2", SEC_OID_SECG_EC_SECT131R2}, +}; + +static SECKEYECParams * +getECParams(char *curve) +{ + SECKEYECParams *ecparams; + SECOidData *oidData = NULL; + SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ + int i, numCurves; + + if (curve != NULL) { + numCurves = sizeof(nameTagPair)/sizeof(CurveNameTagPair); + for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); + i++) { + if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) + curveOidTag = nameTagPair[i].curveOidTag; + } + } + + /* Return NULL if curve name is not recognized */ + if ((curveOidTag == SEC_OID_UNKNOWN) || + (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { + fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); + return NULL; + } + + ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); + + /* + * ecparams->data needs to contain the ASN encoding of an object ID (OID) + * representing the named curve. The actual OID is in + * oidData->oid.data so we simply prepend 0x06 and OID length + */ + ecparams->data[0] = SEC_ASN1_OBJECT_ID; + ecparams->data[1] = oidData->oid.len; + memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); + + return ecparams; +} +#endif /* NSS_ENABLE_ECC */ + SECKEYPrivateKey * CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, int publicExponent, char *noise, @@ -390,13 +524,20 @@ CERTUTIL_GeneratePrivateKey(KeyType keytype, PK11SlotInfo *slot, int size, } params = dsaparams; break; +#ifdef NSS_ENABLE_ECC + case ecKey: + mechanism = CKM_EC_KEY_PAIR_GEN; + /* For EC keys, PQGFile determines EC parameters */ + if ((params = (void *) getECParams(pqgFile)) == NULL) + return NULL; + break; +#endif /* NSS_ENABLE_ECC */ default: return NULL; } if (slot == NULL) return NULL; - if (PK11_Authenticate(slot, PR_TRUE, pwdata) != SECSuccess) return NULL; diff --git a/security/nss/cmd/certutil/manifest.mn b/security/nss/cmd/certutil/manifest.mn index 9bf7af5b8638..7b786070985a 100644 --- a/security/nss/cmd/certutil/manifest.mn +++ b/security/nss/cmd/certutil/manifest.mn @@ -49,4 +49,8 @@ REQUIRES = dbm seccmd PROGRAM = certutil +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + #USE_STATIC_LIBS = 1 diff --git a/security/nss/cmd/lib/manifest.mn b/security/nss/cmd/lib/manifest.mn index c68285252040..9df34a5dfeb9 100644 --- a/security/nss/cmd/lib/manifest.mn +++ b/security/nss/cmd/lib/manifest.mn @@ -51,3 +51,7 @@ CSRCS = secutil.c \ REQUIRES = nss nspr dbm +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/cmd/lib/secutil.c b/security/nss/cmd/lib/secutil.c index 491bdd59e495..96909f3a7102 100644 --- a/security/nss/cmd/lib/secutil.c +++ b/security/nss/cmd/lib/secutil.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -1235,6 +1239,26 @@ secu_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level) SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1); } +#ifdef NSS_ENABLE_ECC +static void +secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level) +{ + SECItem curveOID = { siBuffer, NULL, 0}; + + SECU_Indent(out, level); fprintf(out, "%s:\n", m); + SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level+1); + /* For named curves, the DEREncodedParams field contains an + * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID). + */ + if ((pk->u.ec.DEREncodedParams.len > 2) && + (pk->u.ec.DEREncodedParams.data[0] == 0x06)) { + curveOID.len = pk->u.ec.DEREncodedParams.data[1]; + curveOID.data = pk->u.ec.DEREncodedParams.data + 2; + SECU_PrintObjectID(out, &curveOID, "Curve", level +1); + } +} +#endif /* NSS_ENABLE_ECC */ + static int secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena, CERTSubjectPublicKeyInfo *i, char *msg, int level) @@ -1255,10 +1279,15 @@ secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena, secu_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1); break; +#ifdef NSS_ENABLE_ECC + case ecKey: + secu_PrintECPublicKey(out, pk, "EC Public Key", level +1); + break; +#endif + case dhKey: case fortezzaKey: case keaKey: - case ecKey: fprintf(out, "unable to format this SPKI algorithm type\n"); break; default: diff --git a/security/nss/cmd/pk12util/manifest.mn b/security/nss/cmd/pk12util/manifest.mn index 40fd6d6ac4ef..95b6a21541c5 100644 --- a/security/nss/cmd/pk12util/manifest.mn +++ b/security/nss/cmd/pk12util/manifest.mn @@ -48,4 +48,8 @@ REQUIRES = dbm seccmd PROGRAM = pk12util +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + # USE_STATIC_LIBS = 1 diff --git a/security/nss/cmd/pk12util/pk12util.c b/security/nss/cmd/pk12util/pk12util.c index 2ac073aec03b..f9d392925767 100644 --- a/security/nss/cmd/pk12util/pk12util.c +++ b/security/nss/cmd/pk12util/pk12util.c @@ -470,6 +470,7 @@ P12U_ImportPKCS12Object(char *in_file, PK11SlotInfo *slot, p12cxt->file = NULL; /* PK11_FreeSlot(slot); */ + fprintf(stdout, "%s: PKCS12 IMPORT SUCCESSFUL\n", progName); rv = SECSuccess; loser: diff --git a/security/nss/cmd/selfserv/manifest.mn b/security/nss/cmd/selfserv/manifest.mn index e97085201aed..96201f8e6f64 100644 --- a/security/nss/cmd/selfserv/manifest.mn +++ b/security/nss/cmd/selfserv/manifest.mn @@ -46,3 +46,7 @@ REQUIRES = seccmd dbm PROGRAM = selfserv +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c index a5dec75be508..e2b273114b96 100644 --- a/security/nss/cmd/selfserv/selfserv.c +++ b/security/nss/cmd/selfserv/selfserv.c @@ -112,19 +112,19 @@ const int ssl2CipherSuites[] = { * for new SSL3 ciphers. A -1 indicates the cipher * is not currently implemented. */ - -1, /* TLS_ECDH_ECDSA_WITH_NULL_SHA, * G */ - -1, /* TLS_ECDH_ECDSA_WITH_RC4_128_SHA, * H */ - -1, /* TLS_ECDH_ECDSA_WITH_DES_CBC_SHA, * I */ - -1, /* TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, * J */ - -1, /* TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, * K */ - -1, /* TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, * L */ - -1, /* TLS_ECDH_RSA_WITH_NULL_SHA, * M */ - -1, /* TLS_ECDH_RSA_WITH_RC4_128_SHA, * N */ - -1, /* TLS_ECDH_RSA_WITH_DES_CBC_SHA, * O */ - -1, /* TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, * P */ - -1, /* TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, * Q */ - -1, /* TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, * R */ - -1, /* TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, * S */ + TLS_ECDH_ECDSA_WITH_NULL_SHA, /* G */ + TLS_ECDH_ECDSA_WITH_RC4_128_SHA, /* H */ + TLS_ECDH_ECDSA_WITH_DES_CBC_SHA, /* I */ + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, /* J */ + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, /* K */ + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, /* L */ + TLS_ECDH_RSA_WITH_NULL_SHA, /* M */ + TLS_ECDH_RSA_WITH_RC4_128_SHA, /* N */ + TLS_ECDH_RSA_WITH_DES_CBC_SHA, /* O */ + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, /* P */ + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, /* Q */ + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, /* R */ + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, /* S */ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, /* T */ #endif /* NSS_ENABLE_ECC */ 0 @@ -199,8 +199,13 @@ Usage(const char *progName) fprintf(stderr, "Usage: %s -n rsa_nickname -p port [-3DRTbmrvx] [-w password] [-t threads]\n" +#ifdef NSS_ENABLE_ECC +" [-i pid_file] [-c ciphers] [-d dbdir] [-e ec_nickname] \n" +" [-f fortezza_nickname] [-L [seconds]] [-M maxProcs] [-l]\n" +#else " [-i pid_file] [-c ciphers] [-d dbdir] [-f fortezza_nickname] \n" " [-L [seconds]] [-M maxProcs] [-l]\n" +#endif /* NSS_ENABLE_ECC */ "-3 means disable SSL v3\n" "-D means disable Nagle delays in TCP\n" "-T means disable TLS\n" @@ -227,6 +232,19 @@ Usage(const char *progName) "E SSL2 DES 64 CBC WITH MD5\n" "F SSL2 DES 192 EDE3 CBC WITH MD5\n" #ifdef NSS_ENABLE_ECC +"G TLS ECDH ECDSA WITH NULL SHA\n" +"H TLS ECDH ECDSA WITH RC4 128 SHA\n" +"I TLS ECDH ECDSA WITH DES CBC SHA\n" +"J TLS ECDH ECDSA WITH 3DES EDE CBC SHA\n" +"K TLS ECDH ECDSA WITH AES 128 CBC SHA\n" +"L TLS ECDH ECDSA WITH AES 256 CBC SHA\n" +"M TLS ECDH RSA WITH NULL SHA\n" +"N TLS ECDH RSA WITH RC4 128 SHA\n" +"O TLS ECDH RSA WITH DES CBC SHA\n" +"P TLS ECDH RSA WITH 3DES EDE CBC SHA\n" +"Q TLS ECDH RSA WITH AES 128 CBC SHA\n" +"R TLS ECDH RSA WITH AES 256 CBC SHA\n" +"S TLS ECDHE ECDSA WITH AES 128 CBC SHA\n" "T TLS ECDHE RSA WITH AES 128 CBC SHA\n" #endif /* NSS_ENABLE_ECC */ "\n" @@ -1424,6 +1442,9 @@ main(int argc, char **argv) { char * progName = NULL; char * nickName = NULL; +#ifdef NSS_ENABLE_ECC + char * ecNickName = NULL; +#endif char * fNickName = NULL; const char * fileName = NULL; char * cipherString= NULL; @@ -1460,7 +1481,7 @@ main(int argc, char **argv) ** numbers, then capital letters, then lower case, alphabetical. */ optstate = PL_CreateOptState(argc, argv, - "2:3DL:M:RTbc:d:f:hi:lmn:op:rt:vw:xy"); + "2:3DL:M:RTbc:d:e:f:hi:lmn:op:rt:vw:xy"); while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { ++optionsFound; switch(optstate->option) { @@ -1496,6 +1517,10 @@ main(int argc, char **argv) case 'd': dir = optstate->value; break; +#ifdef NSS_ENABLE_ECC + case 'e': ecNickName = strdup(optstate->value); break; +#endif /* NSS_ENABLE_ECC */ + case 'f': fNickName = strdup(optstate->value); break; case 'h': Usage(progName); exit(0); break; @@ -1699,6 +1724,17 @@ main(int argc, char **argv) } privKey[kt_fortezza] = PK11_FindKeyByAnyCert(cert[kt_fortezza], NULL); } +#ifdef NSS_ENABLE_ECC + if (ecNickName) { + cert[kt_ecdh] = PK11_FindCertFromNickname(ecNickName, NULL); + if (cert[kt_ecdh] == NULL) { + fprintf(stderr, "selfserv: Can't find certificate %s\n", + ecNickName); + exit(13); + } + privKey[kt_ecdh] = PK11_FindKeyByAnyCert(cert[kt_ecdh], NULL); + } +#endif /* NSS_ENABLE_ECC */ /* allocate the array of thread slots, and launch the worker threads. */ rv = launch_threads(&jobLoop, 0, 0, requestCert, useLocalThreads); diff --git a/security/nss/cmd/tstclnt/manifest.mn b/security/nss/cmd/tstclnt/manifest.mn index 8762227e4c8d..d771e33f481d 100644 --- a/security/nss/cmd/tstclnt/manifest.mn +++ b/security/nss/cmd/tstclnt/manifest.mn @@ -48,3 +48,7 @@ CSRCS = tstclnt.c PROGRAM = tstclnt +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/cmd/tstclnt/tstclnt.c b/security/nss/cmd/tstclnt/tstclnt.c index 2f3d5bd808ff..f4e257046d32 100644 --- a/security/nss/cmd/tstclnt/tstclnt.c +++ b/security/nss/cmd/tstclnt/tstclnt.c @@ -242,13 +242,13 @@ static void Usage(const char *progName) "F SSL2 DES 192 EDE3 CBC WITH MD5\n" #ifdef NSS_ENABLE_ECC "G TLS ECDH ECDSA WITH NULL SHA\n" -"H TLS ECDH ECDSA WITH RC4 128 CBC SHA\n" +"H TLS ECDH ECDSA WITH RC4 128 SHA\n" "I TLS ECDH ECDSA WITH DES CBC SHA\n" "J TLS ECDH ECDSA WITH 3DES EDE CBC SHA\n" "K TLS ECDH ECDSA WITH AES 128 CBC SHA\n" "L TLS ECDH ECDSA WITH AES 256 CBC SHA\n" "M TLS ECDH RSA WITH NULL SHA\n" -"N TLS ECDH RSA WITH RC4 128 CBC SHA\n" +"N TLS ECDH RSA WITH RC4 128 SHA\n" "O TLS ECDH RSA WITH DES CBC SHA\n" "P TLS ECDH RSA WITH 3DES EDE CBC SHA\n" "Q TLS ECDH RSA WITH AES 128 CBC SHA\n" diff --git a/security/nss/lib/cryptohi/cryptohi.h b/security/nss/lib/cryptohi/cryptohi.h index 0d05348706b8..43796917dad3 100644 --- a/security/nss/lib/cryptohi/cryptohi.h +++ b/security/nss/lib/cryptohi/cryptohi.h @@ -18,7 +18,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -32,7 +36,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: cryptohi.h,v 1.5 2003/05/24 03:34:48 wtc%netscape.com Exp $ + * $Id: cryptohi.h,v 1.6 2003/10/17 13:45:32 ian.mcgreer%sun.com Exp $ */ #ifndef _CRYPTOHI_H_ @@ -53,7 +57,7 @@ SEC_BEGIN_PROTOS /****************************************/ /* -** DER encode/decode DSA signatures +** DER encode/decode (EC)DSA signatures */ /* ANSI X9.57 defines DSA signatures as DER encoded data. Our DSA code (and @@ -63,7 +67,21 @@ SEC_BEGIN_PROTOS extern SECStatus DSAU_EncodeDerSig(SECItem *dest, SECItem *src); extern SECItem *DSAU_DecodeDerSig(SECItem *item); - +/* + * Unlike DSA, raw ECDSA signatures do not have a fixed length. + * Rather they contain two integers r and s whose length depends + * on the size of the EC key used for signing. + * + * We can reuse the DSAU_EncodeDerSig interface to DER encode + * raw ECDSA signature keeping in mind that the length of r + * is the same as that of s and exactly half of src->len. + * + * For decoding, we need to pass the length of the desired + * raw signature (twice the key size) explicitly. + */ +extern SECStatus DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, + unsigned int len); +extern SECItem *DSAU_DecodeDerSigToLen(SECItem *item, unsigned int len); /****************************************/ /* diff --git a/security/nss/lib/cryptohi/dsautil.c b/security/nss/lib/cryptohi/dsautil.c index 504e6990788e..39eb3191ba4e 100644 --- a/security/nss/lib/cryptohi/dsautil.c +++ b/security/nss/lib/cryptohi/dsautil.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -123,26 +127,34 @@ loser: return SECFailure; } -/* src is a "raw" DSA signature, 20 bytes of r followed by 20 bytes of s. -** dest is the signature DER encoded. ? +/* src is a "raw" ECDSA or DSA signature, the first half contains r + * and the second half contains s. dest is the DER encoded signature. */ -SECStatus -DSAU_EncodeDerSig(SECItem *dest, SECItem *src) +static SECStatus +common_EncodeDerSig(SECItem *dest, SECItem *src) { SECItem * item; SECItem srcItem; DSA_ASN1Signature sig; - unsigned char signedR[DSA_SUBPRIME_LEN + 1]; - unsigned char signedS[DSA_SUBPRIME_LEN + 1]; + unsigned char *signedR; + unsigned char *signedS; + int len; - PORT_Memset(&sig, 0, sizeof(sig)); - - PORT_Assert(src->len == 2 * DSA_SUBPRIME_LEN); - if (src->len != 2 * DSA_SUBPRIME_LEN) { - PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); + /* Allocate memory with room for an extra byte that + * may be required if the top bit in the first byte + * is already set. + */ + len = src->len/2; + signedR = (unsigned char *) PORT_Alloc(len + 1); + if (!signedR) return SECFailure; + signedS = (unsigned char *) PORT_ZAlloc(len + 1); + if (!signedS) { + if (signedR) PORT_Free(signedR); return SECFailure; } + PORT_Memset(&sig, 0, sizeof(sig)); + /* Must convert r and s from "unsigned" integers to "signed" integers. ** If the high order bit of the first byte (MSB) is 1, then must ** prepend with leading zero. @@ -156,13 +168,15 @@ DSAU_EncodeDerSig(SECItem *dest, SECItem *src) sig.s.len = sizeof signedR; srcItem.data = src->data; - srcItem.len = DSA_SUBPRIME_LEN; + srcItem.len = len; DSAU_ConvertUnsignedToSigned(&sig.r, &srcItem); - srcItem.data += DSA_SUBPRIME_LEN; + srcItem.data += len; DSAU_ConvertUnsignedToSigned(&sig.s, &srcItem); item = SEC_ASN1EncodeItem(NULL, dest, &sig, DSA_SignatureTemplate); + if (signedR) PORT_Free(signedR); + if (signedS) PORT_Free(signedS); if (item == NULL) return SECFailure; @@ -170,13 +184,14 @@ DSAU_EncodeDerSig(SECItem *dest, SECItem *src) return SECSuccess; } -/* src is a DER-encoded DSA signature. +/* src is a DER-encoded ECDSA or DSA signature. ** Returns a newly-allocated SECItem structure, pointing at a newly allocated -** buffer containing the "raw" DSA signature, which is 20 bytes of r, -** followed by 20 bytes of s. +** buffer containing the "raw" signature, which is len bytes of r, +** followed by len bytes of s. For DSA, len is always DSA_SUBPRIME_LEN. +** For ECDSA, len depends on the key size used to create the signature. */ -SECItem * -DSAU_DecodeDerSig(SECItem *item) +static SECItem * +common_DecodeDerSig(SECItem *item, int len) { SECItem * result = NULL; SECStatus status; @@ -189,8 +204,8 @@ DSAU_DecodeDerSig(SECItem *item) if (result == NULL) goto loser; - result->len = 2 * DSA_SUBPRIME_LEN; - result->data = (unsigned char*)PORT_Alloc(2 * DSA_SUBPRIME_LEN); + result->len = 2 * len; + result->data = (unsigned char*)PORT_Alloc(2 * len); if (result->data == NULL) goto loser; @@ -204,12 +219,12 @@ DSAU_DecodeDerSig(SECItem *item) ** fixed length unsigned integers. */ dst.data = result->data; - dst.len = DSA_SUBPRIME_LEN; + dst.len = len; status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.r); if (status != SECSuccess) goto loser; - dst.data += DSA_SUBPRIME_LEN; + dst.data += len; status = DSAU_ConvertSignedToFixedUnsigned(&dst, &sig.s); if (status != SECSuccess) goto loser; @@ -229,3 +244,56 @@ loser: } goto done; } + +/* src is a "raw" DSA signature, 20 bytes of r followed by 20 bytes of s. +** dest is the signature DER encoded. ? +*/ +SECStatus +DSAU_EncodeDerSig(SECItem *dest, SECItem *src) +{ + PORT_Assert(src->len == 2 * DSA_SUBPRIME_LEN); + if (src->len != 2 * DSA_SUBPRIME_LEN) { + PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); + return SECFailure; + } + + return common_EncodeDerSig(dest, src); +} + +/* src is a "raw" DSA signature of length len (len/2 bytes of r followed +** by len/2 bytes of s). dest is the signature DER encoded. +*/ +SECStatus +DSAU_EncodeDerSigWithLen(SECItem *dest, SECItem *src, int len) +{ + + PORT_Assert((src->len == len) && (len % 2 == 0)); + if ((src->len != len) || (src->len % 2 != 0)) { + PORT_SetError( PR_INVALID_ARGUMENT_ERROR ); + return SECFailure; + } + + return common_EncodeDerSig(dest, src); +} + +/* src is a DER-encoded DSA signature. +** Returns a newly-allocated SECItem structure, pointing at a newly allocated +** buffer containing the "raw" DSA signature, which is 20 bytes of r, +** followed by 20 bytes of s. +*/ +SECItem * +DSAU_DecodeDerSig(SECItem *item) +{ + return common_DecodeDerSig(item, DSA_SUBPRIME_LEN); +} + +/* src is a DER-encoded ECDSA signature. +** Returns a newly-allocated SECItem structure, pointing at a newly allocated +** buffer containing the "raw" ECDSA signature of length len containing +** r followed by s (both padded to take up exactly len/2 bytes). +*/ +SECItem * +DSAU_DecodeDerSigToLen(SECItem *item, int len) +{ + return common_DecodeDerSig(item, len/2); +} diff --git a/security/nss/lib/cryptohi/manifest.mn b/security/nss/lib/cryptohi/manifest.mn index ff0125ac8fdc..d235ca800725 100644 --- a/security/nss/lib/cryptohi/manifest.mn +++ b/security/nss/lib/cryptohi/manifest.mn @@ -62,3 +62,7 @@ LIBSRCS = \ CSRCS = $(LIBSRCS) +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index b39ba988f09c..11f625164679 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -926,44 +926,6 @@ CERT_GetCertKeyType (CERTSubjectPublicKeyInfo *spki) { return keyType; } -#ifdef NSS_ENABLE_ECC -static int -seckey_supportedECParams(SECItem *encodedParams) -{ - SECOidTag tag; - SECItem oid = { siBuffer, NULL, 0}; - - /* We do not currently support explicit DER encoding of curve - * parameters. Make sure the encoding takes the form of - * an object identifier (this is how named curves are encoded). - */ - if (encodedParams->data[0] != SEC_ASN1_OBJECT_ID) return 0; - - /* The encodedParams data contains 0x06 (SEC_ASN1_OBJECT_ID), - * followed by the length of the curve oid and the curve oid. - */ - oid.len = encodedParams->data[1]; - oid.data = encodedParams->data + 2; - tag = SECOID_FindOIDTag(&oid); - - return (((tag >= SEC_OID_ANSIX962_EC_PRIME192V1) && - (tag <= SEC_OID_ANSIX962_EC_PRIME256V1)) || - ((tag >= SEC_OID_SECG_EC_SECP112R1) && - (tag <= SEC_OID_SECG_EC_SECP521R1)) || - ((tag >= SEC_OID_ANSIX962_EC_C2PNB163V1) && - (tag <= SEC_OID_ANSIX962_EC_C2TNB431R1)) || - ((tag >= SEC_OID_SECG_EC_SECT113R1) && - (tag <= SEC_OID_SECG_EC_SECT571R1))); -} - -static int -seckey_supportedECPointForm(SECItem *ecPoint) -{ - /* For now, we only support uncompressed points */ - return (ecPoint->data[0] == EC_POINT_FORM_UNCOMPRESSED); -} -#endif /* NSS_ENABLE_ECC */ - static SECKEYPublicKey * seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) { @@ -1093,30 +1055,6 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) case SEC_OID_ANSIX962_EC_PUBLIC_KEY: pubk->keyType = ecKey; pubk->u.ec.size = 0; -#if 0 - /* If we uncomment these checks, ssl3con.c produces an "SSL - * was unable to extract the public key from the peer's - * certificate" error upon encountering an EC certificate with - * an unsupported curve or point form. It isn't clear that we - * should be triggering this error because the EC key was - * *successfully extracted* even though we can't use - * it. Commenting these checks delays detection of unsupported - * curves to a later point in the handshake (e.g. when a - * client attempts to generate a key pair before sending the - * ClientKeyExchange message). - */ - if (!seckey_supportedECParams(&spki->algorithm.parameters)) { - PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); - rv = SECFailure; - break; - } - - if (!seckey_supportedECPointForm(&newOs)) { - PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM); - rv = SECFailure; - break; - } -#endif /* Since PKCS#11 directly takes the DER encoding of EC params * and public value, we don't need any decoding here. @@ -1174,9 +1112,8 @@ CERT_KMIDPublicKey(CERTCertificate *cert) return seckey_ExtractPublicKey(&cert->subjectPublicKeyInfo); } -#ifdef NSS_ENABLE_ECC -static int -seckey_ECParams2KeySize(SECItem *encodedParams) +int +SECKEY_ECParams2KeySize(SECItem *encodedParams) { SECOidTag tag; SECItem oid = { siBuffer, NULL, 0}; @@ -1302,7 +1239,6 @@ seckey_ECParams2KeySize(SECItem *encodedParams) return 0; } } -#endif /* NSS_ENABLE_ECC */ /* returns key strength in bytes (not bits) */ unsigned @@ -1332,7 +1268,7 @@ SECKEY_PublicKeyStrength(SECKEYPublicKey *pubk) /* Get the key size in bits and adjust */ if (pubk->u.ec.size == 0) { pubk->u.ec.size = - seckey_ECParams2KeySize(&pubk->u.ec.DEREncodedParams); + SECKEY_ECParams2KeySize(&pubk->u.ec.DEREncodedParams); } return (pubk->u.ec.size + 7)/8; #endif /* NSS_ENABLE_ECC */ @@ -1356,7 +1292,7 @@ SECKEY_PublicKeyStrengthInBits(SECKEYPublicKey *pubk) case ecKey: if (pubk->u.ec.size == 0) { pubk->u.ec.size = - seckey_ECParams2KeySize(&pubk->u.ec.DEREncodedParams); + SECKEY_ECParams2KeySize(&pubk->u.ec.DEREncodedParams); } return pubk->u.ec.size; #endif /* NSS_ENABLE_ECC */ @@ -1682,6 +1618,33 @@ SECKEY_CreateSubjectPublicKeyInfo(SECKEYPublicKey *pubk) } SECITEM_FreeItem(¶ms, PR_FALSE); break; +#ifdef NSS_ENABLE_ECC + case ecKey: + rv = SECITEM_CopyItem(arena, ¶ms, + &pubk->u.ec.DEREncodedParams); + if (rv != SECSuccess) break; + + rv = SECOID_SetAlgorithmID(arena, &spki->algorithm, + SEC_OID_ANSIX962_EC_PUBLIC_KEY, + ¶ms); + if (rv != SECSuccess) break; + + rv = SECITEM_CopyItem(arena, &spki->subjectPublicKey, + &pubk->u.ec.publicValue); + + if (rv == SECSuccess) { + /* + * The stored value is supposed to be a BIT_STRING, + * so convert the length. + */ + spki->subjectPublicKey.len <<= 3; + /* + * We got a good one; return it. + */ + return spki; + } + break; +#endif /* NSS_ENABLE_ECC */ case keaKey: case dhKey: /* later... */ diff --git a/security/nss/lib/cryptohi/secsign.c b/security/nss/lib/cryptohi/secsign.c index bd5a53605570..21920f9eb072 100644 --- a/security/nss/lib/cryptohi/secsign.c +++ b/security/nss/lib/cryptohi/secsign.c @@ -18,7 +18,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -32,7 +36,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: secsign.c,v 1.5 2002/12/12 06:05:17 nelsonb%netscape.com Exp $ + * $Id: secsign.c,v 1.6 2003/10/17 13:45:33 ian.mcgreer%sun.com Exp $ */ #include @@ -117,6 +121,13 @@ SGN_NewContext(SECOidTag alg, SECKEYPrivateKey *key) signalg = SEC_OID_MISSI_DSS; /* XXX Is there a better algid? */ keyType = fortezzaKey; break; +#ifdef NSS_ENABLE_ECC + case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST: + hashalg = SEC_OID_SHA1; + signalg = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + keyType = ecKey; + break; +#endif /* NSS_ENABLE_ECC */ /* we don't implement MD4 hashes. * we *CERTAINLY* don't want to sign one! */ case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: @@ -198,7 +209,6 @@ SGN_End(SGNContext *cx, SECItem *result) SECKEYPrivateKey *privKey = cx->key; SGNDigestInfo *di = 0; - result->data = 0; digder.data = 0; @@ -255,8 +265,10 @@ SGN_End(SGNContext *cx, SECItem *result) goto loser; } - if (cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) { - rv = DSAU_EncodeDerSig(result, &sigitem); + if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) || + (cx->signalg == SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST)) { + /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */ + rv = DSAU_EncodeDerSigWithLen(result, &sigitem, signatureLen); PORT_Free(sigitem.data); if (rv != SECSuccess) goto loser; @@ -413,6 +425,11 @@ SEC_DerSignData(PRArenaPool *arena, SECItem *result, case dsaKey: algID = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; break; +#ifdef NSS_ENABLE_ECC + case ecKey: + algID = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; + break; +#endif /* NSS_ENABLE_ECC */ default: return SECFailure; break; diff --git a/security/nss/lib/cryptohi/secvfy.c b/security/nss/lib/cryptohi/secvfy.c index 1e8b69d6cbf9..a4a47e0b3f81 100644 --- a/security/nss/lib/cryptohi/secvfy.c +++ b/security/nss/lib/cryptohi/secvfy.c @@ -36,7 +36,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: secvfy.c,v 1.8 2003/02/27 01:31:07 nelsonb%netscape.com Exp $ + * $Id: secvfy.c,v 1.9 2003/10/17 13:45:33 ian.mcgreer%sun.com Exp $ */ #include @@ -127,37 +127,51 @@ struct VFYContextStr { }; /* - * decode the DSA signature from it's DER wrapping. + * decode the ECDSA or DSA signature from it's DER wrapping. + * The unwrapped/raw signature is placed in the buffer pointed + * to by digest and has enough room for len bytes. */ static SECStatus -decodeDSASignature(SECOidTag algid, SECItem *sig, unsigned char *digest) { - SECItem *dsasig = NULL; +decodeECorDSASignature(SECOidTag algid, SECItem *sig, unsigned char *digest, + unsigned int len) { + SECItem *dsasig = NULL; /* also used for ECDSA */ SECStatus rv=SECSuccess; - /* if this is a DER encoded signature, decode it first */ - if ((algid == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) || - (algid == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) || - (algid == SEC_OID_ANSIX9_DSA_SIGNATURE)) { - dsasig = DSAU_DecodeDerSig(sig); - if ((dsasig == NULL) || (dsasig->len != DSA_SIGNATURE_LEN)) { - rv = SECFailure; - goto loser; + switch (algid) { + case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: + case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: + case SEC_OID_ANSIX9_DSA_SIGNATURE: + case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST: + if (algid == SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST) { + if (len > MAX_ECKEY_LEN * 2) { + PORT_SetError(SEC_ERROR_BAD_DER); + return SECFailure; + } + dsasig = DSAU_DecodeDerSigToLen(sig, len); + } else { + dsasig = DSAU_DecodeDerSig(sig); } - PORT_Memcpy(digest, dsasig->data, dsasig->len); - } else { - if (sig->len != DSA_SIGNATURE_LEN) { + + if ((dsasig == NULL) || (dsasig->len != len)) { rv = SECFailure; - goto loser; + } else { + PORT_Memcpy(digest, dsasig->data, dsasig->len); } - PORT_Memcpy(digest, sig->data, sig->len); + break; + default: + if (sig->len != len) { + rv = SECFailure; + } else { + PORT_Memcpy(digest, sig->data, sig->len); + } + break; } -loser: - if (dsasig != NULL) - SECITEM_FreeItem(dsasig, PR_TRUE); + if (dsasig != NULL) SECITEM_FreeItem(dsasig, PR_TRUE); + if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER); return rv; - } + /* * Pulls the hash algorithm, signing algorithm, and key type out of a * composite algorithm. @@ -200,6 +214,7 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg) /* what about normal DSA? */ case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: + case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST: *hashalg = SEC_OID_SHA1; break; case SEC_OID_MISSI_DSS: @@ -216,60 +231,14 @@ decodeSigAlg(SECOidTag alg, SECOidTag *hashalg) return SECSuccess; } -#ifdef NSS_ENABLE_ECC -/* - * decode the ECDSA signature from it's DER wrapping. - */ -static SECStatus -decodeECDSASignature(SECOidTag algid, SECItem *sig, - unsigned char *digest, int len) -{ - SECStatus rv=SECSuccess; - - if (len > MAX_ECKEY_LEN * 2) { - rv = SECFailure; - goto loser; - } - - /* if this is a DER encoded signature, decode it first */ - if (algid == SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST) { - /* XXX Use a better decoder */ - if ((sig->len < len + 6) || - (sig->data[0] != 0x30) || /* must start with a SEQUENCE */ - (sig->data[1] != sig->len - 2) || - (sig->data[2] != 0x02) || /* 1st INTEGER, r */ - (sig->data[3] < len/2) || - (sig->data[4 + sig->data[3]] != 0x02) || /* 2nd INTEGER, s */ - (sig->data[5 + sig->data[3]] < len/2)) { - rv = SECFailure; - goto loser; - } - - PORT_Memcpy(digest, sig->data + 4 + (sig->data[3]-len/2), len/2); - PORT_Memcpy(digest + len/2, sig->data + sig->len - len/2, len/2); - } else { - if (sig->len != len) { - rv = SECFailure; - goto loser; - } - PORT_Memcpy(digest, sig->data, sig->len); - } - -loser: - if (rv == SECFailure) PORT_SetError(SEC_ERROR_BAD_DER); - return rv; -} -#endif /* NSS_ENABLE_ECC */ - VFYContext * VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid, void *wincx) { VFYContext *cx; SECStatus rv; -#ifdef NSS_ENABLE_ECC - int sigLen; -#endif /* NSS_ENABLE_ECC */ + unsigned char *tmp; + unsigned int sigLen; cx = (VFYContext*) PORT_ZAlloc(sizeof(VFYContext)); if (cx) { @@ -292,28 +261,25 @@ VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag algid, break; case fortezzaKey: case dsaKey: - cx->type = VFY_DSA; - cx->alg = SEC_OID_SHA1; - cx->key = SECKEY_CopyPublicKey(key); - if (sig) { - rv = decodeDSASignature(algid,sig,&cx->digest[0]); + case ecKey: + if (key->keyType == ecKey) { + cx->type = VFY_ECDSA; + /* Unlike DSA, EDSA does not have a fixed signature length + * (it depends on the key size) + */ + sigLen = SECKEY_PublicKeyStrength(key) * 2; + tmp = cx->ecdsadigest; + } else { + cx->type = VFY_DSA; + sigLen = DSA_SIGNATURE_LEN; + tmp = cx->digest; } - break; -#ifdef NSS_ENABLE_ECC - case ecKey: - cx->type = VFY_ECDSA; - cx->alg = SEC_OID_SHA1; - cx->key = SECKEY_CopyPublicKey(key); - /* Unlike DSA, EDSA does not have a fixed signature length - * (it depends on the key size) - */ - sigLen = SECKEY_PublicKeyStrength(key) * 2; - if (sig) { - rv = decodeECDSASignature(algid,sig,&cx->ecdsadigest[0], - sigLen); - } - break; -#endif /* NSS_ENABLE_ECC */ + cx->alg = SEC_OID_SHA1; + cx->key = SECKEY_CopyPublicKey(key); + if (sig) { + rv = decodeECorDSASignature(algid,sig,tmp,sigLen); + } + break; default: rv = SECFailure; break; @@ -392,11 +358,9 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig) { unsigned char final[32]; unsigned part; - SECItem hash,dsasig; + SECItem hash,dsasig; /* dsasig is also used for ECDSA */ SECStatus rv; -#ifdef NSS_ENABLE_ECC - SECItem ecdsasig; -#endif /* NSS_ENABLE_ECC */ + int rawSigLen; if ((cx->hasSignature == PR_FALSE) && (sig == NULL)) { PORT_SetError(SEC_ERROR_INVALID_ARGS); @@ -410,15 +374,22 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig) (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final)); switch (cx->type) { case VFY_DSA: + case VFY_ECDSA: + if (cx->type == VFY_DSA) { + dsasig.data = cx->digest; + dsasig.len = DSA_SIGNATURE_LEN; + } else { + dsasig.data = cx->ecdsadigest; + dsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2; + } if (sig) { - rv = decodeDSASignature(cx->sigAlg,sig,&cx->digest[0]); + rv = decodeECorDSASignature(cx->sigAlg,sig,dsasig.data, + dsasig.len); if (rv != SECSuccess) { PORT_SetError(SEC_ERROR_BAD_SIGNATURE); return SECFailure; } } - dsasig.data = cx->digest; - dsasig.len = DSA_SIGNATURE_LEN; /* magic size of dsa signature */ hash.data = final; hash.len = part; if (PK11_Verify(cx->key,&dsasig,&hash,cx->wincx) != SECSuccess) { @@ -441,28 +412,6 @@ VFY_EndWithSignature(VFYContext *cx, SECItem *sig) return SECFailure; } break; - -#ifdef NSS_ENABLE_ECC - case VFY_ECDSA: - if (sig) { - rv = decodeECDSASignature(cx->sigAlg,sig,&cx->ecdsadigest[0], - SECKEY_PublicKeyStrength(cx->key) * 2); - if (rv != SECSuccess) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - return SECFailure; - } - } - ecdsasig.data = cx->ecdsadigest; - ecdsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2; - hash.data = final; - hash.len = part; - if (PK11_Verify(cx->key,&ecdsasig,&hash,cx->wincx) != SECSuccess) { - PORT_SetError(SEC_ERROR_BAD_SIGNATURE); - return SECFailure; - } - break; -#endif /* NSS_ENABLE_ECC */ - default: PORT_SetError(SEC_ERROR_BAD_SIGNATURE); return SECFailure; /* shouldn't happen */ @@ -490,6 +439,9 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, SECStatus rv; VFYContext *cx; SECItem dsasig; +#ifdef NSS_ENABLE_ECC + SECItem ecdsasig; +#endif /* NSS_ENABLE_ECC */ rv = SECFailure; @@ -513,6 +465,18 @@ VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig, rv = SECSuccess; } break; +#ifdef NSS_ENABLE_ECC + case ecKey: + ecdsasig.data = &cx->ecdsadigest[0]; + ecdsasig.len = SECKEY_PublicKeyStrength(cx->key) * 2; + if (PK11_Verify(cx->key, &ecdsasig, digest, cx->wincx) + != SECSuccess) { + PORT_SetError(SEC_ERROR_BAD_SIGNATURE); + } else { + rv = SECSuccess; + } + break; +#endif /* NSS_ENABLE_ECC */ default: break; } diff --git a/security/nss/lib/freebl/Makefile b/security/nss/lib/freebl/Makefile index 349d09ba4a50..ff770c198c0c 100644 --- a/security/nss/lib/freebl/Makefile +++ b/security/nss/lib/freebl/Makefile @@ -17,7 +17,13 @@ # Copyright (C) 1994-2000 Netscape Communications Corporation. All # Rights Reserved. # +# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +# Sun Microsystems, Inc. All Rights Reserved. +# # Contributor(s): +# Stephen Fung and +# Douglas Stebila , Sun Microsystems +# Laboratories # # Alternatively, the contents of this file may be used under the # terms of the GNU General Public License Version 2 or later (the @@ -127,6 +133,12 @@ ifeq ($(OS_TARGET),Linux) ifeq ($(CPU_ARCH),x86) ASFILES = mpi_x86.s DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D +ifdef NSS_ENABLE_ECC + #enable floating point ECC code + DEFINES += -DECL_USE_FP + ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c + ECL_HDRS += ecp_fp.h +endif endif endif @@ -212,6 +224,11 @@ else # ASM_SUFFIX = .S endif endif +ifdef NSS_ENABLE_ECC +DEFINES += -DECL_USE_FP +ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c +ECL_HDRS += ecp_fp.h +endif endif else # Solaris x86 @@ -254,31 +271,38 @@ rijndael_tables: $(OBJDIR)/make_rijndael_tab ifdef USE_PURE_32 -vpath %.h $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) -vpath %.c $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) -vpath %.S $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) -vpath %.s $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) -vpath %.asm $(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) -INCLUDES += -I$(FREEBL_PARENT) -I$(FREEBL_PARENT)/mpi +vpath %.h $(FREEBL_PARENT)/ecl:$(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) +vpath %.c $(FREEBL_PARENT)/ecl:$(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) +vpath %.S $(FREEBL_PARENT)/ecl:$(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) +vpath %.s $(FREEBL_PARENT)/ecl:$(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) +vpath %.asm $(FREEBL_PARENT)/ecl:$(FREEBL_PARENT)/mpi:$(FREEBL_PARENT) +INCLUDES += -I$(FREEBL_PARENT) -I$(FREEBL_PARENT)/mpi -I$(FREEBL_PARENT)/ecl else -vpath %.h mpi -vpath %.c mpi -vpath %.S mpi -vpath %.s mpi -vpath %.asm mpi -INCLUDES += -Impi +vpath %.h mpi:ecl +vpath %.c mpi:ecl +vpath %.S mpi:ecl +vpath %.s mpi:ecl +vpath %.asm mpi:ecl +INCLUDES += -Impi -Iecl endif DEFINES += -DMP_API_COMPATIBLE -MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c GFp_ecl.c +MPI_USERS = dh.c pqg.c dsa.c rsa.c ec.c MPI_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_SRCS:.c=$(OBJ_SUFFIX))) MPI_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(MPI_USERS:.c=$(OBJ_SUFFIX))) +ECL_USERS = ec.c + +ECL_OBJS = $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_SRCS:.c=$(OBJ_SUFFIX)) $(ECL_ASM_SRCS:$(ASM_SUFFIX)=$(OBJ_SUFFIX))) +ECL_OBJS += $(addprefix $(OBJDIR)/$(PROG_PREFIX), $(ECL_USERS:.c=$(OBJ_SUFFIX))) + $(MPI_OBJS): $(MPI_HDRS) +$(ECL_OBJS): $(ECL_HDRS) + $(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c $(OBJDIR)/ldvector$(OBJ_SUFFIX) $(OBJDIR)/loader$(OBJ_SUFFIX) : loader.h diff --git a/security/nss/lib/freebl/blapit.h b/security/nss/lib/freebl/blapit.h index fe0ebd631aa0..a8aac9aeb971 100644 --- a/security/nss/lib/freebl/blapit.h +++ b/security/nss/lib/freebl/blapit.h @@ -22,7 +22,8 @@ * Sun Microsystems, Inc. All Rights Reserved. * * Contributor(s): - * Dr Vipul Gupta , Sun Microsystems Laboratories + * Dr Vipul Gupta and + * Douglas Stebila , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -36,7 +37,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: blapit.h,v 1.10 2003/03/29 00:18:18 nelsonb%netscape.com Exp $ + * $Id: blapit.h,v 1.11 2003/10/17 13:45:33 ian.mcgreer%sun.com Exp $ */ #ifndef _BLAPIT_H_ @@ -45,6 +46,7 @@ #include "seccomon.h" #include "prlink.h" #include "plarena.h" +#include "ecl-exp.h" /* RC2 operation modes */ @@ -315,6 +317,8 @@ struct ECParamsStr { SECItem order; int cofactor; SECItem DEREncoding; + ECCurveName name; + SECItem curveOID; }; typedef struct ECParamsStr ECParams; @@ -330,6 +334,7 @@ struct ECPrivateKeyStr { ECParams ecParams; SECItem publicValue; /* encoded ec point */ SECItem privateValue; /* private big integer */ + SECItem version; /* As per SEC 1, Appendix C, Section C.4 */ }; typedef struct ECPrivateKeyStr ECPrivateKey; diff --git a/security/nss/lib/freebl/ec.c b/security/nss/lib/freebl/ec.c index bb61738a0fc1..66d265025110 100644 --- a/security/nss/lib/freebl/ec.c +++ b/security/nss/lib/freebl/ec.c @@ -18,7 +18,8 @@ * Sun Microsystems, Inc. All Rights Reserved. * * Contributor(s): - * Dr Vipul Gupta , Sun Microsystems Laboratories + * Dr Vipul Gupta and + * Douglas Stebila , 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 @@ -40,8 +41,7 @@ #include "secmpi.h" #include "secitem.h" #include "ec.h" -#include "GFp_ecl.h" -#include "GF2m_ecl.h" +#include "ecl.h" #ifdef NSS_ENABLE_ECC @@ -61,136 +61,19 @@ ec_point_at_infinity(SECItem *pointP) } /* - * Computes point addition R = P + Q for the curve whose - * parameters are encoded in params. Two or more of P, Q, - * R may point to the same memory location. + * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for + * the curve whose parameters are encoded in params with base point G. */ -SECStatus -ec_point_add(ECParams *params, SECItem *pointP, - SECItem *pointQ, SECItem *pointR) -{ - mp_int Px, Py, Qx, Qy, Rx, Ry; - mp_int irreducible, a; - SECStatus rv = SECFailure; - mp_err err = MP_OKAY; - int len; - -#if EC_DEBUG - int i; - - printf("ec_point_add: params [len=%d]:", params->DEREncoding.len); - for (i = 0; i < params->DEREncoding.len; i++) - printf("%02x:", params->DEREncoding.data[i]); - printf("\n"); - - printf("ec_point_add: pointP [len=%d]:", pointP->len); - for (i = 0; i < pointP->len; i++) - printf("%02x:", pointP->data[i]); - printf("\n"); - - printf("ec_point_add: pointQ [len=%d]:", pointQ->len); - for (i = 0; i < pointQ->len; i++) - printf("%02x:", pointQ->data[i]); - printf("\n"); -#endif - - /* NOTE: We only support prime field curves for now */ - len = (params->fieldID.size + 7) >> 3; - if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) || - (pointP->len != (2 * len + 1)) || - (pointQ->data[0] != EC_POINT_FORM_UNCOMPRESSED) || - (pointQ->len != (2 * len + 1))) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - - MP_DIGITS(&Px) = 0; - MP_DIGITS(&Py) = 0; - MP_DIGITS(&Qx) = 0; - MP_DIGITS(&Qy) = 0; - MP_DIGITS(&Rx) = 0; - MP_DIGITS(&Ry) = 0; - MP_DIGITS(&irreducible) = 0; - MP_DIGITS(&a) = 0; - CHECK_MPI_OK( mp_init(&Px) ); - CHECK_MPI_OK( mp_init(&Py) ); - CHECK_MPI_OK( mp_init(&Qx) ); - CHECK_MPI_OK( mp_init(&Qy) ); - CHECK_MPI_OK( mp_init(&Rx) ); - CHECK_MPI_OK( mp_init(&Ry) ); - CHECK_MPI_OK( mp_init(&irreducible) ); - CHECK_MPI_OK( mp_init(&a) ); - - /* Initialize Px and Py */ - CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, - (mp_size) len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, - (mp_size) len) ); - - /* Initialize Qx and Qy */ - CHECK_MPI_OK( mp_read_unsigned_octets(&Qx, pointQ->data + 1, - (mp_size) len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&Qy, pointQ->data + 1 + len, - (mp_size) len) ); - - /* Set up the curve coefficient */ - SECITEM_TO_MPINT( params->curve.a, &a ); - - /* Compute R = P + Q */ - if (params->fieldID.type == ec_field_GFp) { - SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible ); - if (GFp_ec_pt_add(&irreducible, &a, &Px, &Py, &Qx, &Qy, - &Rx, &Ry) != SECSuccess) - goto cleanup; - } else { - SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible ); - if (GF2m_ec_pt_add(&irreducible, &a, &Px, &Py, &Qx, &Qy, &Rx, &Ry) - != SECSuccess) - goto cleanup; - } - - /* Construct the SECItem representation of the result */ - pointR->data[0] = EC_POINT_FORM_UNCOMPRESSED; - CHECK_MPI_OK( mp_to_fixlen_octets(&Rx, pointR->data + 1, - (mp_size) len) ); - CHECK_MPI_OK( mp_to_fixlen_octets(&Ry, pointR->data + 1 + len, - (mp_size) len) ); - rv = SECSuccess; - -#if EC_DEBUG - printf("ec_point_add: pointR [len=%d]:", pointR->len); - for (i = 0; i < pointR->len; i++) - printf("%02x:", pointR->data[i]); - printf("\n"); -#endif - -cleanup: - mp_clear(&Px); - mp_clear(&Py); - mp_clear(&Qx); - mp_clear(&Qy); - mp_clear(&Rx); - mp_clear(&Ry); - mp_clear(&irreducible); - mp_clear(&a); - if (err) { - MP_TO_SEC_ERROR(err); - rv = SECFailure; - } - - return rv; -} - -/* - * Computes scalar point multiplication pointQ = k * pointP for - * the curve whose parameters are encoded in params. - */ -SECStatus -ec_point_mul(ECParams *params, mp_int *k, - SECItem *pointP, SECItem *pointQ) +SECStatus +ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2, + const SECItem *pointP, SECItem *pointQ) { mp_int Px, Py, Qx, Qy; - mp_int irreducible, a, b; + mp_int Gx, Gy, order, irreducible, a, b; +#if 0 /* currently don't support non-named curves */ + unsigned int irr_arr[5]; +#endif + ECGroup *group = NULL; SECStatus rv = SECFailure; mp_err err = MP_OKAY; int len; @@ -199,66 +82,105 @@ ec_point_mul(ECParams *params, mp_int *k, int i; char mpstr[256]; - printf("ec_point_mul: params [len=%d]:", params->DEREncoding.len); + printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len); for (i = 0; i < params->DEREncoding.len; i++) printf("%02x:", params->DEREncoding.data[i]); printf("\n"); - mp_tohex(k, mpstr); - printf("ec_point_mul: scalar : %s\n", mpstr); - mp_todecimal(k, mpstr); - printf("ec_point_mul: scalar : %s (dec)\n", mpstr); + if (k1 != NULL) { + mp_tohex(k1, mpstr); + printf("ec_points_mul: scalar k1: %s\n", mpstr); + mp_todecimal(k1, mpstr); + printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr); + } - printf("ec_point_mul: pointP [len=%d]:", pointP->len); - for (i = 0; i < pointP->len; i++) - printf("%02x:", pointP->data[i]); - printf("\n"); + if (k2 != NULL) { + mp_tohex(k2, mpstr); + printf("ec_points_mul: scalar k2: %s\n", mpstr); + mp_todecimal(k2, mpstr); + printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr); + } + + if (pointP != NULL) { + printf("ec_points_mul: pointP [len=%d]:", pointP->len); + for (i = 0; i < pointP->len; i++) + printf("%02x:", pointP->data[i]); + printf("\n"); + } #endif - /* NOTE: We only support prime field curves for now */ - len = (params->fieldID.size + 7) >> 3; - if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) || - (pointP->len != (2 * len + 1))) { - return SECFailure; - }; - - MP_DIGITS(&Px) = 0; - MP_DIGITS(&Py) = 0; - MP_DIGITS(&Qx) = 0; - MP_DIGITS(&Qy) = 0; - MP_DIGITS(&irreducible) = 0; - MP_DIGITS(&a) = 0; - MP_DIGITS(&b) = 0; - CHECK_MPI_OK( mp_init(&Px) ); - CHECK_MPI_OK( mp_init(&Py) ); - CHECK_MPI_OK( mp_init(&Qx) ); - CHECK_MPI_OK( mp_init(&Qy) ); - CHECK_MPI_OK( mp_init(&irreducible) ); - CHECK_MPI_OK( mp_init(&a) ); - CHECK_MPI_OK( mp_init(&b) ); - - /* Initialize Px and Py */ - CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, - (mp_size) len) ); - CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, - (mp_size) len) ); - - /* Set up mp_ints containing the curve coefficients */ - SECITEM_TO_MPINT( params->curve.a, &a ); - SECITEM_TO_MPINT( params->curve.b, &b ); - - /* Compute Q = k * P */ - if (params->fieldID.type == ec_field_GFp) { - SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible ); - if (GFp_ec_pt_mul(&irreducible, &a, &b, &Px, &Py, k, &Qx, &Qy) - != SECSuccess) - goto cleanup; - } else { - SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible ); - if (GF2m_ec_pt_mul(&irreducible, &a, &b, &Px, &Py, k, &Qx, &Qy) - != SECSuccess) { - goto cleanup; + /* NOTE: We only support uncompressed points for now */ + len = (params->fieldID.size + 7) >> 3; + if (pointP != NULL) { + if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) || + (pointP->len != (2 * len + 1))) { + return SECFailure; + }; } + + MP_DIGITS(&Px) = 0; + MP_DIGITS(&Py) = 0; + MP_DIGITS(&Qx) = 0; + MP_DIGITS(&Qy) = 0; + MP_DIGITS(&Gx) = 0; + MP_DIGITS(&Gy) = 0; + MP_DIGITS(&order) = 0; + MP_DIGITS(&irreducible) = 0; + MP_DIGITS(&a) = 0; + MP_DIGITS(&b) = 0; + CHECK_MPI_OK( mp_init(&Px) ); + CHECK_MPI_OK( mp_init(&Py) ); + CHECK_MPI_OK( mp_init(&Qx) ); + CHECK_MPI_OK( mp_init(&Qy) ); + CHECK_MPI_OK( mp_init(&Gx) ); + CHECK_MPI_OK( mp_init(&Gy) ); + CHECK_MPI_OK( mp_init(&order) ); + CHECK_MPI_OK( mp_init(&irreducible) ); + CHECK_MPI_OK( mp_init(&a) ); + CHECK_MPI_OK( mp_init(&b) ); + + if ((k2 != NULL) && (pointP != NULL)) { + /* Initialize Px and Py */ + CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) ); + CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) ); + } + + /* construct from named params, if possible */ + if (params->name != ECCurve_noName) { + group = ECGroup_fromName(params->name); + } + +#if 0 /* currently don't support non-named curves */ + if (group == NULL) { + /* Set up mp_ints containing the curve coefficients */ + CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1, + (mp_size) len) ); + CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len, + (mp_size) len) ); + SECITEM_TO_MPINT( params->order, &order ); + SECITEM_TO_MPINT( params->curve.a, &a ); + SECITEM_TO_MPINT( params->curve.b, &b ); + if (params->fieldID.type == ec_field_GFp) { + SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible ); + group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor); + } else { + SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible ); + irr_arr[0] = params->fieldID.size; + irr_arr[1] = params->fieldID.k1; + irr_arr[2] = params->fieldID.k2; + irr_arr[3] = params->fieldID.k3; + irr_arr[4] = 0; + group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor); + } + } +#endif + if (group == NULL) + goto cleanup; + + if ((k2 != NULL) && (pointP != NULL)) { + CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) ); + } else { + CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) ); } /* Construct the SECItem representation of point Q */ @@ -271,17 +193,21 @@ ec_point_mul(ECParams *params, mp_int *k, rv = SECSuccess; #if EC_DEBUG - printf("ec_point_mul: pointQ [len=%d]:", pointQ->len); + printf("ec_points_mul: pointQ [len=%d]:", pointQ->len); for (i = 0; i < pointQ->len; i++) printf("%02x:", pointQ->data[i]); printf("\n"); #endif cleanup: + ECGroup_free(group); mp_clear(&Px); mp_clear(&Py); mp_clear(&Qx); mp_clear(&Qy); + mp_clear(&Gx); + mp_clear(&Gy); + mp_clear(&order); mp_clear(&irreducible); mp_clear(&a); mp_clear(&b); @@ -335,6 +261,9 @@ EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, return SECFailure; } + /* Set the version number (SEC 1 section C.4 says it should be 1) */ + SECITEM_AllocItem(arena, &key->version, 1); + key->version.data[0] = 1; /* Copy all of the fields from the ECParams argument to the * ECParams structure within the private key. @@ -366,6 +295,9 @@ EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, key->ecParams.cofactor = ecParams->cofactor; CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding, &ecParams->DEREncoding)); + key->ecParams.name = ecParams->name; + CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID, + &ecParams->curveOID)); len = (ecParams->fieldID.size + 7) >> 3; SECITEM_AllocItem(arena, &key->privateValue, len); @@ -385,7 +317,7 @@ EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data, (mp_size) len) ); - rv = ec_point_mul(ecParams, &k, &(ecParams->base), &(key->publicValue)); + rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue)); if (rv != SECSuccess) goto cleanup; *privKey = key; @@ -523,7 +455,7 @@ ECDH_Derive(SECItem *publicValue, } /* Multiply our private key and peer's public point */ - if ((ec_point_mul(ecParams, &k, publicValue, &pointQ) != SECSuccess) || + if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ) != SECSuccess) || ec_point_at_infinity(&pointQ)) goto cleanup; @@ -611,6 +543,13 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) ); /* Make sure k is in the interval [1, n-1] */ if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) { +#if EC_DEBUG + printf("k is outside [1, n-1]\n"); + mp_tohex(&k, mpstr); + printf("k : %s \n", mpstr); + mp_tohex(&n, mpstr); + printf("n : %s \n", mpstr); +#endif PORT_SetError(SEC_ERROR_NEED_RANDOM); goto cleanup; } @@ -623,7 +562,7 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, kGpoint.len = 2*len + 1; kGpoint.data = PORT_Alloc(2*len + 1); if ((kGpoint.data == NULL) || - (ec_point_mul(ecParams, &k, &(ecParams->base), &kGpoint) + (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint) != SECSuccess)) goto cleanup; @@ -670,6 +609,8 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, printf("digest: %s (decimal)\n", mpstr); mp_todecimal(&r, mpstr); printf("r : %s (dec)\n", mpstr); + mp_tohex(&r, mpstr); + printf("r : %s\n", mpstr); #endif CHECK_MPI_OK( mp_invmod(&k, &n, &k) ); /* k = k**-1 mod n */ @@ -680,6 +621,8 @@ ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, #if EC_DEBUG mp_todecimal(&s, mpstr); printf("s : %s (dec)\n", mpstr); + mp_tohex(&s, mpstr); + printf("s : %s\n", mpstr); #endif /* @@ -740,9 +683,10 @@ ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest) SECStatus rv = SECFailure; #ifdef NSS_ENABLE_ECC int prerr = 0; - int n = (key->ecParams.fieldID.size + 7) >> 3; - unsigned char mask = bitmask[n * 8 - key->ecParams.fieldID.size]; + int n = key->ecParams.order.len; unsigned char *kseed = NULL; + unsigned char *mask; + int i; /* Generate random seed of appropriate size as dictated * by field size. @@ -752,9 +696,29 @@ ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest) do { if (RNG_GenerateGlobalRandomBytes(kseed, n) != SECSuccess) goto cleanup; - *kseed &= mask; - rv = ECDSA_SignDigestWithSeed(key, signature, digest, kseed, n); - if (rv) prerr = PORT_GetError(); + /* make sure that kseed is smaller than the curve order */ + mask = key->ecParams.order.data; + for (i = 0; (i < n) && (*mask == 0x00); i++, mask++) { +#if EC_DEBUG + printf("replacing byte %02x in position %d [n=%d] with zero\n", + *(kseed + i), i, n); +#endif + *(kseed + i) = 0x00; + } + + if (i == n) { + rv = SECFailure; + prerr = SEC_ERROR_NEED_RANDOM; + } else { +#if EC_DEBUG + printf("replacing byte %02x in position %d [n=%d] with %d\n", + *(kseed + i), i, n, (*mask - 1)); +#endif + if (*(kseed + i) >= *mask) + *(kseed + i) = *mask - 1; + rv = ECDSA_SignDigestWithSeed(key, signature, digest, kseed, n); + if (rv) prerr = PORT_GetError(); + } } while ((rv != SECSuccess) && (prerr == SEC_ERROR_NEED_RANDOM)); cleanup: @@ -903,11 +867,7 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, ** Here, A = u1.G B = u2.Q and C = A + B ** If the result, C, is the point at infinity, reject the signature */ - if ((ec_point_mul(ecParams, &u1, &ecParams->base, &pointA) - == SECFailure) || - (ec_point_mul(ecParams, &u2, &key->publicValue, &pointB) - == SECFailure) || - (ec_point_add(ecParams, &pointA, &pointB, &pointC) == SECFailure) || + if ((ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC) == SECFailure) || ec_point_at_infinity(&pointC)) { rv = SECFailure; goto cleanup; @@ -922,6 +882,13 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, */ CHECK_MPI_OK( mp_mod(&x1, &n, &v) ); +#if EC_DEBUG + mp_todecimal(&r_, mpstr); + printf("r_: %s (dec)\n", mpstr); + mp_todecimal(&v, mpstr); + printf("v : %s (dec)\n", mpstr); +#endif + /* ** ANSI X9.62, Section 5.4.4, Step 3 ** diff --git a/security/nss/lib/freebl/ecl/Makefile b/security/nss/lib/freebl/ecl/Makefile new file mode 100644 index 000000000000..5ee99a730063 --- /dev/null +++ b/security/nss/lib/freebl/ecl/Makefile @@ -0,0 +1,224 @@ +## +## Makefile for elliptic curve library +## +## The contents of this file are subject to the Mozilla Public +## License Version 1.1 (the "License"); you may not use this file +## except in compliance with the License. You may obtain a copy of +## the License at http://www.mozilla.org/MPL/ +## +## Software distributed under the License is distributed on an "AS +## IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +## implied. See the License for the specific language governing +## rights and limitations under the License. +## +## The Original Code is the elliptic curve math library. +## +## The Initial Developer of the Original Code is Sun Microsystems, Inc. +## Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +## Sun Microsystems, Inc. All Rights Reserved. +## +## Portions created by Michael J. Fromberger are +## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved. +## +## Contributor(s): +## Douglas Stebila +## Michael J. Fromberger +## Netscape Communications Corporation +## Richard C. Swift (swift@netscape.com) +## +## Alternatively, the contents of this file may be used under the +## terms of the GNU General Public License Version 2 or later (the +## "GPL"), in which case the provisions of the GPL are applicable +## instead of those above. If you wish to allow use of your +## version of this file only under the terms of the GPL and not to +## allow others to use your version of this file under the MPL, +## indicate your decision by deleting the provisions above and +## replace them with the notice and other provisions required by +## the GPL. If you do not delete the provisions above, a recipient +## may use your version of this file under either the MPL or the +## GPL. + +## 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 +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_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/security/nss/lib/freebl/ecl/README b/security/nss/lib/freebl/ecl/README new file mode 100644 index 000000000000..0265675c3192 --- /dev/null +++ b/security/nss/lib/freebl/ecl/README @@ -0,0 +1,329 @@ + +Version: MPL 1.1/GPL 2.0/LGPL 2.1 + +The contents of this file are subject to the Mozilla Public License Version +1.1 (the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at +http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the +License. + +The Original Code is the elliptic curve math library. + +The Initial Developer of the Original Code is Sun Microsystems, Inc. +Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +Sun Microsystems, Inc. All Rights Reserved. + +Contributor(s): + Stephen Fung and + Douglas Stebila , 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. + + +The ECL exposes routines for constructing and converting curve +parameters for internal use. + + +HEADER FILES +============ + +ecl-exp.h - Exports data structures and curve names. For use by code +that does not have access to mp_ints. + +ecl-curve.h - Provides hex encodings (in the form of ECCurveParams +structs) of standardizes elliptic curve domain parameters and mappings +from ECCurveName to ECCurveParams. For use be code that does not have +access to mp_ints. + +ecl.h - Interface to constructors for curve parameters and group object, +and point multiplication operations. Used by higher level algorithms +(like ECDH and ECDSA) to actually perform elliptic curve cryptography. + +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. + +DATA STRUCTURES AND TYPES +========================= + +ECCurveName (from ecl-exp.h) - Opaque name for standardized elliptic +curve domain parameters. + +ECCurveParams (from ecl-exp.h) - Provides hexadecimal encoding +of elliptic curve domain parameters. Can be generated by a user +and passed to ECGroup_fromHex or can be generated from a name by +EC_GetNamedCurveParams. ecl-curve.h contains ECCurveParams structs for +the standardized curves defined by ECCurveName. + +ECGroup (from ecl.h and ecl-priv.h) - Opaque data structure that +represents a group of elliptic curve points for a particular set of +elliptic curve domain parameters. Contains all domain parameters (curve +a and b, field, base point) as well as pointers to the functions that +should be used for point arithmetic and the underlying field GFMethod. +Generated by either ECGroup_fromHex or ECGroup_fromName. + +GFMethod (from ecl-priv.h) - Represents a field underlying a set of +elliptic curve domain parameters. Contains the irreducible that defines +the field (either the prime or the binary polynomial) as well as +pointers to the functions that should be used for field arithmetic. + +ARITHMETIC FUNCTIONS +==================== + +Higher-level algorithms (like ECDH and ECDSA) should call ECPoint_mul +or ECPoints_mul (from ecl.h) to do point arithmetic. These functions +will choose which underlying algorithms to use, based on the ECGroup +structure. + +Point Multiplication +-------------------- + +ecl_mult.c provides the ECPoints_mul and ECPoint_mul wrappers. +It also provides two implementations for the pts_mul operation - +ec_pts_mul_basic (which computes kP, lQ, and then adds kP + lQ) and +ec_pts_mul_simul_w2 (which does a simultaneous point multiplication +using a table with window size 2*2). + +ec_naf.c provides an implementation of an algorithm to calculate a +non-adjacent form of a scalar, minimizing the number of point +additions that need to be done in a point multiplication. + +Point Arithmetic over Prime Fields +---------------------------------- + +ecp_aff.c provides point arithmetic using affine coordinates. + +ecp_jac.c provides point arithmetic using Jacobian projective +coordinates and mixed Jacobian-affine coordinates. (Jacobian projective +coordinates represent a point (x, y) as (X, Y, Z), where x=X/Z^2, +y=Y/Z^3). + +ecp_jm.c provides point arithmetic using Modified Jacobian +coordinates and mixed Modified_Jacobian-affine coordinates. +(Modified Jacobian coordinates represent a point (x, y) +as (X, Y, Z, a*Z^4), where x=X/Z^2, y=Y/Z^3, and a is +the linear coefficient in the curve defining equation). + +ecp_192.c and ecp_224.c provide optimized field arithmetic. + +Point Arithmetic over Binary Polynomial Fields +---------------------------------------------- + +ec2_aff.c provides point arithmetic using affine coordinates. + +ec2_proj.c provides point arithmetic using projective coordinates. +(Projective coordinates represent a point (x, y) as (X, Y, Z), where +x=X/Z, y=Y/Z^2). + +ec2_mont.c provides point multiplication using Montgomery projective +coordinates. + +ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic. + +Field Arithmetic +---------------- + +ecl_gf.c provides constructors for field objects (GFMethod) with the +functions GFMethod_cons*. It also provides wrappers around the basic +field operations. + +Prime Field Arithmetic +---------------------- + +The mpi library provides the basic prime field arithmetic. + +ecp_mont.c provides wrappers around the Montgomery multiplication +functions from the mpi library and adds encoding and decoding functions. +It also provides the function to construct a GFMethod object using +Montgomery multiplication. + +ecp_192.c and ecp_224.c provide optimized modular reduction for the +fields defined by nistp192 and nistp224 primes. + +ecl_gf.c provides wrappers around the basic field operations. + +Binary Polynomial Field Arithmetic +---------------------------------- + +../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic, +including addition, multiplication, squaring, mod, and division, as well +as conversion ob polynomial representations between bitstring and int[]. + +ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul, +and sqr operations. + +ecl_gf.c provides wrappers around the basic field operations. + +Field Encoding +-------------- + +By default, field elements are encoded in their basic form. It is +possible to use an alternative encoding, however. For example, it is +possible to Montgomery representation of prime field elements and +take advantage of the fast modular multiplication that Montgomery +representation provides. The process of converting from basic form to +Montgomery representation is called field encoding, and the opposite +process would be field decoding. All internal point operations assume +that the operands are field encoded as appropriate. By rewiring the +underlying field arithmetic to perform operations on these encoded +values, the same overlying point arithmetic operations can be used +regardless of field representation. + +ALGORITHM WIRING +================ + +The EC library allows point and field arithmetic algorithms to be +substituted ("wired-in") on a fine-grained basis. This allows for +generic algorithms and algorithms that are optimized for a particular +curve, field, or architecture, to coexist and to be automatically +selected at runtime. + +Wiring Mechanism +---------------- + +The ECGroup and GFMethod structure contain pointers to the point and +field arithmetic functions, respectively, that are to be used in +operations. + +The selection of algorithms to use is handled in the function +ecgroup_fromNameAndHex in ecl.c. + +Default Wiring +-------------- + +Curves over prime fields by default use montgomery field arithmetic, +point multiplication using 5-bit window non-adjacent-form with +Modified Jacobian coordinates, and 2*2-bit simultaneous point +multiplication using Jacobian coordinates. +(Wiring in function ECGroup_consGFp_mont in ecl.c.) + +Curves over prime fields that have optimized modular reduction (i.e., +secp160r1, nistp192, and nistp224) do not use Montgomery field +arithmetic. Instead, they use basic field arithmetic with their +optimized reduction (as in ecp_192.c and ecp_224.c). They +use the same point multiplication and simultaneous point multiplication +algorithms as other curves over prime fields. + +Curves over binary polynomial fields by default use generic field +arithmetic with montgomery point multiplication and basic kP + lQ +computation (multiply, multiply, and add). (Wiring in function +ECGroup_cons_GF2m in ecl.c.) + +Curves over binary polynomial fields that have optimized field +arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized +field arithmetic. They use the same point multiplication and +simultaneous point multiplication algorithms as other curves over binary +fields. + +Example +------- + +We provide an example for plugging in an optimized implementation for +the Koblitz curve nistk163. + +Suppose the file ec2_k163.c contains the optimized implementation. In +particular it contains a point multiplication function: + + mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px, + const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group); + +Since only a pt_mul function is provided, the generic pt_add function +will be used. + +There are two options for handling the optimized field arithmetic used +by the ..._pt_mul function. Say the optimized field arithmetic includes +the following functions: + + mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b, + mp_int *r, const GFMethod *meth); + mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b, + mp_int *r, const GFMethod *meth); + mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b, + mp_int *r, const GFMethod *meth); + mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b, + mp_int *r, const GFMethod *meth); + +First, the optimized field arithmetic could simply be called directly +by the ..._pt_mul function. This would be accomplished by changing +the ecgroup_fromNameAndHex function in ecl.c to include the following +statements: + + if (name == ECCurve_NIST_K163) { + group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, + &geny, &order, params->cofactor); + if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } + MP_CHECKOK( ec_group_set_nistk163(group) ); + } + +and including in ec2_k163.c the following function: + + mp_err ec_group_set_nistk163(ECGroup *group) { + group->point_mul = &ec_GF2m_nistk163_pt_mul; + return MP_OKAY; + } + +As a result, ec_GF2m_pt_add and similar functions would use the +basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul, +ec_GF2m_sqr, and ec_GF2m_div. + +Alternatively, the optimized field arithmetic could be wired into the +group's GFMethod. This would be accomplished by putting the following +function in ec2_k163.c: + + mp_err ec_group_set_nistk163(ECGroup *group) { + group->meth->field_add = &ec_GF2m_nistk163_add; + group->meth->field_mul = &ec_GF2m_nistk163_mul; + group->meth->field_sqr = &ec_GF2m_nistk163_sqr; + group->meth->field_div = &ec_GF2m_nistk163_div; + group->point_mul = &ec_GF2m_nistk163_pt_mul; + return MP_OKAY; + } + +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/security/nss/lib/freebl/ecl/README.FP b/security/nss/lib/freebl/ecl/README.FP new file mode 100644 index 000000000000..e92a5affea92 --- /dev/null +++ b/security/nss/lib/freebl/ecl/README.FP @@ -0,0 +1,316 @@ + +Version: MPL 1.1/GPL 2.0/LGPL 2.1 + +The contents of this file are subject to the Mozilla Public License Version +1.1 (the "License"); you may not use this file except in compliance with +the License. You may obtain a copy of the License at +http://www.mozilla.org/MPL/ + +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the +License. + +The Original Code is the elliptic curve math library. + +The Initial Developer of the Original Code is Sun Microsystems, Inc. +Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +Sun Microsystems, Inc. All Rights Reserved. + +Contributor(s): + Stephen Fung and + Nils Gura , Sun Microsystems Laboratories + +Alternatively, the contents of this file may be used under the terms of +either the GNU General Public License Version 2 or later (the "GPL"), or +the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +in which case the provisions of the GPL or the LGPL are applicable instead +of those above. If you wish to allow use of your version of this file only +under the terms of either the GPL or the LGPL, and not to allow others to +use your version of this file under the terms of the MPL, indicate your +decision by deleting the provisions above and replace them with the notice +and other provisions required by the GPL or the LGPL. If you do not delete +the provisions above, a recipient may use your version of this file under +the terms of any one of the MPL, the GPL or the LGPL. + + +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/security/nss/lib/freebl/ecl/ec2.h b/security/nss/lib/freebl/ecl/ec2.h new file mode 100644 index 000000000000..2c66b55f53ad --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2.h @@ -0,0 +1,122 @@ +/* + * 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 binary polynomial + * 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 , 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. + * + */ + +#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); + +/* 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/security/nss/lib/freebl/ecl/ec2_163.c b/security/nss/lib/freebl/ecl/ec2_163.c new file mode 100644 index 000000000000..d6872500d2c0 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_163.c @@ -0,0 +1,258 @@ +/* + * 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 binary polynomial + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , 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 "ec2.h" +#include "mp_gf2m.h" +#include "mp_gf2m-priv.h" +#include "mpi.h" +#include "mpi-priv.h" +#include + +/* 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/security/nss/lib/freebl/ecl/ec2_193.c b/security/nss/lib/freebl/ecl/ec2_193.c new file mode 100644 index 000000000000..5035a99bdbea --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_193.c @@ -0,0 +1,275 @@ +/* + * 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 binary polynomial + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , 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 "ec2.h" +#include "mp_gf2m.h" +#include "mp_gf2m-priv.h" +#include "mpi.h" +#include "mpi-priv.h" +#include + +/* 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/security/nss/lib/freebl/ecl/ec2_233.c b/security/nss/lib/freebl/ecl/ec2_233.c new file mode 100644 index 000000000000..719854229de5 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_233.c @@ -0,0 +1,298 @@ +/* + * 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 binary polynomial + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , 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 "ec2.h" +#include "mp_gf2m.h" +#include "mp_gf2m-priv.h" +#include "mpi.h" +#include "mpi-priv.h" +#include + +/* 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/security/nss/lib/freebl/ecl/ec2_aff.c b/security/nss/lib/freebl/ecl/ec2_aff.c new file mode 100644 index 000000000000..5c7972c0c14e --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_aff.c @@ -0,0 +1,270 @@ +/* + * 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 binary polynomial + * 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 , 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 "ec2.h" +#include "mplogic.h" +#include "mp_gf2m.h" +#include + +/* 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 diff --git a/security/nss/lib/freebl/ecl/ec2_mont.c b/security/nss/lib/freebl/ecl/ec2_mont.c new file mode 100644 index 000000000000..6658d3295ed6 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_mont.c @@ -0,0 +1,276 @@ +/* + * 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 binary polynomial + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , 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 "ec2.h" +#include "mplogic.h" +#include "mp_gf2m.h" +#include + +/* 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(rx, &x2)); /* x2 = rx */ + MP_CHECKOK(mp_copy(ry, &z2)); /* z2 = ry */ + + 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 = + * x2^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/security/nss/lib/freebl/ecl/ec2_proj.c b/security/nss/lib/freebl/ecl/ec2_proj.c new file mode 100644 index 000000000000..8df72433cb71 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec2_proj.c @@ -0,0 +1,368 @@ +/* + * 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 binary polynomial + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , 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 "ec2.h" +#include "mplogic.h" +#include "mp_gf2m.h" +#include +#ifdef ECL_DEBUG +#include +#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/security/nss/lib/freebl/ecl/ec_naf.c b/security/nss/lib/freebl/ecl/ec_naf.c new file mode 100644 index 000000000000..a6b04add8033 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ec_naf.c @@ -0,0 +1,101 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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 "ecl-priv.h" + +/* 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; + + 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 + * 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) +{ + mp_int k; + mp_err res = MP_OKAY; + int i, twowm1, mask; + + twowm1 = ec_twoTo(w - 1); + mask = 2 * twowm1 - 1; + + 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; + +} diff --git a/security/nss/lib/freebl/ecl/ecl-curve.h b/security/nss/lib/freebl/ecl/ecl-curve.h new file mode 100644 index 000000000000..5c03f3a84938 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl-curve.h @@ -0,0 +1,646 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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 "ecl-exp.h" +#include + +#ifndef __ecl_curve_h_ +#define __ecl_curve_h_ + +/* NIST prime curves */ +static const ECCurveParams ecCurve_NIST_P192 = { + "NIST-P192", ECField_GFp, 192, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", 1 +}; +static const ECCurveParams ecCurve_NIST_P224 = { + "NIST-P224", ECField_GFp, 224, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", 1 +}; +static const ECCurveParams ecCurve_NIST_P256 = { + "NIST-P256", ECField_GFp, 256, + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 1 +}; +static const ECCurveParams ecCurve_NIST_P384 = { + "NIST-P384", ECField_GFp, 384, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", + 1 +}; +static const ECCurveParams ecCurve_NIST_P521 = { + "NIST-P521", ECField_GFp, 521, + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", + "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", + 1 +}; + +/* NIST binary curves */ +static const ECCurveParams ecCurve_NIST_K163 = { + "NIST-K163", ECField_GF2m, 163, + "0800000000000000000000000000000000000000C9", + "000000000000000000000000000000000000000001", + "000000000000000000000000000000000000000001", + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8", + "0289070FB05D38FF58321F2E800536D538CCDAA3D9", + "04000000000000000000020108A2E0CC0D99F8A5EF", 2 +}; +static const ECCurveParams ecCurve_NIST_B163 = { + "NIST-B163", ECField_GF2m, 163, + "0800000000000000000000000000000000000000C9", + "000000000000000000000000000000000000000001", + "020A601907B8C953CA1481EB10512F78744A3205FD", + "03F0EBA16286A2D57EA0991168D4994637E8343E36", + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", + "040000000000000000000292FE77E70C12A4234C33", 2 +}; +static const ECCurveParams ecCurve_NIST_K233 = { + "NIST-K233", ECField_GF2m, 233, + "020000000000000000000000000000000000000004000000000000000001", + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126", + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3", + "008000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF", 4 +}; +static const ECCurveParams ecCurve_NIST_B233 = { + "NIST-B233", ECField_GF2m, 233, + "020000000000000000000000000000000000000004000000000000000001", + "000000000000000000000000000000000000000000000000000000000001", + "0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD", + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B", + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052", + "01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7", 2 +}; +static const ECCurveParams ecCurve_NIST_K283 = { + "NIST-K283", ECField_GF2m, 283, + "0800000000000000000000000000000000000000000000000000000000000000000010A1", + "000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000001", + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836", + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259", + "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61", + 4 +}; +static const ECCurveParams ecCurve_NIST_B283 = { + "NIST-B283", ECField_GF2m, 283, + "0800000000000000000000000000000000000000000000000000000000000000000010A1", + "000000000000000000000000000000000000000000000000000000000000000000000001", + "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5", + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053", + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307", + 2 +}; +static const ECCurveParams ecCurve_NIST_K409 = { + "NIST-K409", ECField_GF2m, 409, + "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746", + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B", + "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF", + 4 +}; +static const ECCurveParams ecCurve_NIST_B409 = { + "NIST-B409", ECField_GF2m, 409, + "02000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000001", + "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F", + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7", + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706", + "010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173", + 2 +}; +static const ECCurveParams ecCurve_NIST_K571 = { + "NIST-K571", ECField_GF2m, 571, + "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972", + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3", + "020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001", + 4 +}; +static const ECCurveParams ecCurve_NIST_B571 = { + "NIST-B571", ECField_GF2m, 571, + "080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000425", + "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", + "02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A", + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19", + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B", + "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47", + 2 +}; + +/* ANSI X9.62 prime curves */ +static const ECCurveParams ecCurve_X9_62_PRIME_192V2 = { + "X9.62 P-192V2", ECField_GFp, 192, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", + "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", + "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", + "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", 1 +}; +static const ECCurveParams ecCurve_X9_62_PRIME_192V3 = { + "X9.62 P-192V3", ECField_GFp, 192, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", + "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", + "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", + "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", + "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", 1 +}; +static const ECCurveParams ecCurve_X9_62_PRIME_239V1 = { + "X9.62 P-239V1", ECField_GFp, 239, + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", + "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", + "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", 1 +}; +static const ECCurveParams ecCurve_X9_62_PRIME_239V2 = { + "X9.62 P-239V2", ECField_GFp, 239, + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", + "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", + "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", + "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", 1 +}; +static const ECCurveParams ecCurve_X9_62_PRIME_239V3 = { + "X9.62 P-239V3", ECField_GFp, 239, + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", + "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", + "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", + "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", 1 +}; + +/* ANSI X9.62 binary curves */ +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V1 = { + "X9.62 C2-PNB163V1", ECField_GF2m, 163, + "080000000000000000000000000000000000000107", + "072546B5435234A422E0789675F432C89435DE5242", + "00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", + "07AF69989546103D79329FCC3D74880F33BBE803CB", + "01EC23211B5966ADEA1D3F87F7EA5848AEF0B7CA9F", + "0400000000000000000001E60FC8821CC74DAEAFC1", 2 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V2 = { + "X9.62 C2-PNB163V2", ECField_GF2m, 163, + "080000000000000000000000000000000000000107", + "0108B39E77C4B108BED981ED0E890E117C511CF072", + "0667ACEB38AF4E488C407433FFAE4F1C811638DF20", + "0024266E4EB5106D0A964D92C4860E2671DB9B6CC5", + "079F684DDF6684C5CD258B3890021B2386DFD19FC5", + "03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 2 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB163V3 = { + "X9.62 C2-PNB163V3", ECField_GF2m, 163, + "080000000000000000000000000000000000000107", + "07A526C63D3E25A256A007699F5447E32AE456B50E", + "03F7061798EB99E238FD6F1BF95B48FEEB4854252B", + "02F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB", + "05B935590C155E17EA48EB3FF3718B893DF59A05D0", + "03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 2 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB176V1 = { + "X9.62 C2-PNB176V1", ECField_GF2m, 176, + "0100000000000000000000000000000000080000000007", + "E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", + "5DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", + "8D16C2866798B600F9F08BB4A8E860F3298CE04A5798", + "6FA4539C2DADDDD6BAB5167D61B436E1D92BB16A562C", + "00010092537397ECA4F6145799D62B0A19CE06FE26AD", 0xFF6E +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V1 = { + "X9.62 C2-TNB191V1", ECField_GF2m, 191, + "800000000000000000000000000000000000000000000201", + "2866537B676752636A68F56554E12640276B649EF7526267", + "2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", + "36B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D", + "765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB", + "40000000000000000000000004A20E90C39067C893BBB9A5", 2 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V2 = { + "X9.62 C2-TNB191V2", ECField_GF2m, 191, + "800000000000000000000000000000000000000000000201", + "401028774D7777C7B7666D1366EA432071274F89FF01E718", + "0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", + "3809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10", + "17434386626D14F3DBF01760D9213A3E1CF37AEC437D668A", + "20000000000000000000000050508CB89F652824E06B8173", 4 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB191V3 = { + "X9.62 C2-TNB191V3", ECField_GF2m, 191, + "800000000000000000000000000000000000000000000201", + "6C01074756099122221056911C77D77E77A777E7E7E77FCB", + "71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", + "375D4CE24FDE434489DE8746E71786015009E66E38A926DD", + "545A39176196575D985999366E6AD34CE0A77CD7127B06BE", + "155555555555555555555555610C0B196812BFB6288A3EA3", 6 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB208W1 = { + "X9.62 C2-PNB208W1", ECField_GF2m, 208, + "010000000000000000000000000000000800000000000000000007", + "0000000000000000000000000000000000000000000000000000", + "C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", + "89FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A", + "0F55B51A06E78E9AC38A035FF520D8B01781BEB1A6BB08617DE3", + "000101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 0xFE48 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V1 = { + "X9.62 C2-TNB239V1", ECField_GF2m, 239, + "800000000000000000000000000000000000000000000000001000000001", + "32010857077C5431123A46B808906756F543423E8D27877578125778AC76", + "790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", + "57927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D", + "61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305", + "2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 4 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V2 = { + "X9.62 C2-TNB239V2", ECField_GF2m, 239, + "800000000000000000000000000000000000000000000000001000000001", + "4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", + "5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", + "28F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205", + "5667334C45AFF3B5A03BAD9DD75E2C71A99362567D5453F7FA6E227EC833", + "1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 6 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB239V3 = { + "X9.62 C2-TNB239V3", ECField_GF2m, 239, + "800000000000000000000000000000000000000000000000001000000001", + "01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", + "6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", + "70F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92", + "2E5A0EAF6E5E1305B9004DCE5C0ED7FE59A35608F33837C816D80B79F461", + "0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 0xA +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB272W1 = { + "X9.62 C2-PNB272W1", ECField_GF2m, 272, + "010000000000000000000000000000000000000000000000000000010000000000000B", + "91A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", + "7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", + "6108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D", + "10C7695716851EEF6BA7F6872E6142FBD241B830FF5EFCACECCAB05E02005DDE9D23", + "000100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", + 0xFF06 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB304W1 = { + "X9.62 C2-PNB304W1", ECField_GF2m, 304, + "010000000000000000000000000000000000000000000000000000000000000000000000000807", + "FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", + "BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", + "197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614", + "E19FBEB76E0DA171517ECF401B50289BF014103288527A9B416A105E80260B549FDC1B92C03B", + "000101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", + 0xFE2E +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB359V1 = { + "X9.62 C2-TNB359V1", ECField_GF2m, 359, + "800000000000000000000000000000000000000000000000000000000000000000000000100000000000000001", + "5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", + "2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", + "3C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097", + "53D7E08529547048121E9C95F3791DD804963948F34FAE7BF44EA82365DC7868FE57E4AE2DE211305A407104BD", + "01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", + 0x4C +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_PNB368W1 = { + "X9.62 C2-PNB368W1", ECField_GF2m, 368, + "0100000000000000000000000000000000000000000000000000000000000000000000002000000000000000000007", + "E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", + "FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", + "1085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F", + "7B3EB1BDDCBA62D5D8B2059B525797FC73822C59059C623A45FF3843CEE8F87CD1855ADAA81E2A0750B80FDA2310", + "00010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", + 0xFF70 +}; +static const ECCurveParams ecCurve_X9_62_CHAR2_TNB431R1 = { + "X9.62 C2-TNB431R1", ECField_GF2m, 431, + "800000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000001", + "1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", + "10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", + "120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7", + "20D0AF8903A96F8D5FA2C255745D3C451B302C9346D9B7E485E7BCE41F6B591F3E8F6ADDCBB0BC4C2F947A7DE1A89B625D6A598B3760", + "0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", + 0x2760 +}; + +/* SEC2 prime curves */ +static const ECCurveParams ecCurve_SECG_PRIME_112R1 = { + "SECP-112R1", ECField_GFp, 112, + "DB7C2ABF62E35E668076BEAD208B", + "DB7C2ABF62E35E668076BEAD2088", + "659EF8BA043916EEDE8911702B22", + "09487239995A5EE76B55F9C2F098", + "A89CE5AF8724C0A23E0E0FF77500", + "DB7C2ABF62E35E7628DFAC6561C5", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_112R2 = { + "SECP-112R2", ECField_GFp, 112, + "DB7C2ABF62E35E668076BEAD208B", + "6127C24C05F38A0AAAF65C0EF02C", + "51DEF1815DB5ED74FCC34C85D709", + "4BA30AB5E892B4E1649DD0928643", + "adcd46f5882e3747def36e956e97", + "36DF0AAFD8B8D7597CA10520D04B", 4 +}; +static const ECCurveParams ecCurve_SECG_PRIME_128R1 = { + "SECP-128R1", ECField_GFp, 128, + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", + "E87579C11079F43DD824993C2CEE5ED3", + "161FF7528B899B2D0C28607CA52C5B86", + "CF5AC8395BAFEB13C02DA292DDED7A83", + "FFFFFFFE0000000075A30D1B9038A115", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_128R2 = { + "SECP-128R2", ECField_GFp, 128, + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", + "D6031998D1B3BBFEBF59CC9BBFF9AEE1", + "5EEEFCA380D02919DC2C6558BB6D8A5D", + "7B6AA5D85E572983E6FB32A7CDEBC140", + "27B6916A894D3AEE7106FE805FC34B44", + "3FFFFFFF7FFFFFFFBE0024720613B5A3", 4 +}; +static const ECCurveParams ecCurve_SECG_PRIME_160K1 = { + "SECP-160K1", ECField_GFp, 160, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "0000000000000000000000000000000000000000", + "0000000000000000000000000000000000000007", + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", + "938CF935318FDCED6BC28286531733C3F03C4FEE", + "0100000000000000000001B8FA16DFAB9ACA16B6B3", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_160R1 = { + "SECP-160R1", ECField_GFp, 160, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", + "4A96B5688EF573284664698968C38BB913CBFC82", + "23A628553168947D59DCC912042351377AC5FB32", + "0100000000000000000001F4C8F927AED3CA752257", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_160R2 = { + "SECP-160R2", ECField_GFp, 160, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", + "B4E134D3FB59EB8BAB57274904664D5AF50388BA", + "52DCB034293A117E1F4FF11B30F7199D3144CE6D", + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", + "0100000000000000000000351EE786A818F3A1A16B", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_192K1 = { + "SECP-192K1", ECField_GFp, 192, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", + "000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000003", + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_224K1 = { + "SECP-224K1", ECField_GFp, 224, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", + "00000000000000000000000000000000000000000000000000000000", + "00000000000000000000000000000000000000000000000000000005", + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", + "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7", 1 +}; +static const ECCurveParams ecCurve_SECG_PRIME_256K1 = { + "SECP-256K1", ECField_GFp, 256, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", + "0000000000000000000000000000000000000000000000000000000000000000", + "0000000000000000000000000000000000000000000000000000000000000007", + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 1 +}; + +/* SEC2 binary curves */ +static const ECCurveParams ecCurve_SECG_CHAR2_113R1 = { + "SECT-113R1", ECField_GF2m, 113, + "020000000000000000000000000201", + "003088250CA6E7C7FE649CE85820F7", + "00E8BEE4D3E2260744188BE0E9C723", + "009D73616F35F4AB1407D73562C10F", + "00A52830277958EE84D1315ED31886", + "0100000000000000D9CCEC8A39E56F", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_113R2 = { + "SECT-113R2", ECField_GF2m, 113, + "020000000000000000000000000201", + "00689918DBEC7E5A0DD6DFC0AA55C7", + "0095E9A9EC9B297BD4BF36E059184F", + "01A57A6A7B26CA5EF52FCDB8164797", + "00B3ADC94ED1FE674C06E695BABA1D", + "010000000000000108789B2496AF93", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_131R1 = { + "SECT-131R1", ECField_GF2m, 131, + "080000000000000000000000000000010D", + "07A11B09A76B562144418FF3FF8C2570B8", + "0217C05610884B63B9C6C7291678F9D341", + "0081BAF91FDF9833C40F9C181343638399", + "078C6E7EA38C001F73C8134B1B4EF9E150", + "0400000000000000023123953A9464B54D", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_131R2 = { + "SECT-131R2", ECField_GF2m, 131, + "080000000000000000000000000000010D", + "03E5A88919D7CAFCBF415F07C2176573B2", + "04B8266A46C55657AC734CE38F018F2192", + "0356DCD8F2F95031AD652D23951BB366A8", + "0648F06D867940A5366D9E265DE9EB240F", + "0400000000000000016954A233049BA98F", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_163R1 = { + "SECT-163R1", ECField_GF2m, 163, + "0800000000000000000000000000000000000000C9", + "07B6882CAAEFA84F9554FF8428BD88E246D2782AE2", + "0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9", + "0369979697AB43897789566789567F787A7876A654", + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883", + "03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_193R1 = { + "SECT-193R1", ECField_GF2m, 193, + "02000000000000000000000000000000000000000000008001", + "0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01", + "00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814", + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1", + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05", + "01000000000000000000000000C7F34A778F443ACC920EBA49", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_193R2 = { + "SECT-193R2", ECField_GF2m, 193, + "02000000000000000000000000000000000000000000008001", + "0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B", + "00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE", + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F", + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C", + "010000000000000000000000015AAB561B005413CCD4EE99D5", 2 +}; +static const ECCurveParams ecCurve_SECG_CHAR2_239K1 = { + "SECT-239K1", ECField_GF2m, 239, + "800000000000000000004000000000000000000000000000000000000001", + "000000000000000000000000000000000000000000000000000000000000", + "000000000000000000000000000000000000000000000000000000000001", + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC", + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA", + "2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5", 4 +}; + +/* WTLS curves */ +static const ECCurveParams ecCurve_WTLS_1 = { + "WTLS-1", ECField_GF2m, 113, + "020000000000000000000000000201", + "000000000000000000000000000001", + "000000000000000000000000000001", + "01667979A40BA497E5D5C270780617", + "00F44B4AF1ECC2630E08785CEBCC15", + "00FFFFFFFFFFFFFFFDBF91AF6DEA73", 2 +}; +static const ECCurveParams ecCurve_WTLS_8 = { + "WTLS-8", ECField_GFp, 112, + "FFFFFFFFFFFFFFFFFFFFFFFFFDE7", + "0000000000000000000000000000", + "0000000000000000000000000003", + "0000000000000000000000000001", + "0000000000000000000000000002", + "0100000000000001ECEA551AD837E9", 1 +}; +static const ECCurveParams ecCurve_WTLS_9 = { + "WTLS-9", ECField_GFp, 160, + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC808F", + "0000000000000000000000000000000000000000", + "0000000000000000000000000000000000000003", + "0000000000000000000000000000000000000001", + "0000000000000000000000000000000000000002", + "0100000000000000000001CDC98AE0E2DE574ABF33", 1 +}; + +/* mapping between ECCurveName enum and pointers to ECCurveParams */ +static const ECCurveParams *ecCurve_map[] = { + NULL, /* ECCurve_noName */ + &ecCurve_NIST_P192, /* ECCurve_NIST_P192 */ + &ecCurve_NIST_P224, /* ECCurve_NIST_P224 */ + &ecCurve_NIST_P256, /* ECCurve_NIST_P256 */ + &ecCurve_NIST_P384, /* ECCurve_NIST_P384 */ + &ecCurve_NIST_P521, /* ECCurve_NIST_P521 */ + &ecCurve_NIST_K163, /* ECCurve_NIST_K163 */ + &ecCurve_NIST_B163, /* ECCurve_NIST_B163 */ + &ecCurve_NIST_K233, /* ECCurve_NIST_K233 */ + &ecCurve_NIST_B233, /* ECCurve_NIST_B233 */ + &ecCurve_NIST_K283, /* ECCurve_NIST_K283 */ + &ecCurve_NIST_B283, /* ECCurve_NIST_B283 */ + &ecCurve_NIST_K409, /* ECCurve_NIST_K409 */ + &ecCurve_NIST_B409, /* ECCurve_NIST_B409 */ + &ecCurve_NIST_K571, /* ECCurve_NIST_K571 */ + &ecCurve_NIST_B571, /* ECCurve_NIST_B571 */ + &ecCurve_X9_62_PRIME_192V2, /* ECCurve_X9_62_PRIME_192V2 */ + &ecCurve_X9_62_PRIME_192V3, /* ECCurve_X9_62_PRIME_192V3 */ + &ecCurve_X9_62_PRIME_239V1, /* ECCurve_X9_62_PRIME_239V1 */ + &ecCurve_X9_62_PRIME_239V2, /* ECCurve_X9_62_PRIME_239V2 */ + &ecCurve_X9_62_PRIME_239V3, /* ECCurve_X9_62_PRIME_239V3 */ + &ecCurve_X9_62_CHAR2_PNB163V1, /* ECCurve_X9_62_CHAR2_PNB163V1 */ + &ecCurve_X9_62_CHAR2_PNB163V2, /* ECCurve_X9_62_CHAR2_PNB163V2 */ + &ecCurve_X9_62_CHAR2_PNB163V3, /* ECCurve_X9_62_CHAR2_PNB163V3 */ + &ecCurve_X9_62_CHAR2_PNB176V1, /* ECCurve_X9_62_CHAR2_PNB176V1 */ + &ecCurve_X9_62_CHAR2_TNB191V1, /* ECCurve_X9_62_CHAR2_TNB191V1 */ + &ecCurve_X9_62_CHAR2_TNB191V2, /* ECCurve_X9_62_CHAR2_TNB191V2 */ + &ecCurve_X9_62_CHAR2_TNB191V3, /* ECCurve_X9_62_CHAR2_TNB191V3 */ + &ecCurve_X9_62_CHAR2_PNB208W1, /* ECCurve_X9_62_CHAR2_PNB208W1 */ + &ecCurve_X9_62_CHAR2_TNB239V1, /* ECCurve_X9_62_CHAR2_TNB239V1 */ + &ecCurve_X9_62_CHAR2_TNB239V2, /* ECCurve_X9_62_CHAR2_TNB239V2 */ + &ecCurve_X9_62_CHAR2_TNB239V3, /* ECCurve_X9_62_CHAR2_TNB239V3 */ + &ecCurve_X9_62_CHAR2_PNB272W1, /* ECCurve_X9_62_CHAR2_PNB272W1 */ + &ecCurve_X9_62_CHAR2_PNB304W1, /* ECCurve_X9_62_CHAR2_PNB304W1 */ + &ecCurve_X9_62_CHAR2_TNB359V1, /* ECCurve_X9_62_CHAR2_TNB359V1 */ + &ecCurve_X9_62_CHAR2_PNB368W1, /* ECCurve_X9_62_CHAR2_PNB368W1 */ + &ecCurve_X9_62_CHAR2_TNB431R1, /* ECCurve_X9_62_CHAR2_TNB431R1 */ + &ecCurve_SECG_PRIME_112R1, /* ECCurve_SECG_PRIME_112R1 */ + &ecCurve_SECG_PRIME_112R2, /* ECCurve_SECG_PRIME_112R2 */ + &ecCurve_SECG_PRIME_128R1, /* ECCurve_SECG_PRIME_128R1 */ + &ecCurve_SECG_PRIME_128R2, /* ECCurve_SECG_PRIME_128R2 */ + &ecCurve_SECG_PRIME_160K1, /* ECCurve_SECG_PRIME_160K1 */ + &ecCurve_SECG_PRIME_160R1, /* ECCurve_SECG_PRIME_160R1 */ + &ecCurve_SECG_PRIME_160R2, /* ECCurve_SECG_PRIME_160R2 */ + &ecCurve_SECG_PRIME_192K1, /* ECCurve_SECG_PRIME_192K1 */ + &ecCurve_SECG_PRIME_224K1, /* ECCurve_SECG_PRIME_224K1 */ + &ecCurve_SECG_PRIME_256K1, /* ECCurve_SECG_PRIME_256K1 */ + &ecCurve_SECG_CHAR2_113R1, /* ECCurve_SECG_CHAR2_113R1 */ + &ecCurve_SECG_CHAR2_113R2, /* ECCurve_SECG_CHAR2_113R2 */ + &ecCurve_SECG_CHAR2_131R1, /* ECCurve_SECG_CHAR2_131R1 */ + &ecCurve_SECG_CHAR2_131R2, /* ECCurve_SECG_CHAR2_131R2 */ + &ecCurve_SECG_CHAR2_163R1, /* ECCurve_SECG_CHAR2_163R1 */ + &ecCurve_SECG_CHAR2_193R1, /* ECCurve_SECG_CHAR2_193R1 */ + &ecCurve_SECG_CHAR2_193R2, /* ECCurve_SECG_CHAR2_193R2 */ + &ecCurve_SECG_CHAR2_239K1, /* ECCurve_SECG_CHAR2_239K1 */ + &ecCurve_WTLS_1, /* ECCurve_WTLS_1 */ + &ecCurve_WTLS_8, /* ECCurve_WTLS_8 */ + &ecCurve_WTLS_9, /* ECCurve_WTLS_9 */ + NULL /* ECCurve_pastLastCurve */ +}; + +#endif diff --git a/security/nss/lib/freebl/ecl/ecl-exp.h b/security/nss/lib/freebl/ecl/ecl-exp.h new file mode 100644 index 000000000000..1a3421c81fd8 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl-exp.h @@ -0,0 +1,194 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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. + * + */ + +#ifndef __ecl_exp_h_ +#define __ecl_exp_h_ + +/* Curve field type */ +typedef enum { + 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; +}; +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 +} ECCurveName; + +/* Aliased named curves */ + +#define ECCurve_X9_62_PRIME_192V1 ECCurve_NIST_P192 +#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_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_ */ diff --git a/security/nss/lib/freebl/ecl/ecl-priv.h b/security/nss/lib/freebl/ecl/ecl-priv.h new file mode 100644 index 000000000000..908ed8ebc07b --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl-priv.h @@ -0,0 +1,216 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung and + * Douglas Stebila , 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. + * + */ + +#ifndef __ecl_priv_h_ +#define __ecl_priv_h_ + +#include "ecl.h" +#include "mpi.h" +#include "mplogic.h" + +/* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */ +#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT) +#define ECL_SIXTY_FOUR_BIT +#define ECL_BITS 64 +#define ECL_MAX_FIELD_SIZE_DIGITS 10 +#else +#define ECL_THIRTY_TWO_BIT +#define ECL_BITS 32 +#define ECL_MAX_FIELD_SIZE_DIGITS 20 +#endif + +/* 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)) + +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); +}; + +/* 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); + /* 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); +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); +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); +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); +/* 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); +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); +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); + +/* Montgomery prime field arithmetic. */ +mp_err ec_GFp_mul_mont(const mp_int *a, const mp_int *b, mp_int *r, + 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); +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); +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); + +/* 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 + * 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); + +/* Optimized field arithmetic */ +mp_err ec_group_set_gfp192(ECGroup *group, ECCurveName); +mp_err ec_group_set_gfp224(ECGroup *group, ECCurveName); +mp_err ec_group_set_gf2m163(ECGroup *group, ECCurveName name); +mp_err ec_group_set_gf2m193(ECGroup *group, ECCurveName name); +mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name); + +/* Optimized floating-point arithmetic */ +#ifdef ECL_USE_FP +mp_err ec_group_set_secp160r1_fp(ECGroup *group); +mp_err ec_group_set_nistp192_fp(ECGroup *group); +mp_err ec_group_set_nistp224_fp(ECGroup *group); +#endif + +#endif /* __ecl_priv_h_ */ diff --git a/security/nss/lib/freebl/ecl/ecl.c b/security/nss/lib/freebl/ecl/ecl.c new file mode 100644 index 000000000000..9d7af0624c02 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl.c @@ -0,0 +1,406 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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 "mpi.h" +#include "mplogic.h" +#include "ecl.h" +#include "ecl-priv.h" +#include "ec2.h" +#include "ecp.h" +#include +#include + +/* Allocate memory for a new ECGroup object. */ +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->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; + 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)); + group->base_point_mul = NULL; + group->points_mul = NULL; + group->extra1 = NULL; + group->extra2 = NULL; + group->extra_free = NULL; + + 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) +{ + mp_err res = MP_OKAY; + ECGroup *group = 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; + + 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) +{ + mp_err res = MP_OKAY; + ECGroup *group = 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; + + CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; +} + +/* 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; + + CLEANUP: + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return group; +} + +/* Helper macros for ecgroup_fromNameAndHex. */ +#define CHECK_GROUP \ + if (group == NULL) { res = MP_UNDEF; goto CLEANUP; } +#define CONS_GF2M \ + group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor); \ + CHECK_GROUP + +/* 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) +{ + 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)); + + /* 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) { + if ((name == ECCurve_SECG_PRIME_160K1) + || (name == ECCurve_SECG_PRIME_160R2)) { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + } else if ((name == ECCurve_SECG_PRIME_160R1)) { +#ifdef ECL_USE_FP + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_secp160r1_fp(group)); +#else + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); +#endif + } else if ((name == ECCurve_SECG_PRIME_192K1)) { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp192(group, name)); + } else if ((name == ECCurve_SECG_PRIME_192R1)) { +#ifdef ECL_USE_FP + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_nistp192_fp(group)); +#else + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp192(group, name)); +#endif + } else if ((name == ECCurve_SECG_PRIME_224K1)) { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp224(group, name)); + } else if ((name == ECCurve_SECG_PRIME_224R1)) { +#ifdef ECL_USE_FP + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_nistp224_fp(group)); +#else + group = + ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP MP_CHECKOK(ec_group_set_gfp224(group, name)); +#endif + } else { + group = + ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, + &order, params->cofactor); + CHECK_GROUP} + /* XXX secp521r1 fails ecp_test with &ec_GFp_pts_mul_jac */ + if (name == ECCurve_SECG_PRIME_521R1) { + group->points_mul = &ec_pts_mul_simul_w2; + } + } else if (params->field == ECField_GF2m) { + switch (bits) { + case 163: + CONS_GF2M MP_CHECKOK(ec_group_set_gf2m163(group, name)); + break; + case 193: + CONS_GF2M MP_CHECKOK(ec_group_set_gf2m193(group, name)); + break; + case 233: + CONS_GF2M MP_CHECKOK(ec_group_set_gf2m233(group, name)); + break; + default: + group = + ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, + &geny, &order, params->cofactor); + CHECK_GROUP break; + } + } + + /* set name, if any */ + if (params->text != NULL) { + group->text = (char *) malloc(sizeof(char) * strlen(params->text)); + if (group->text == NULL) { + res = MP_MEM; + } + strcpy(group->text, params->text); + } + + 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; +} + +#undef CHECK_GROUP +#undef CONS_GFP +#undef CONS_GF2M + +/* Construct ECGroup from hexadecimal representations of parameters. */ +ECGroup * +ECGroup_fromHex(const ECCurveParams * 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; + + 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; + } + + CLEANUP: + EC_FreeCurveParams(params); + if (res != MP_OKAY) { + ECGroup_free(group); + return NULL; + } + return 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; + if (group->text != NULL) + free(group->text); + if (group->extra_free != NULL) + group->extra_free(group); + free(group); +} diff --git a/security/nss/lib/freebl/ecl/ecl.h b/security/nss/lib/freebl/ecl/ecl.h new file mode 100644 index 000000000000..7db9deb0ad5d --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl.h @@ -0,0 +1,82 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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. + * + */ + +/* Although this is not an exported header file, code which uses elliptic + * curve point operations will need to include it. */ + +#ifndef __ecl_h_ +#define __ecl_h_ + +#include "ecl-exp.h" +#include "mpi.h" + +struct ECGroupStr; +typedef struct ECGroupStr ECGroup; + +/* Construct ECGroup from hexadecimal representations of parameters. */ +ECGroup *ECGroup_fromHex(const ECCurveParams * params); + +/* Construct ECGroup from named parameters. */ +ECGroup *ECGroup_fromName(const ECCurveName name); + +/* Free an allocated ECGroup. */ +void ECGroup_free(ECGroup *group); + +/* Construct ECCurveParams from an ECCurveName */ +ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name); + +/* Duplicates an ECCurveParams */ +ECCurveParams *ECCurveParams_dup(const ECCurveParams * params); + +/* Free an allocated ECCurveParams */ +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) + * 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); + +/* 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); + +#endif /* __ecl_h_ */ diff --git a/security/nss/lib/freebl/ecl/ecl_curve.c b/security/nss/lib/freebl/ecl/ecl_curve.c new file mode 100644 index 000000000000..d8368092eb6e --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl_curve.c @@ -0,0 +1,120 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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 "ecl.h" +#include "ecl-curve.h" +#include "ecl-priv.h" +#include +#include + +#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; } + +/* Duplicates an ECCurveParams */ +ECCurveParams * +ECCurveParams_dup(const ECCurveParams * params) +{ + int res = 1; + ECCurveParams *ret = NULL; + + CHECK(ret = (ECCurveParams *) malloc(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; +} + +#undef CHECK + +/* Construct ECCurveParams from an ECCurveName */ +ECCurveParams * +EC_GetNamedCurveParams(const ECCurveName name) +{ + if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name)) { + return NULL; + } else { + return ECCurveParams_dup(ecCurve_map[name]); + } +} + +/* Free the memory allocated (if any) to an ECCurveParams object. */ +void +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); +} diff --git a/security/nss/lib/freebl/ecl/ecl_gf.c b/security/nss/lib/freebl/ecl/ecl_gf.c new file mode 100644 index 000000000000..000f97b86830 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl_gf.c @@ -0,0 +1,337 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung and + * Douglas Stebila , 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 "mpi.h" +#include "mp_gf2m.h" +#include "ecl-priv.h" +#include + +/* Allocate memory for a new GFMethod object. */ +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_CHECKOK(mp_init(&meth->irr)); + meth->extra_free = NULL; + + CLEANUP: + if (res != MP_OKAY) { + GFMethod_free(meth); + return NULL; + } + return meth; +} + +/* Construct a generic GFMethod for arithmetic over prime fields with + * irreducible irr. */ +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; + meth->field_add = &ec_GFp_add; + meth->field_neg = &ec_GFp_neg; + meth->field_sub = &ec_GFp_sub; + 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; +} + +/* 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; + if (meth->extra_free != NULL) + meth->extra_free(meth); + free(meth); +} + +/* Wrapper functions for generic prime field arithmetic. */ + +/* 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) +{ + /* 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) */ + + 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) +{ + 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; +} + +/* 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); +} + +/* Multiplies two field elements. */ +mp_err +ec_GFp_mul(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + 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); +} + +/* 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) +{ + 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. */ + +/* Adds two field elements. */ +mp_err +ec_GF2m_add(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + return mp_badd(a, b, r); +} + +/* Negates a field element. Note that for binary polynomial fields, the + * negation of a field element is the field element itself. */ +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); + } +} + +/* 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); +} + +/* Multiplies two field elements. */ +mp_err +ec_GF2m_mul(const mp_int *a, const mp_int *b, mp_int *r, + const GFMethod *meth) +{ + 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); +} + +/* 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) +{ + 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/security/nss/lib/freebl/ecl/ecl_mult.c b/security/nss/lib/freebl/ecl/ecl_mult.c new file mode 100644 index 000000000000..9609733defa2 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecl_mult.c @@ -0,0 +1,359 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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 "mpi.h" +#include "mplogic.h" +#include "ecl.h" +#include "ecl-priv.h" +#include +#include + +/* 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) +{ + mp_err res = MP_OKAY; + mp_int kt; + + 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); + } + + 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; +} + +/* 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) +{ + 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); + + /* 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_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)); + } + + 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)); + } + + CLEANUP: + mp_clear(&sx); + mp_clear(&sy); + return res; +} + +/* 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 + * algorithm 15 (simultaneous multiple point multiplication) from Brown, + * Hankerson, Lopez, Menezes. Software Implementation of the NIST + * 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) +{ + mp_err res = MP_OKAY; + mp_int precomp[4][4][2]; + mp_digit precomp_arr[ECL_MAX_FIELD_SIZE_DIGITS * 4 * 4 * 2], *t; + const mp_int *a, *b; + int i, j; + int ai, bi, d; + + 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 */ + t = precomp_arr; + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + /* x co-ord */ + MP_SIGN(&precomp[i][j][0]) = MP_ZPOS; + MP_ALLOC(&precomp[i][j][0]) = ECL_MAX_FIELD_SIZE_DIGITS; + MP_USED(&precomp[i][j][0]) = 1; + *t = 0; + MP_DIGITS(&precomp[i][j][0]) = t; + t += ECL_MAX_FIELD_SIZE_DIGITS; + /* y co-ord */ + MP_SIGN(&precomp[i][j][1]) = MP_ZPOS; + MP_ALLOC(&precomp[i][j][1]) = ECL_MAX_FIELD_SIZE_DIGITS; + MP_USED(&precomp[i][j][1]) = 1; + *t = 0; + MP_DIGITS(&precomp[i][j][1]) = t; + t += 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)); + } + + d = (mpl_significant_bits(a) + 1) / 2; + + /* R = inf */ + mp_zero(rx); + mp_zero(ry); + + for (i = d - 1; i >= 0; i--) { + 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)); + } + + CLEANUP: + return res; +} + +/* 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) +{ + mp_err res = MP_OKAY; + mp_int k1t, k2t; + const mp_int *k1p, *k2p; + + MP_DIGITS(&k1t) = 0; + MP_DIGITS(&k2t) = 0; + + 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; + } + + /* if points_mul is defined, then use it */ + if (group->points_mul) { + return group->points_mul(k1p, k2p, px, py, rx, ry, group); + } else { + return ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group); + } + + CLEANUP: + if (k1 != k1p) { + mp_clear(&k1t); + } + if (k2 != k2p) { + mp_clear(&k2t); + } + return res; +} diff --git a/security/nss/lib/freebl/ecl/ecp.h b/security/nss/lib/freebl/ecl/ecp.h new file mode 100644 index 000000000000..801c83c5616c --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp.h @@ -0,0 +1,136 @@ +/* + * 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 , 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. + * + */ + +#ifndef __ecp_h_ +#define __ecp_h_ + +#include "ecl-priv.h" + +/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ +mp_err ec_GFp_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_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); + +/* 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); + +/* 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); + +#ifdef ECL_ENABLE_GFP_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 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); +#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); + +/* 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); + +/* 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); + +/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian + * coordinates. */ +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); + +/* 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); + +#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); +#endif + +/* 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. Implemented using mixed Jacobian-affine + * 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); + +/* 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. 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 + * 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); + +#endif /* __ecp_h_ */ diff --git a/security/nss/lib/freebl/ecl/ecp_192.c b/security/nss/lib/freebl/ecl/ecp_192.c new file mode 100644 index 000000000000..914349e63e89 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_192.c @@ -0,0 +1,228 @@ +/* + * 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 , 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 + +/* 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. */ +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); + + /* s is a statically-allocated mp_int of exactly the size we need */ + mp_int s; + +#ifdef ECL_THIRTY_TWO_BIT + mp_digit sa[6]; + mp_digit a11 = 0, a10, a9 = 0, a8, a7 = 0, a6; + + MP_SIGN(&s) = MP_ZPOS; + MP_ALLOC(&s) = 6; + MP_USED(&s) = 6; + MP_DIGITS(&s) = sa; +#else + mp_digit sa[3]; + mp_digit a5 = 0, a4 = 0, a3 = 0; + + MP_SIGN(&s) = MP_ZPOS; + MP_ALLOC(&s) = 3; + MP_USED(&s) = 3; + MP_DIGITS(&s) = sa; +#endif + + /* reduction not needed if a is not larger than field size */ +#ifdef ECL_THIRTY_TWO_BIT + if (a_used < 6) { +#else + if (a_used < 3) { +#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 > 12) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + /* copy out upper words of a */ + switch (a_used) { + 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); + case 7: + a6 = MP_DIGIT(a, 6); + } + /* set the lower words of r */ + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 7)); + 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) = 6; + /* compute r = s1 + s2 + s3 + s4, where s1 = (a2,a1,a0), s2 = + * (0,a3,a3), s3 = (a4,a4,0), and s4 = (a5,a5,a5), for + * sixty-four-bit words */ + switch (a_used) { + case 12: + case 11: + sa[5] = sa[3] = sa[1] = a11; + sa[4] = sa[2] = sa[0] = a10; + MP_CHECKOK(mp_add(r, &s, r)); + case 10: + case 9: + sa[5] = sa[3] = a9; + sa[4] = sa[2] = a8; + sa[1] = sa[0] = 0; + MP_CHECKOK(mp_add(r, &s, r)); + case 8: + case 7: + sa[5] = sa[4] = 0; + sa[3] = sa[1] = a7; + sa[2] = sa[0] = a6; + MP_CHECKOK(mp_add(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 > 6) { + MP_CHECKOK(mp_mod(a, &meth->irr, r)); + } else { + /* copy out upper words of a */ + switch (a_used) { + case 6: + a5 = MP_DIGIT(a, 5); + case 5: + a4 = MP_DIGIT(a, 4); + case 4: + a3 = MP_DIGIT(a, 3); + } + /* set the lower words of r */ + if (a != r) { + MP_CHECKOK(s_mp_pad(r, 4)); + 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) = 3; + /* compute r = s1 + s2 + s3 + s4, where s1 = (a2,a1,a0), s2 = + * (0,a3,a3), s3 = (a4,a4,0), and s4 = (a5,a5,a5) */ + switch (a_used) { + case 6: + sa[2] = sa[1] = sa[0] = a5; + MP_CHECKOK(mp_add(r, &s, r)); + case 5: + sa[2] = sa[1] = a4; + sa[0] = 0; + MP_CHECKOK(mp_add(r, &s, r)); + case 4: + sa[2] = 0; + sa[1] = sa[0] = a3; + MP_CHECKOK(mp_add(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 p192. Store the + * result in r. r could be a. Uses optimized modular reduction for p192. + */ +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. */ +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; +} + +/* 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; + } + return MP_OKAY; +} 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 000000000000..6e6e81ce4481 --- /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 , 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 + +/* 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; +} diff --git a/security/nss/lib/freebl/ecl/ecp_aff.c b/security/nss/lib/freebl/ecl/ecp_aff.c new file mode 100644 index 000000000000..0bda87657e19 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_aff.c @@ -0,0 +1,284 @@ +/* + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , Sun Microsystems Laboratories. + * + * Bodo Moeller , + * Nils Larsch , and + * Lenka Fibikova , the OpenSSL Project. + * + * 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 "mplogic.h" +#include + +/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */ +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; + } + +} + +/* 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; +} + +/* 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) +{ + 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)); + + 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 + * 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_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 = -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 + * affine coordinates. Assumes input is already field-encoded using + * 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) +{ + 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 + * 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_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_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)); + + CLEANUP: + mp_clear(&k); + mp_clear(&k3); + mp_clear(&qx); + mp_clear(&qy); + mp_clear(&sx); + mp_clear(&sy); + return res; +} +#endif diff --git a/security/nss/lib/freebl/ecl/ecp_fp.c b/security/nss/lib/freebl/ecl/ecp_fp.c new file mode 100644 index 000000000000..1b9c6ed67c72 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp.c @@ -0,0 +1,566 @@ +/* + * 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 using floating point operations. + * + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , 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_fp.h" +#include "ecl-priv.h" +#include + +/* 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/security/nss/lib/freebl/ecl/ecp_fp.h b/security/nss/lib/freebl/ecl/ecp_fp.h new file mode 100644 index 000000000000..6df7b9e69c9c --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp.h @@ -0,0 +1,405 @@ +/* + * 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 using floating point operations. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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. + * + */ + +#ifndef __ecp_fp_h_ +#define __ecp_fp_h_ + +#include "mpi.h" +#include "ecl.h" +#include "ecp.h" + +#include +#include "mpi-priv.h" + +#ifdef ECL_DEBUG +#include +#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/security/nss/lib/freebl/ecl/ecp_fp160.c b/security/nss/lib/freebl/ecl/ecp_fp160.c new file mode 100644 index 000000000000..57399d494f91 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp160.c @@ -0,0 +1,178 @@ +/* + * 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 using floating point operations. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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_fp.h" +#include + +#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/security/nss/lib/freebl/ecl/ecp_fp192.c b/security/nss/lib/freebl/ecl/ecp_fp192.c new file mode 100644 index 000000000000..2e143aa49539 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp192.c @@ -0,0 +1,176 @@ +/* + * 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 using floating point operations. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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_fp.h" +#include + +#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/security/nss/lib/freebl/ecl/ecp_fp224.c b/security/nss/lib/freebl/ecl/ecp_fp224.c new file mode 100644 index 000000000000..f32e8d71798b --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fp224.c @@ -0,0 +1,189 @@ +/* + * 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 using floating point operations. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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_fp.h" +#include + +#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/security/nss/lib/freebl/ecl/ecp_fpinc.c b/security/nss/lib/freebl/ecl/ecp_fpinc.c new file mode 100644 index 000000000000..e05e478ef0c0 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_fpinc.c @@ -0,0 +1,854 @@ +/* + * 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 using floating point operations. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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. + * + */ + +/* 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;jaIsM3) { + /* 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/security/nss/lib/freebl/ecl/ecp_jac.c b/security/nss/lib/freebl/ecl/ecp_jac.c new file mode 100644 index 000000000000..8eea8c904f91 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_jac.c @@ -0,0 +1,553 @@ +/* + * 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): + * Sheueling Chang-Shantz , + * Stephen Fung , and + * Douglas Stebila , Sun Microsystems Laboratories. + * + * Bodo Moeller , + * Nils Larsch , and + * Lenka Fibikova , the OpenSSL Project. + * + * 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 "mplogic.h" +#include +#ifdef ECL_DEBUG +#include +#endif + +/* Converts a point P(px, py) from affine coordinates to Jacobian + * 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_GFp_pt_aff2jac(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; + + 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 + * 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_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_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 + * coordinates. */ +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); +} + +/* Sets P(px, py, pz) to be the point at infinity. Uses Jacobian + * coordinates. */ +mp_err +ec_GFp_pt_set_inf_jac(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 Jacobian-affine coordinates. Assumes input is already + * field-encoded using field_enc, and returns output that is still + * field-encoded. Uses equation (2) from Brown, Hankerson, Lopez, and + * Menezes. Software Implementation of the NIST Elliptic Curves Over Prime + * 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) +{ + 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)); + + /* 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 + * Jacobian coordinates. + * + * 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 + * 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_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)); + + if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) { + 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; +} + +/* by default, this routine is unused and thus doesn't need to be compiled */ +#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. 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 + * 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_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 + + * 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 + * assumed to be NOT field-encoded. Uses algorithm 15 (simultaneous + * multiple point multiplication) from Brown, Hankerson, Lopez, Menezes. + * 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) +{ + mp_err res = MP_OKAY; + mp_int precomp[4][4][2]; + mp_int rz; + const mp_int *a, *b; + 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 - 1; i >= 0; i--) { + 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/security/nss/lib/freebl/ecl/ecp_jm.c b/security/nss/lib/freebl/ecl/ecp_jm.c new file mode 100644 index 000000000000..2174650d1f10 --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_jm.c @@ -0,0 +1,320 @@ +/* + * 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): + * Stephen Fung , 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 "ecl-priv.h" +#include "mplogic.h" +#include + +/* 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 + * output that is still field-encoded. + * + */ +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, 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)); + + /* 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; + } + + /* 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, rz, group->meth)); + MP_CHECKOK(group->meth->field_add(rz, rz, 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)); + + /* 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)); + + /* ry = M * (S - rx) - t1 */ + MP_CHECKOK(group->meth->field_sub(&S, rx, ry, group->meth)); + MP_CHECKOK(group->meth->field_mul(ry, &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)); + + CLEANUP: + mp_clear(&t0); + mp_clear(&t1); + mp_clear(&M); + mp_clear(&S); + return res; +} + +/* 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 Modified_Jacobian-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_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, 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)); + 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: + mp_clear(&A); + mp_clear(&B); + mp_clear(&C); + mp_clear(&D); + mp_clear(&C2); + mp_clear(&C3); + 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. 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 + * 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_err res = MP_OKAY; + mp_int precomp[16][2], rz, tpx, tpy; + mp_int raz4; + 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; + } + + 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])); + } + + /* 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); + 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, 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, group); + } + } + + /* convert result S to affine coordinates */ + MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group)); + + CLEANUP: + 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/security/nss/lib/freebl/ecl/ecp_mont.c b/security/nss/lib/freebl/ecl/ecp_mont.c new file mode 100644 index 000000000000..a251af1fc3cc --- /dev/null +++ b/security/nss/lib/freebl/ecl/ecp_mont.c @@ -0,0 +1,190 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Douglas Stebila , 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. + * + */ + +/* Uses Montgomery reduction for field arithmetic. See mpi/mpmontg.c for + * code implementation. */ + +#include "mpi.h" +#include "mplogic.h" +#include "mpi-priv.h" +#include "ecl-priv.h" +#include "ecp.h" +#include +#include + +/* Construct a generic GFMethod for arithmetic over prime fields with + * irreducible irr. */ +GFMethod * +GFMethod_consGFp_mont(const mp_int *irr) +{ + mp_err res = MP_OKAY; + int i; + 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; + i = mpl_significant_bits(&meth->irr); + i += MP_DIGIT_BIT - 1; + mmm->b = i - i % MP_DIGIT_BIT; + 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. */ + +/* 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) +{ + 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)); +#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); + } +#endif + 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); +} + +/* 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) +{ + 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 + * mpi/mpmontg.c */ +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(mpl_lsh(a, r, mmm->b)); + 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; +} + +/* Free the memory allocated to the extra fields of Montgomery GFMethod + * object. */ +void +ec_GFp_extra_free_mont(GFMethod *meth) +{ + if (meth->extra1 != NULL) { + free(meth->extra1); + meth->extra1 = NULL; + } +} diff --git a/security/nss/lib/freebl/ecl/tests/ec2_test.c b/security/nss/lib/freebl/ecl/tests/ec2_test.c new file mode 100644 index 000000000000..4bb6bc6eeaa8 --- /dev/null +++ b/security/nss/lib/freebl/ecl/tests/ec2_test.c @@ -0,0 +1,459 @@ +/* + * 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 binary polynomial + * 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 , 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 "mpi.h" +#include "mplogic.h" +#include "mpprime.h" +#include "mp_gf2m.h" +#include "ecl.h" +#include "ecl-curve.h" +#include "ec2.h" +#include +#include +#include + +#include +#include +#include + +/* 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; + } + + 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("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); + + 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/security/nss/lib/freebl/ecl/tests/ec_naft.c b/security/nss/lib/freebl/ecl/tests/ec_naft.c new file mode 100644 index 000000000000..d400475e4a6f --- /dev/null +++ b/security/nss/lib/freebl/ecl/tests/ec_naft.c @@ -0,0 +1,149 @@ +/* + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the elliptic curve math library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung , 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 "mpi.h" +#include "mplogic.h" +#include "ecl.h" +#include "ecp.h" +#include "ecl-priv.h" + +#include +#include +#include +#include +#include + +/* Returns 2^e as an integer. This is meant to be used for small powers of + * two. */ +int ec_twoTo(int e); + +/* Number of bits of scalar to test */ +#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. + * 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; +} diff --git a/security/nss/lib/freebl/ecl/tests/ecp_fpt.c b/security/nss/lib/freebl/ecl/tests/ecp_fpt.c new file mode 100644 index 000000000000..4a71aa2c8583 --- /dev/null +++ b/security/nss/lib/freebl/ecl/tests/ecp_fpt.c @@ -0,0 +1,1122 @@ +/* + * 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 using floating point operations. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Stephen Fung and + * Douglas Stebila , 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_fp.h" +#include "mpprime.h" + +#include +#include +#include +#include + +/* 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/security/nss/lib/freebl/ecl/tests/ecp_test.c b/security/nss/lib/freebl/ecl/tests/ecp_test.c new file mode 100644 index 000000000000..41182793734e --- /dev/null +++ b/security/nss/lib/freebl/ecl/tests/ecp_test.c @@ -0,0 +1,421 @@ +/* + * 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 , 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 "mpi.h" +#include "mplogic.h" +#include "mpprime.h" +#include "ecl.h" +#include "ecl-curve.h" +#include "ecp.h" +#include +#include +#include + +#include +#include +#include + +/* 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_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"); \ + } + +/* 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) +{ + + 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_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; + } +#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; + } +#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, &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; + } +#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; + } +#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, &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; + } + + 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); +#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 prime 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_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1); + + /* specific arithmetic tests */ + 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); + + 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/security/nss/lib/freebl/loader.h b/security/nss/lib/freebl/loader.h index b55d845c8d8a..1a3544cc30ce 100644 --- a/security/nss/lib/freebl/loader.h +++ b/security/nss/lib/freebl/loader.h @@ -36,7 +36,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: loader.h,v 1.9 2003/02/27 01:31:14 nelsonb%netscape.com Exp $ + * $Id: loader.h,v 1.10 2003/10/17 13:45:33 ian.mcgreer%sun.com Exp $ */ #ifndef _LOADER_H_ @@ -44,7 +44,7 @@ #include "blapi.h" -#define FREEBL_VERSION 0x0306 +#define FREEBL_VERSION 0x0307 struct FREEBLVectorStr { @@ -371,6 +371,12 @@ struct FREEBLVectorStr { /* Version 3.006 came to here */ + /* no modification to FREEBLVectorStr itself + * but ECParamStr was modified + */ + + /* Version 3.007 came to here */ + }; typedef struct FREEBLVectorStr FREEBLVector; diff --git a/security/nss/lib/freebl/manifest.mn b/security/nss/lib/freebl/manifest.mn index f31c0f8c65f8..00715a2eebb9 100644 --- a/security/nss/lib/freebl/manifest.mn +++ b/security/nss/lib/freebl/manifest.mn @@ -20,7 +20,9 @@ # Sun Microsystems, Inc. All Rights Reserved. # # Contributor(s): -# Dr Vipul Gupta , Sun Microsystems Laboratories +# Dr Vipul Gupta and +# Douglas Stebila , Sun Microsystems +# Laboratories # # Alternatively, the contents of this file may be used under the # terms of the GNU General Public License Version 2 or later (the @@ -59,6 +61,8 @@ REQUIRES = EXPORTS = \ blapit.h \ shsign.h \ + ecl-exp.h \ + ecl-curve.h \ $(NULL) PRIVATE_EXPORTS = \ @@ -66,10 +70,22 @@ PRIVATE_EXPORTS = \ secmpi.h \ secrng.h \ ec.h \ + ecl.h \ $(NULL) MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c +ECL_HDRS = ecl-exp.h ecl.h ec2.h ecp.h ecl-priv.h +ifdef NSS_ENABLE_ECC +ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \ + ec2_aff.c ec2_mont.c ec2_proj.c \ + ec2_163.c ec2_193.c ec2_233.c \ + ecp_aff.c ecp_jac.c ecp_mont.c \ + ecp_192.c ecp_224.c \ + ec_naf.c ecp_jm.c +else +ECL_SRCS = $(NULL) +endif CSRCS = \ ldvector.c \ @@ -88,13 +104,12 @@ CSRCS = \ aeskeywrap.c \ dh.c \ ec.c \ - GFp_ecl.c \ - GF2m_ecl.c \ pqg.c \ dsa.c \ rsa.c \ shvfy.c \ $(MPI_SRCS) \ + $(ECL_SRCS) \ $(NULL) ALL_CSRCS := $(CSRCS) @@ -104,8 +119,6 @@ ALL_HDRS = \ blapit.h \ des.h \ ec.h \ - GFp_ecl.h \ - GF2m_ecl.h \ loader.h \ rijndael.h \ secmpi.h \ @@ -115,6 +128,10 @@ ALL_HDRS = \ vis_proto.h \ $(NULL) +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + ifdef AES_GEN_TBL DEFINES += -DRIJNDAEL_GENERATE_TABLES else diff --git a/security/nss/lib/freebl/mpi/Makefile b/security/nss/lib/freebl/mpi/Makefile index 7962fd7b4c70..25c78fe92da0 100644 --- a/security/nss/lib/freebl/mpi/Makefile +++ b/security/nss/lib/freebl/mpi/Makefile @@ -20,9 +20,13 @@ ## Portions created by Michael J. Fromberger are ## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved. ## +## Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +## Sun Microsystems, Inc. All Rights Reserved. +## ## Contributor(s): ## Netscape Communications Corporation ## Richard C. Swift (swift@netscape.com) +## Douglas Stebila , Sun Microsystems Laboratories ## ## Alternatively, the contents of this file may be used under the ## terms of the GNU General Public License Version 2 or later (the @@ -37,7 +41,7 @@ ## GPL. ## ## -## $Id: Makefile,v 1.19 2003/03/29 00:18:22 nelsonb%netscape.com Exp $ +## $Id: Makefile,v 1.20 2003/10/17 13:45:36 ian.mcgreer%sun.com Exp $ ## ## Define CC to be the C compiler you wish to use. The GNU cc @@ -53,186 +57,9 @@ #PERL=/usr/bin/perl PERL=perl -## -## Define CFLAGS to contain any local options your compiler -## setup requires. -## -## Conditional compilation options are no longer here; see -## the file 'mpi-config.h' instead. -## -MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC -CFLAGS= -O $(MPICMN) -#CFLAGS=-ansi -fullwarn -woff 1521 -O3 $(MPICMN) -#CFLAGS=-ansi -pedantic -Wall -O3 $(MPICMN) -#CFLAGS=-ansi -pedantic -Wall -g -O2 -DMP_DEBUG=1 $(MPICMN) +include target.mk -ifeq ($(TARGET),mipsIRIX) -#IRIX -#MPICMN += -DMP_MONT_USE_MP_MUL -MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -MPICMN += -DMP_USE_UINT_DIGIT -#MPICMN += -DMP_NO_MP_WORD -AS_OBJS = mpi_mips.o -#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -exceptions -ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -#CFLAGS=-ansi -n32 -O3 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) -CFLAGS=-ansi -n32 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) -#CFLAGS=-ansi -n32 -g -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) -#CFLAGS=-ansi -64 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE -DMP_NO_MP_WORD \ - $(MPICMN) -endif - -ifeq ($(TARGET),alphaOSF1) -#Alpha/OSF1 -MPICMN += -DMP_ASSEMBLY_MULTIPLY -AS_OBJS+= mpvalpha.o -#CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT $(MPICMN) -CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT \ - -DMP_NO_MP_WORD $(MPICMN) -endif - -ifeq ($(TARGET),v9SOLARIS) -#Solaris 64 -SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a -KPIC -mt -#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v9a -KPIC -mt -SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v9a -KPIC -mt -AS_OBJS += montmulfv9.o -AS_OBJS += mpi_sparc.o mpv_sparcv9.o -MPICMN += -DMP_USE_UINT_DIGIT -#MPICMN += -DMP_NO_MP_WORD -MPICMN += -DMP_ASSEMBLY_MULTIPLY -MPICMN += -DMP_USING_MONT_MULF -CFLAGS= -O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ - -DSOLARIS2_8 -D_SVID_GETTOD -xarch=v9 -DXP_UNIX $(MPICMN) -#CFLAGS= -g -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ - -DSOLARIS2_8 -D_SVID_GETTOD -xarch=v9 -DXP_UNIX $(MPICMN) -endif - -ifeq ($(TARGET),v8plusSOLARIS) -#Solaris 32 -SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8plusa -KPIC -mt -SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt -AS_OBJS += montmulfv8.o -AS_OBJS += mpi_sparc.o mpv_sparcv8.o -#AS_OBJS = montmulf.o -MPICMN += -DMP_ASSEMBLY_MULTIPLY -MPICMN += -DMP_USING_MONT_MULF -MPICMN += -DMP_USE_UINT_DIGIT -MPICMN += -DMP_NO_MP_WORD -CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ - -DSOLARIS2_6 -D_SVID_GETTOD -xarch=v8plus -DXP_UNIX $(MPICMN) -endif - -ifeq ($(TARGET),v8SOLARIS) -#Solaris 32 -#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8 -KPIC -mt -#SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt -#AS_OBJS = montmulfv8.o mpi_sparc.o mpv_sparcv8.o -#AS_OBJS = montmulf.o -#MPICMN += -DMP_USING_MONT_MULF -#MPICMN += -DMP_ASSEMBLY_MULTIPLY -MPICMN += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT -MPICMN += -DMP_NO_MP_WORD -CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ - -DSOLARIS2_6 -D_SVID_GETTOD -xarch=v8 -DXP_UNIX $(MPICMN) -endif - -ifeq ($(TARGET),ia64HPUX) -#HPUX 32 on ia64 -- 64 bit digits SCREAM. -# This one is for DD32 which is the 32-bit ABI with 64-bit registers. -CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) -#CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) -#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) -endif - -ifeq ($(TARGET),ia64HPUX64) -#HPUX 32 on ia64 -# This one is for DD64 which is the 64-bit ABI -CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) -#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) -endif - -ifeq ($(TARGET),PA2.0WHPUX) -#HPUX64 (HP PA 2.0 Wide) using MAXPY and 64-bit digits -MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -AS_OBJS = mpi_hp.o hpma512.o hppa20.o -CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +O3 +DChpux -DHPUX11 -DXP_UNIX \ - $(MPICMN) -#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ - $(MPICMN) -AS = $(CC) $(CFLAGS) -c -endif - -ifeq ($(TARGET),PA2.0NHPUX) -#HPUX32 (HP PA 2.0 Narrow) hybrid model, using 32-bit digits -# This one is for DA2.0 (N) which is the 32-bit ABI with 64-bit registers. -MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -AS_OBJS = mpi_hp.o hpma512.o hppa20.o -CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ - -Wl,+k $(MPICMN) -#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ - -Wl,+k $(MPICMN) -AS = $(CC) $(CFLAGS) -c -endif - -ifeq ($(TARGET),PA1.1HPUX) -#HPUX32 (HP PA 1.1) Pure 32 bit -MPICMN += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD -#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY -CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ - -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN) -##CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ -# -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN) -endif - -ifeq ($(TARGET),32AIX) -# -CC = xlC_r -MPICMN += -DMP_USE_UINT_DIGIT -MPICMN += -DMP_NO_DIV_WORD -#MPICMN += -DMP_NO_MUL_WORD -MPICMN += -DMP_NO_ADD_WORD -MPICMN += -DMP_NO_SUB_WORD -#MPICMN += -DMP_NO_MP_WORD -#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY -CFLAGS = -O -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) -#CFLAGS = -g -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) -#CFLAGS += -pg -endif - -ifeq ($(TARGET),64AIX) -# -CC = xlC_r -MPICMN += -DMP_USE_UINT_DIGIT -CFLAGS = -O -O2 -DAIX -DSYSV -qarch=com -DAIX_64BIT -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) -OBJECT_MODE=64 -export OBJECT_MODE -endif - -ifeq ($(TARGET),x86LINUX) -#Linux -AS_OBJS = mpi_x86.o -MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D -MPICMN += -DMP_MONT_USE_MP_MUL -CFLAGS= -O2 -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ - -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ - -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) -#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ - -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ - -DXP_UNIX -DDEBUG -UNDEBUG -D_REENTRANT $(MPICMN) -#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ - -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ - -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) -endif +CFLAGS+= $(XCFLAGS) ## ## Define LIBS to include any libraries you need to link against. @@ -275,7 +102,7 @@ SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c tests/ ## These are the header files that go into the distribution file HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h mp_gf2m.h \ - utils/bbs_rand.h tests/mpi.h tests/mpprime.h + mp_gf2m-priv.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h ## These are the documentation files that go into the distribution file DOCS=README doc utils/README utils/PRIMES @@ -320,7 +147,7 @@ mpi.o: mpi.c logtab.h $(LIBHDRS) mplogic.o: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS) -mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h $(LIBHDRS) +mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h mp_gf2m-priv.h $(LIBHDRS) mpmontg.o: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS) diff --git a/security/nss/lib/freebl/mpi/mp_gf2m-priv.h b/security/nss/lib/freebl/mpi/mp_gf2m-priv.h new file mode 100644 index 000000000000..e2236299fc36 --- /dev/null +++ b/security/nss/lib/freebl/mpi/mp_gf2m-priv.h @@ -0,0 +1,101 @@ +/* + * 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 Multi-precision Binary Polynomial Arithmetic + * Library. + * + * The Initial Developer of the Original Code is Sun Microsystems, Inc. + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * + * Contributor(s): + * Sheueling Chang Shantz and + * Douglas Stebila of Sun 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. + * + */ + +#ifndef _MP_GF2M_PRIV_H_ +#define _MP_GF2M_PRIV_H_ + +#include "mpi-priv.h" + +extern const mp_digit mp_gf2m_sqr_tb[16]; + +#if defined(MP_USE_UINT_DIGIT) +#define MP_DIGIT_BITS 32 +#else +#define MP_DIGIT_BITS 64 +#endif + +/* Platform-specific macros for fast binary polynomial squaring. */ +#if MP_DIGIT_BITS == 32 +#define gf2m_SQR1(w) \ + mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] +#define gf2m_SQR0(w) \ + mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF] +#else +#define gf2m_SQR1(w) \ + mp_gf2m_sqr_tb[(w) >> 60 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 56 & 0xF] << 48 | \ + mp_gf2m_sqr_tb[(w) >> 52 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 48 & 0xF] << 32 | \ + mp_gf2m_sqr_tb[(w) >> 44 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 40 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 36 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) >> 32 & 0xF] +#define gf2m_SQR0(w) \ + mp_gf2m_sqr_tb[(w) >> 28 & 0xF] << 56 | mp_gf2m_sqr_tb[(w) >> 24 & 0xF] << 48 | \ + mp_gf2m_sqr_tb[(w) >> 20 & 0xF] << 40 | mp_gf2m_sqr_tb[(w) >> 16 & 0xF] << 32 | \ + mp_gf2m_sqr_tb[(w) >> 12 & 0xF] << 24 | mp_gf2m_sqr_tb[(w) >> 8 & 0xF] << 16 | \ + mp_gf2m_sqr_tb[(w) >> 4 & 0xF] << 8 | mp_gf2m_sqr_tb[(w) & 0xF] +#endif + +/* Multiply two binary polynomials mp_digits a, b. + * Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1. + * Output in two mp_digits rh, rl. + */ +void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b); + +/* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0) + * result is a binary polynomial in 4 mp_digits r[4]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1, + const mp_digit b0); + +/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0) + * result is a binary polynomial in 6 mp_digits r[6]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0, + const mp_digit b2, const mp_digit b1, const mp_digit b0); + +/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0) + * result is a binary polynomial in 8 mp_digits r[8]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1, + const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1, + const mp_digit b0); + +#endif /* _MP_GF2M_PRIV_H_ */ diff --git a/security/nss/lib/freebl/mpi/mp_gf2m.c b/security/nss/lib/freebl/mpi/mp_gf2m.c index 93d419611bfb..990b2649c409 100644 --- a/security/nss/lib/freebl/mpi/mp_gf2m.c +++ b/security/nss/lib/freebl/mpi/mp_gf2m.c @@ -37,32 +37,22 @@ */ #include "mp_gf2m.h" +#include "mp_gf2m-priv.h" #include "mplogic.h" #include "mpi-priv.h" -static const mp_digit SQR_tb[16] = +const mp_digit mp_gf2m_sqr_tb[16] = { 0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85 }; -#if defined(MP_USE_UINT_DIGIT) -#define MP_DIGIT_BITS 32 - -/* Platform-specific macros for fast binary polynomial squaring. */ - -#define gf2m_SQR1(w) \ - SQR_tb[(w) >> 28 & 0xF] << 24 | SQR_tb[(w) >> 24 & 0xF] << 16 | \ - SQR_tb[(w) >> 20 & 0xF] << 8 | SQR_tb[(w) >> 16 & 0xF] -#define gf2m_SQR0(w) \ - SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >> 8 & 0xF] << 16 | \ - SQR_tb[(w) >> 4 & 0xF] << 8 | SQR_tb[(w) & 0xF] - /* Multiply two binary polynomials mp_digits a, b. * Result is a polynomial with degree < 2 * MP_DIGIT_BITS - 1. * Output in two mp_digits rh, rl. */ -static void +#if MP_DIGIT_BITS == 32 +void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b) { register mp_digit h, l, s; @@ -93,26 +83,8 @@ s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b) *rh = h; *rl = l; } -#endif - -#if defined(MP_USE_LONG_DIGIT) || defined(MP_USE_LONG_LONG_DIGIT) -#define MP_DIGIT_BITS 64 -#define MP_TOP_BIT - -/* Platform-specific fast binary polynomial squaring. */ -#define gf2m_SQR1(w) \ - SQR_tb[(w) >> 60 & 0xF] << 56 | SQR_tb[(w) >> 56 & 0xF] << 48 | \ - SQR_tb[(w) >> 52 & 0xF] << 40 | SQR_tb[(w) >> 48 & 0xF] << 32 | \ - SQR_tb[(w) >> 44 & 0xF] << 24 | SQR_tb[(w) >> 40 & 0xF] << 16 | \ - SQR_tb[(w) >> 36 & 0xF] << 8 | SQR_tb[(w) >> 32 & 0xF] -#define gf2m_SQR0(w) \ - SQR_tb[(w) >> 28 & 0xF] << 56 | SQR_tb[(w) >> 24 & 0xF] << 48 | \ - SQR_tb[(w) >> 20 & 0xF] << 40 | SQR_tb[(w) >> 16 & 0xF] << 32 | \ - SQR_tb[(w) >> 12 & 0xF] << 24 | SQR_tb[(w) >> 8 & 0xF] << 16 | \ - SQR_tb[(w) >> 4 & 0xF] << 8 | SQR_tb[(w) & 0xF] - -/* Multiply two binary polynomials mp_digits a, b, output in rh, rl */ -static void +#else +void s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b) { register mp_digit h, l, s; @@ -153,12 +125,11 @@ s_bmul_1x1(mp_digit *rh, mp_digit *rl, const mp_digit a, const mp_digit b) } #endif -#if 0 /* to be used later */ /* Compute xor-multiply of two binary polynomials (a1, a0) x (b1, b0) * result is a binary polynomial in 4 mp_digits r[4]. * The caller MUST ensure that r has the right amount of space allocated. */ -static void +void s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1, const mp_digit b0) { @@ -169,9 +140,58 @@ s_bmul_2x2(mp_digit *r, const mp_digit a1, const mp_digit a0, const mp_digit b1, s_bmul_1x1(&m1, &m0, a0 ^ a1, b0 ^ b1); /* Correction on m1 ^= l1 ^ h1; m0 ^= l0 ^ h0; */ r[2] ^= m1 ^ r[1] ^ r[3]; /* h0 ^= m1 ^ l1 ^ h1; */ - r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */ + r[1] = r[3] ^ r[2] ^ r[0] ^ m1 ^ m0; /* l1 ^= l0 ^ h0 ^ m0; */ +} + +/* Compute xor-multiply of two binary polynomials (a2, a1, a0) x (b2, b1, b0) + * result is a binary polynomial in 6 mp_digits r[6]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void +s_bmul_3x3(mp_digit *r, const mp_digit a2, const mp_digit a1, const mp_digit a0, + const mp_digit b2, const mp_digit b1, const mp_digit b0) +{ + mp_digit zm[4]; + + s_bmul_1x1(r+5, r+4, a2, b2); /* fill top 2 words */ + s_bmul_2x2(zm, a1, a2^a0, b1, b2^b0); /* fill middle 4 words */ + s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */ + + zm[3] ^= r[3]; + zm[2] ^= r[2]; + zm[1] ^= r[1] ^ r[5]; + zm[0] ^= r[0] ^ r[4]; + + r[5] ^= zm[3]; + r[4] ^= zm[2]; + r[3] ^= zm[1]; + r[2] ^= zm[0]; +} + +/* Compute xor-multiply of two binary polynomials (a3, a2, a1, a0) x (b3, b2, b1, b0) + * result is a binary polynomial in 8 mp_digits r[8]. + * The caller MUST ensure that r has the right amount of space allocated. + */ +void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1, + const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1, + const mp_digit b0) +{ + mp_digit zm[4]; + + s_bmul_2x2(r+4, a3, a2, b3, b2); /* fill top 4 words */ + s_bmul_2x2(zm, a3^a1, a2^a0, b3^b1, b2^b0); /* fill middle 4 words */ + s_bmul_2x2(r, a1, a0, b1, b0); /* fill bottom 4 words */ + + zm[3] ^= r[3] ^ r[7]; + zm[2] ^= r[2] ^ r[6]; + zm[1] ^= r[1] ^ r[5]; + zm[0] ^= r[0] ^ r[4]; + + r[5] ^= zm[3]; + r[4] ^= zm[2]; + r[3] ^= zm[1]; + r[2] ^= zm[0]; } -#endif /* 0 */ /* Compute addition of two binary polynomials a and b, * store result in c; c could be a or b, a and b could be equal; @@ -263,6 +283,8 @@ mp_bmul(const mp_int *a, const mp_int *b, mp_int *c) mp_size ib, a_used, b_used; mp_err res = MP_OKAY; + MP_DIGITS(&tmp) = 0; + ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG); if (a == c) { @@ -273,7 +295,7 @@ mp_bmul(const mp_int *a, const mp_int *b, mp_int *c) } else if (b == c) { MP_CHECKOK( mp_init_copy(&tmp, b) ); b = &tmp; - } else MP_DIGITS(&tmp) = 0; + } if (MP_USED(a) < MP_USED(b)) { const mp_int *xch = b; /* switch a and b if b longer */ @@ -290,6 +312,7 @@ mp_bmul(const mp_int *a, const mp_int *b, mp_int *c) /* Outer loop: Digits of b */ a_used = MP_USED(a); b_used = MP_USED(b); + MP_USED(c) = a_used + b_used; for (ib = 1; ib < b_used; ib++) { b_i = *pb++; @@ -317,7 +340,7 @@ CLEANUP: * f(t) = t^p[0] + t^p[1] + ... + t^p[k] * where m = p[0] > p[1] > ... > p[k] = 0. */ -int +mp_err mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r) { int j, k; @@ -423,11 +446,12 @@ mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r) mp_err res; ARGCHK(a != NULL && r != NULL, MP_BADARG); + MP_DIGITS(&tmp) = 0; if (a == r) { MP_CHECKOK( mp_init_copy(&tmp, a) ); a = &tmp; - } else MP_DIGITS(&tmp) = 0; + } MP_USED(r) = 1; MP_DIGIT(r, 0) = 0; MP_CHECKOK( s_mp_pad(r, 2*USED(a)) ); @@ -435,6 +459,7 @@ mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r) pa = MP_DIGITS(a); pr = MP_DIGITS(r); a_used = MP_USED(a); + MP_USED(r) = 2 * a_used; for (ia = 0; ia < a_used; ia++) { a_i = *pa++; @@ -465,6 +490,10 @@ mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp, mp_int *a, *b, *u, *v; mp_err res = MP_OKAY; + MP_DIGITS(&aa) = 0; + MP_DIGITS(&bb) = 0; + MP_DIGITS(&uu) = 0; + MP_CHECKOK( mp_init_copy(&aa, x) ); MP_CHECKOK( mp_init_copy(&uu, y) ); MP_CHECKOK( mp_init_copy(&bb, pp) ); @@ -481,7 +510,7 @@ mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp, if (mp_isodd(u)) { MP_CHECKOK( mp_badd(u, pp, u) ); } - s_mp_div_2(u); + s_mp_div2(u); } do { @@ -541,9 +570,9 @@ mp_bpoly2arr(const mp_int *a, unsigned int p[], int max) if (MP_DIGITS(a)[i] & mask) { if (k < max) p[k] = MP_DIGIT_BIT * i + j; k++; - } + } mask >>= 1; - } + } } return k; @@ -566,5 +595,5 @@ mp_barr2poly(const unsigned int p[], mp_int *a) MP_CHECKOK( mpl_set_bit(a, 0, 1) ); CLEANUP: - return MP_OKAY; + return res; } diff --git a/security/nss/lib/freebl/mpi/mpi-priv.h b/security/nss/lib/freebl/mpi/mpi-priv.h index b644da724b19..cbe7684bc974 100644 --- a/security/nss/lib/freebl/mpi/mpi-priv.h +++ b/security/nss/lib/freebl/mpi/mpi-priv.h @@ -38,7 +38,7 @@ * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the GPL. * - * $Id: mpi-priv.h,v 1.14 2001/10/17 20:35:34 jpierre%netscape.com Exp $ + * $Id: mpi-priv.h,v 1.15 2003/10/17 13:45:36 ian.mcgreer%sun.com Exp $ */ #ifndef _MPI_PRIV_H_ #define _MPI_PRIV_H_ 1 @@ -253,6 +253,16 @@ mp_err MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, #define s_mp_mul_d_add_offset(a, b, c, off) \ (s_mpv_mul_d_add_prop(MP_DIGITS(a), MP_USED(a), b, MP_DIGITS(c) + off), MP_OKAY) +typedef struct { + mp_int N; /* modulus N */ + mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */ + mp_size b; /* R == 2 ** b, also b = # significant bits in N */ +} mp_mont_modulus; + +mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, + mp_mont_modulus *mmm); +mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm); + /* }}} */ #endif diff --git a/security/nss/lib/freebl/mpi/mpi.c b/security/nss/lib/freebl/mpi/mpi.c index 4b0634c0ad40..e0040b48693f 100644 --- a/security/nss/lib/freebl/mpi/mpi.c +++ b/security/nss/lib/freebl/mpi/mpi.c @@ -21,8 +21,12 @@ * Copyright (C) 1998, 1999, 2000 Michael J. Fromberger. * All Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): * Netscape Communications Corporation + * Douglas Stebila of Sun Laboratories. * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -35,7 +39,7 @@ * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the GPL. * - * $Id: mpi.c,v 1.39 2002/09/07 02:59:04 jpierre%netscape.com Exp $ + * $Id: mpi.c,v 1.40 2003/10/17 13:45:36 ian.mcgreer%sun.com Exp $ */ #include "mpi-priv.h" @@ -2768,7 +2772,7 @@ mp_err s_mp_pad(mp_int *mp, mp_size min) if ((res = s_mp_grow(mp, min)) != MP_OKAY) return res; } else { -/* s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp)); */ + s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp)); } /* Increase precision; should already be 0-filled */ diff --git a/security/nss/lib/freebl/mpi/mpmontg.c b/security/nss/lib/freebl/mpi/mpmontg.c index 83677ceded19..d88478796026 100644 --- a/security/nss/lib/freebl/mpi/mpmontg.c +++ b/security/nss/lib/freebl/mpi/mpmontg.c @@ -35,7 +35,7 @@ * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. - * $Id: mpmontg.c,v 1.12 2003/09/26 02:15:12 nelsonb%netscape.com Exp $ + * $Id: mpmontg.c,v 1.13 2003/10/17 13:45:36 ian.mcgreer%sun.com Exp $ */ /* This file implements moduluar exponentiation using Montgomery's @@ -68,17 +68,7 @@ #define ABORT abort() #endif -typedef struct { - mp_int N; /* modulus N */ - mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */ - mp_size b; /* R == 2 ** b, also b = # significant bits in N */ -} mp_mont_modulus; - -mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, - mp_mont_modulus *mmm); - /* computes T = REDC(T), 2^b == R */ -STATIC mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm) { mp_err res; diff --git a/security/nss/lib/freebl/mpi/target.mk b/security/nss/lib/freebl/mpi/target.mk new file mode 100644 index 000000000000..ee175d2a42b6 --- /dev/null +++ b/security/nss/lib/freebl/mpi/target.mk @@ -0,0 +1,220 @@ +## 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 MPI Arbitrary Precision Integer Arithmetic +## library. +## +## The Initial Developer of the Original Code is +## Michael J. Fromberger +## +## Portions created by Michael J. Fromberger are +## Copyright (C) 1998, 2000 Michael J. Fromberger. All Rights Reserved. +## +## Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +## Sun Microsystems, Inc. All Rights Reserved. +## +## Contributor(s): +## Netscape Communications Corporation +## Richard C. Swift (swift@netscape.com) +## Douglas Stebila , Sun Microsystems Laboratories +## +## Alternatively, the contents of this file may be used under the +## terms of the GNU General Public License Version 2 or later (the +## "GPL"), in which case the provisions of the GPL are applicable +## instead of those above. If you wish to allow use of your +## version of this file only under the terms of the GPL and not to +## allow others to use your version of this file under the MPL, +## indicate your decision by deleting the provisions above and +## replace them with the notice and other provisions required by +## the GPL. If you do not delete the provisions above, a recipient +## may use your version of this file under either the MPL or the +## GPL. +## + +## +## Define CFLAGS to contain any local options your compiler +## setup requires. +## +## Conditional compilation options are no longer here; see +## the file 'mpi-config.h' instead. +## +MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC +CFLAGS= -O $(MPICMN) +#CFLAGS=-ansi -fullwarn -woff 1521 -O3 $(MPICMN) +#CFLAGS=-ansi -pedantic -Wall -O3 $(MPICMN) +#CFLAGS=-ansi -pedantic -Wall -g -O2 -DMP_DEBUG=1 $(MPICMN) + +ifeq ($(TARGET),mipsIRIX) +#IRIX +#MPICMN += -DMP_MONT_USE_MP_MUL +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE +MPICMN += -DMP_USE_UINT_DIGIT +#MPICMN += -DMP_NO_MP_WORD +AS_OBJS = mpi_mips.o +#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -exceptions +ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 +#CFLAGS=-ansi -n32 -O3 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) +CFLAGS=-ansi -n32 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) +#CFLAGS=-ansi -n32 -g -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN) +#CFLAGS=-ansi -64 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE -DMP_NO_MP_WORD \ + $(MPICMN) +endif + +ifeq ($(TARGET),alphaOSF1) +#Alpha/OSF1 +MPICMN += -DMP_ASSEMBLY_MULTIPLY +AS_OBJS+= mpvalpha.o +#CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT $(MPICMN) +CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT \ + -DMP_NO_MP_WORD $(MPICMN) +endif + +ifeq ($(TARGET),v9SOLARIS) +#Solaris 64 +SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a -KPIC -mt +#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v9a -KPIC -mt +SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v9a -KPIC -mt +AS_OBJS += montmulfv9.o +AS_OBJS += mpi_sparc.o mpv_sparcv9.o +MPICMN += -DMP_USE_UINT_DIGIT +#MPICMN += -DMP_NO_MP_WORD +MPICMN += -DMP_ASSEMBLY_MULTIPLY +MPICMN += -DMP_USING_MONT_MULF +CFLAGS= -O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_8 -xarch=v9 -DXP_UNIX $(MPICMN) +#CFLAGS= -g -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_8 -xarch=v9 -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),v8plusSOLARIS) +#Solaris 32 +SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8plusa -KPIC -mt +SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt +AS_OBJS += montmulfv8.o +AS_OBJS += mpi_sparc.o mpv_sparcv8.o +#AS_OBJS = montmulf.o +MPICMN += -DMP_ASSEMBLY_MULTIPLY +MPICMN += -DMP_USING_MONT_MULF +MPICMN += -DMP_USE_UINT_DIGIT +MPICMN += -DMP_NO_MP_WORD +CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_6 -xarch=v8plus -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),v8SOLARIS) +#Solaris 32 +#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8 -KPIC -mt +#SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt +#AS_OBJS = montmulfv8.o mpi_sparc.o mpv_sparcv8.o +#AS_OBJS = montmulf.o +#MPICMN += -DMP_USING_MONT_MULF +#MPICMN += -DMP_ASSEMBLY_MULTIPLY +MPICMN += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT +MPICMN += -DMP_NO_MP_WORD +CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \ + -DSOLARIS2_6 -xarch=v8 -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),ia64HPUX) +#HPUX 32 on ia64 -- 64 bit digits SCREAM. +# This one is for DD32 which is the 32-bit ABI with 64-bit registers. +CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +#CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +endif + +ifeq ($(TARGET),ia64HPUX64) +#HPUX 32 on ia64 +# This one is for DD64 which is the 64-bit ABI +CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN) +endif + +ifeq ($(TARGET),PA2.0WHPUX) +#HPUX64 (HP PA 2.0 Wide) using MAXPY and 64-bit digits +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE +AS_OBJS = mpi_hp.o hpma512.o hppa20.o +CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +O3 +DChpux -DHPUX11 -DXP_UNIX \ + $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ + $(MPICMN) +AS = $(CC) $(CFLAGS) -c +endif + +ifeq ($(TARGET),PA2.0NHPUX) +#HPUX32 (HP PA 2.0 Narrow) hybrid model, using 32-bit digits +# This one is for DA2.0 (N) which is the 32-bit ABI with 64-bit registers. +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE +AS_OBJS = mpi_hp.o hpma512.o hppa20.o +CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ + -Wl,+k $(MPICMN) +#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \ + -Wl,+k $(MPICMN) +AS = $(CC) $(CFLAGS) -c +endif + +ifeq ($(TARGET),PA1.1HPUX) +#HPUX32 (HP PA 1.1) Pure 32 bit +MPICMN += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD +#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY +CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ + -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN) +##CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \ +# -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN) +endif + +ifeq ($(TARGET),32AIX) +# +CC = xlC_r +MPICMN += -DMP_USE_UINT_DIGIT +MPICMN += -DMP_NO_DIV_WORD +#MPICMN += -DMP_NO_MUL_WORD +MPICMN += -DMP_NO_ADD_WORD +MPICMN += -DMP_NO_SUB_WORD +#MPICMN += -DMP_NO_MP_WORD +#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY +CFLAGS = -O -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) +#CFLAGS = -g -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) +#CFLAGS += -pg +endif + +ifeq ($(TARGET),64AIX) +# +CC = xlC_r +MPICMN += -DMP_USE_UINT_DIGIT +CFLAGS = -O -O2 -DAIX -DSYSV -qarch=com -DAIX_64BIT -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN) +OBJECT_MODE=64 +export OBJECT_MODE +endif + +ifeq ($(TARGET),x86LINUX) +#Linux +AS_OBJS = mpi_x86.o +MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D +MPICMN += -DMP_MONT_USE_MP_MUL +CFLAGS= -O2 -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ + -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ + -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) +#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ + -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ + -DXP_UNIX -DDEBUG -UNDEBUG -D_REENTRANT $(MPICMN) +#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \ + -pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \ + -DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN) +endif diff --git a/security/nss/lib/nss/nss.def b/security/nss/lib/nss/nss.def index f36d6f7e1b49..3531fe63455f 100644 --- a/security/nss/lib/nss/nss.def +++ b/security/nss/lib/nss/nss.def @@ -761,9 +761,13 @@ SECKEY_PublicKeyStrengthInBits; CERT_DecodeTimeChoice; CERT_EncodeTimeChoice; ;;CERT_TimeChoiceTemplate DATA ; +DSAU_EncodeDerSigWithLen; +DSAU_DecodeDerSigToLen; NSS_Get_CERT_TimeChoiceTemplate; PK11_ExportEncryptedPrivKeyInfo; PK11_FindSlotsByAliases; +PK11_PubDeriveExtended; +SECKEY_ECParams2KeySize; SECMOD_GetDBModuleList; SECMOD_GetDeadModuleList; SEC_ASN1DecoderAbort; diff --git a/security/nss/lib/pk11wrap/manifest.mn b/security/nss/lib/pk11wrap/manifest.mn index d4abd991736c..0dfc21ef9488 100644 --- a/security/nss/lib/pk11wrap/manifest.mn +++ b/security/nss/lib/pk11wrap/manifest.mn @@ -76,3 +76,7 @@ ifdef DEBUG_PKCS11 DEFINES += -DDEBUG_MODULE endif +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index fd67455af5f4..72b8b99eb20b 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -352,6 +356,13 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dh.publicValue.data, pubKey->u.dh.publicValue.len); break; +#ifdef NSS_ENABLE_ECC + case ecKey: + PK11_SETATTRS(&theTemplate,CKA_EC_POINT, + pubKey->u.ec.publicValue.data, + pubKey->u.ec.publicValue.len); + break; +#endif /* NSS_ENABLE_ECC */ case keaKey: case fortezzaKey: case nullKey: @@ -1507,6 +1518,11 @@ PK11_GetPubIndexKeyID(CERTCertificate *cert) { case dhKey: newItem = SECITEM_DupItem(&pubk->u.dh.publicValue); break; + case ecKey: +#ifdef NSS_ENABLE_ECC + newItem = SECITEM_DupItem(&pubk->u.ec.publicValue); +#endif /* NSS_ENABLE_ECC */ + break; case fortezzaKey: default: newItem = NULL; /* Fortezza Fix later... */ diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h index 4f31f3e380a6..d4f637de9e0d 100644 --- a/security/nss/lib/pk11wrap/pk11func.h +++ b/security/nss/lib/pk11wrap/pk11func.h @@ -17,6 +17,7 @@ * Rights Reserved. * * Contributor(s): + * Douglas Stebila , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -306,6 +307,11 @@ PK11SymKey *PK11_PubDerive( SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB, CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx) ; +PK11SymKey *PK11_PubDeriveExtended( SECKEYPrivateKey *privKey, + SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB, + CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, + CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx, + CK_ULONG kdf, SECItem *sharedData); PK11SymKey *PK11_UnwrapSymKey(PK11SymKey *key, CK_MECHANISM_TYPE wraptype, SECItem *param, SECItem *wrapppedKey, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize); diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index 684e26cd2276..b772c8885ecc 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -21,7 +21,8 @@ * * Contributor(s): * Dr Stephen Henson - * Dr Vipul Gupta , Sun Microsystems Laboratories + * Dr Vipul Gupta and + * Douglas Stebila , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -68,6 +69,9 @@ static PK11SymKey *pk11_DeriveWithTemplate(PK11SymKey *baseKey, CK_ATTRIBUTE_TYPE operation, int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs); +#ifdef NSS_ENABLE_ECC +extern int SECKEY_ECParams2KeySize(SECItem *params); +#endif /* NSS_ENABLE_ECC */ /* * strip leading zero's from key material @@ -1225,6 +1229,7 @@ pk11_backupGetSignLength(SECKEYPrivateKey *key) } return len; } + /* * get the length of a signature object based on the key */ @@ -1232,6 +1237,11 @@ int PK11_SignatureLen(SECKEYPrivateKey *key) { int val; +#ifdef NSS_ENABLE_ECC + CK_ATTRIBUTE theTemplate = { CKA_EC_PARAMS, NULL, 0 }; + SECItem params = {siBuffer, NULL, 0}; + int length; +#endif /* NSS_ENABLE_ECC */ switch (key->keyType) { case rsaKey: @@ -1244,7 +1254,21 @@ PK11_SignatureLen(SECKEYPrivateKey *key) case fortezzaKey: case dsaKey: return 40; - +#ifdef NSS_ENABLE_ECC + case ecKey: + if (PK11_GetAttributes(NULL, key->pkcs11Slot, key->pkcs11ID, + &theTemplate, 1) == CKR_OK) { + if (theTemplate.pValue != NULL) { + params.len = theTemplate.ulValueLen; + params.data = (unsigned char *) theTemplate.pValue; + length = SECKEY_ECParams2KeySize(¶ms); + PORT_Free(theTemplate.pValue); + } + length = ((length + 7)/8) * 2; + return length; + } + break; +#endif /* NSS_ENABLE_ECC */ default: break; } @@ -1735,6 +1759,8 @@ pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, * We are not doing consistency check for Diffie-Hellman Key - * otherwise it would be here * This is also true for Elliptic Curve Diffie-Hellman keys + * NOTE: EC keys are currently subjected to pairwise + * consistency check for signing/verification. */ } @@ -1825,6 +1851,12 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, ap->type = CKA_BASE; ap++; count++; extra_count++; ap->type = CKA_VALUE; ap++; count++; extra_count++; break; +#ifdef NSS_ENABLE_ECC + case ecKey: + ap->type = CKA_EC_PARAMS; ap++; count++; extra_count++; + ap->type = CKA_VALUE; ap++; count++; extra_count++; + break; +#endif /* NSS_ENABLE_ECC */ default: count = 0; extra_count = 0; @@ -2205,7 +2237,6 @@ PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, crv = PK11_GETTAB(slot)->C_GenerateKeyPair(session_handle, &mechanism, pubTemplate,pubCount,privTemplate,privCount,&pubID,&privID); - if (crv != CKR_OK) { if (restore) { PK11_RestoreROSession(slot,session_handle); @@ -2869,6 +2900,115 @@ PK11_PubDerive(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, if (crv == CKR_OK) return symKey; PORT_SetError( PK11_MapError(crv) ); } +#else + case ecKey: + break; +#endif /* NSS_ENABLE_ECC */ + } + + PK11_FreeSymKey(symKey); + return NULL; +} + +PK11SymKey * +PK11_PubDeriveExtended(SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, + PRBool isSender, SECItem *randomA, SECItem *randomB, + CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target, + CK_ATTRIBUTE_TYPE operation, int keySize,void *wincx, + CK_ULONG kdf, SECItem *sharedData) +{ + PK11SlotInfo *slot = privKey->pkcs11Slot; + PK11SymKey *symKey; +#ifdef NSS_ENABLE_ECC + CK_MECHANISM mechanism; + CK_RV crv; +#endif + + /* get our key Structure */ + symKey = PK11_CreateSymKey(slot,target,wincx); + if (symKey == NULL) { + return NULL; + } + + symKey->origin = PK11_OriginDerive; + + switch (privKey->keyType) { + case rsaKey: + case nullKey: + case dsaKey: + case keaKey: + case fortezzaKey: + case dhKey: + PK11_FreeSymKey(symKey); + return PK11_PubDerive(privKey, pubKey, isSender, randomA, randomB, + derive, target, operation, keySize, wincx); +#ifdef NSS_ENABLE_ECC + case ecKey: + { + CK_BBOOL cktrue = CK_TRUE; + CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY; + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; + CK_ULONG key_size = 0; + CK_ATTRIBUTE keyTemplate[4]; + int templateCount; + CK_ATTRIBUTE *attrs = keyTemplate; + CK_ECDH1_DERIVE_PARAMS *mechParams = NULL; + + if (pubKey->keyType != ecKey) { + PORT_SetError(SEC_ERROR_BAD_KEY); + break; + } + + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); + attrs++; + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); + attrs++; + PK11_SETATTRS(attrs, operation, &cktrue, 1); attrs++; + PK11_SETATTRS(attrs, CKA_VALUE_LEN, &key_size, sizeof(key_size)); + attrs++; + templateCount = attrs - keyTemplate; + PR_ASSERT(templateCount <= sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE)); + + keyType = PK11_GetKeyType(target,keySize); + key_size = keySize; + symKey->size = keySize; + if (key_size == 0) templateCount--; + + mechParams = (CK_ECDH1_DERIVE_PARAMS *) + PORT_ZAlloc(sizeof(CK_ECDH1_DERIVE_PARAMS)); + if ((kdf < CKD_NULL) || (kdf > CKD_SHA1_KDF)) { + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + break; + } + mechParams->kdf = kdf; + if (sharedData == NULL) { + mechParams->ulSharedDataLen = 0; + mechParams->pSharedData = NULL; + } else { + mechParams->ulSharedDataLen = sharedData->len; + mechParams->pSharedData = sharedData->data; + } + mechParams->ulPublicDataLen = pubKey->u.ec.publicValue.len; + mechParams->pPublicData = pubKey->u.ec.publicValue.data; + + mechanism.mechanism = derive; + mechanism.pParameter = mechParams; + mechanism.ulParameterLen = sizeof(CK_ECDH1_DERIVE_PARAMS); + + pk11_EnterKeyMonitor(symKey); + crv = PK11_GETTAB(slot)->C_DeriveKey(symKey->session, + &mechanism, privKey->pkcs11ID, keyTemplate, + templateCount, &symKey->objectID); + pk11_ExitKeyMonitor(symKey); + + PORT_ZFree(mechParams, sizeof(CK_ECDH1_DERIVE_PARAMS)); + + if (crv == CKR_OK) return symKey; + PORT_SetError( PK11_MapError(crv) ); + } +#else + case ecKey: + break; #endif /* NSS_ENABLE_ECC */ } @@ -4567,7 +4707,9 @@ PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, CKA_UNWRAP, CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER }; CK_ATTRIBUTE_TYPE dsaUsage[] = { CKA_SIGN }; CK_ATTRIBUTE_TYPE dhUsage[] = { CKA_DERIVE }; - +#ifdef NSS_ENABLE_ECC + CK_ATTRIBUTE_TYPE ecUsage[] = { CKA_SIGN, CKA_DERIVE }; +#endif /* NSS_ENABLE_ECC */ if((epki == NULL) || (pwitem == NULL)) return SECFailure; @@ -4606,6 +4748,26 @@ PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, usage = dsaUsage; usageCount = sizeof(dsaUsage)/sizeof(dsaUsage[0]); break; +#ifdef NSS_ENABLE_ECC + case ecKey: + key_type = CKK_EC; + switch (keyUsage & (KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) { + case KU_DIGITAL_SIGNATURE: + usage = ecUsage; + usageCount = 1; + break; + case KU_KEY_AGREEMENT: + usage = &ecUsage[1]; + usageCount = 1; + break; + case KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT: + default: /* default to everything */ + usage = ecUsage; + usageCount = 2; + break; + } + break; +#endif /* NSS_ENABLE_ECC */ } try_faulty_3des: @@ -4645,7 +4807,6 @@ try_faulty_3des: rv = SECSuccess; goto done; } - /* if we are unable to import the key and the mechanism is * CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, then it is possible that * the encrypted blob was created with a buggy key generation method @@ -4706,9 +4867,20 @@ pk11_private_key_encrypt_buffer_length(SECKEYPrivateKey *key) { CK_ATTRIBUTE rsaTemplate = { CKA_MODULUS, NULL, 0 }; CK_ATTRIBUTE dsaTemplate = { CKA_PRIME, NULL, 0 }; +#ifdef NSS_ENABLE_ECC + /* XXX We should normally choose an attribute such that + * factor times its size is enough to hold the private key. + * For EC keys, we have no choice but to use CKA_EC_PARAMS, + * CKA_VALUE is not available for token keys. But for named + * curves, the number of bytes needed to represent the params + * is quite small so we bump up factor from 10 to 15. + */ + CK_ATTRIBUTE ecTemplate = { CKA_EC_PARAMS, NULL, 0 }; +#endif /* NSS_ENABLE_ECC */ CK_ATTRIBUTE_PTR pTemplate; CK_RV crv; int length; + int factor = 10; if(!key) { return -1; @@ -4722,6 +4894,12 @@ pk11_private_key_encrypt_buffer_length(SECKEYPrivateKey *key) case dhKey: pTemplate = &dsaTemplate; break; +#ifdef NSS_ENABLE_ECC + case ecKey: + pTemplate = &ecTemplate; + factor = 15; + break; +#endif /* NSS_ENABLE_ECC */ case fortezzaKey: default: pTemplate = NULL; @@ -4739,7 +4917,8 @@ pk11_private_key_encrypt_buffer_length(SECKEYPrivateKey *key) } length = pTemplate->ulValueLen; - length *= 10; + length *= factor; + if(pTemplate->pValue != NULL) { PORT_Free(pTemplate->pValue); diff --git a/security/nss/lib/pkcs12/manifest.mn b/security/nss/lib/pkcs12/manifest.mn index e40f8620facd..fc788c5a58a5 100644 --- a/security/nss/lib/pkcs12/manifest.mn +++ b/security/nss/lib/pkcs12/manifest.mn @@ -55,4 +55,8 @@ CSRCS = \ REQUIRES = dbm +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + LIBRARY_NAME = pkcs12 diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index b88962cd0501..f6ffd30f98ea 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -2747,6 +2751,11 @@ sec_pkcs12_get_public_value_and_type(sec_PKCS12SafeBag *certBag, case rsaKey: pubValue = SECITEM_DupItem(&pubKey->u.rsa.modulus); break; +#ifdef NSS_ENABLE_ECC + case ecKey: + pubValue = SECITEM_DupItem(&pubKey->u.ec.publicValue); + break; +#endif /* NSS_ENABLE_ECC */ default: pubValue = NULL; } diff --git a/security/nss/lib/softoken/ecdecode.c b/security/nss/lib/softoken/ecdecode.c index a981241f70bc..1d952a789eaf 100644 --- a/security/nss/lib/softoken/ecdecode.c +++ b/security/nss/lib/softoken/ecdecode.c @@ -18,7 +18,8 @@ * Sun Microsystems, Inc. All Rights Reserved. * * Contributor(s): - * Dr Vipul Gupta , Sun Microsystems Laboratories + * Dr Vipul Gupta and + * Douglas Stebila , 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 @@ -41,8 +42,10 @@ #include "secitem.h" #include "secerr.h" #include "ec.h" +#include "ecl-curve.h" -#define CHECK_OK(func) if (func == NULL) goto cleanup; +#define CHECK_OK(func) if (func == NULL) goto cleanup +#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup /* Initializes a SECItem from a hexadecimal string */ static SECItem * @@ -54,7 +57,7 @@ hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str) if ((tmp % 2) != 0) return NULL; - item->data = (unsigned char *) PORT_ArenaZAlloc(arena, tmp/2); + item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2); if (item->data == NULL) return NULL; item->len = tmp/2; @@ -79,12 +82,59 @@ hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str) return item; } +/* Copy all of the fields from srcParams into dstParams + */ +SECStatus +EC_CopyParams(PRArenaPool *arena, ECParams *dstParams, + const ECParams *srcParams) +{ + SECStatus rv = SECFailure; + + dstParams->arena = arena; + dstParams->type = srcParams->type; + dstParams->fieldID.size = srcParams->fieldID.size; + dstParams->fieldID.type = srcParams->fieldID.type; + if (srcParams->fieldID.type == ec_field_GFp) { + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.prime, + &srcParams->fieldID.u.prime)); + } else { + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->fieldID.u.poly, + &srcParams->fieldID.u.poly)); + } + dstParams->fieldID.k1 = srcParams->fieldID.k1; + dstParams->fieldID.k2 = srcParams->fieldID.k2; + dstParams->fieldID.k3 = srcParams->fieldID.k3; + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.a, + &srcParams->curve.a)); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.b, + &srcParams->curve.b)); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curve.seed, + &srcParams->curve.seed)); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->base, + &srcParams->base)); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->order, + &srcParams->order)); + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->DEREncoding, + &srcParams->DEREncoding)); + dstParams->name = srcParams->name; + CHECK_SEC_OK(SECITEM_CopyItem(arena, &dstParams->curveOID, + &srcParams->curveOID)); + dstParams->cofactor = srcParams->cofactor; + + return SECSuccess; + +cleanup: + return SECFailure; +} + SECStatus EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams, ECParams *params) { SECOidTag tag; SECItem oid = { siBuffer, NULL, 0}; + const ECCurveParams *curveParams; + char genenc[2 + 2 * 2 * MAX_ECKEY_LEN]; #if EC_DEBUG int i; @@ -113,1444 +163,472 @@ EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams, params->arena = arena; params->cofactor = 0; params->type = ec_params_named; + params->name = ECCurve_noName; + + /* For named curves, fill out curveOID */ + params->curveOID.len = oid.len; + params->curveOID.data = (unsigned char *) PORT_ArenaAlloc(arena, oid.len); + if (params->curveOID.data == NULL) goto cleanup; + memcpy(params->curveOID.data, oid.data, oid.len); #if EC_DEBUG printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag)); #endif switch (tag) { + +#define GF2M_POPULATE \ + if ((params->name < ECCurve_noName) || \ + (params->name > ECCurve_pastLastCurve)) goto cleanup; \ + CHECK_OK(curveParams); \ + params->fieldID.size = curveParams->size; \ + params->fieldID.type = ec_field_GF2m; \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, \ + curveParams->irr)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, \ + curveParams->curvea)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, \ + curveParams->curveb)); \ + genenc[0] = '0'; \ + genenc[1] = '4'; \ + genenc[2] = '\0'; \ + CHECK_OK(strcat(genenc, curveParams->genx)); \ + CHECK_OK(strcat(genenc, curveParams->geny)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, \ + genenc)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, \ + curveParams->order)); \ + params->cofactor = curveParams->cofactor; + case SEC_OID_ANSIX962_EC_C2PNB163V1: /* Populate params for c2pnb163v1 */ - params->fieldID.size = 163; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "0000000107")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "072546B5435234A422E0789675F432C8" \ - "9435DE5242")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "00C9517D06D5240D3CFF38C74B20B6CD" \ - "4D6F9DD4D9")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "07AF69989546103D79329FCC3D74880F" \ - "33BBE803CB" \ - "01EC23211B5966ADEA1D3F87F7EA5848" \ - "AEF0B7CA9F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0400000000000000000001E60FC8821C" \ - "C74DAEAFC1")); - params->cofactor = 2; + params->name = ECCurve_X9_62_CHAR2_PNB163V1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB163V2: /* Populate params for c2pnb163v2 */ - params->fieldID.size = 163; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "0000000107")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "0108B39E77C4B108BED981ED0E890E11" \ - "7C511CF072")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0667ACEB38AF4E488C407433FFAE4F1C" \ - "811638DF20")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0024266E4EB5106D0A964D92C4860E26" \ - "71DB9B6CC5" \ - "079F684DDF6684C5CD258B3890021B23" \ - "86DFD19FC5")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "03FFFFFFFFFFFFFFFFFFFDF64DE1151A" \ - "DBB78F10A7")); - params->cofactor = 2; + params->name = ECCurve_X9_62_CHAR2_PNB163V2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB163V3: /* Populate params for c2pnb163v3 */ - params->fieldID.size = 163; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "0000000107")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "07A526C63D3E25A256A007699F5447E3" \ - "2AE456B50E")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "03F7061798EB99E238FD6F1BF95B48FE" \ - "EB4854252B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "02F9F87B7C574D0BDECF8A22E6524775" \ - "F98CDEBDCB" \ - "05B935590C155E17EA48EB3FF3718B89" \ - "3DF59A05D0")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "03FFFFFFFFFFFFFFFFFFFE1AEE140F11" \ - "0AFF961309")); - params->cofactor = 2; + params->name = ECCurve_X9_62_CHAR2_PNB163V3; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB176V1: /* Populate params for c2pnb176v1 */ - params->fieldID.size = 176; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "01000000000000000000000000000000" \ - "00080000000007")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "E4E6DB2995065C407D9D39B8D0967B96" \ - "704BA8E9C90B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "5DDA470ABE6414DE8EC133AE28E9BBD7" \ - "FCEC0AE0FFF2")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "8D16C2866798B600F9F08BB4A8E860F3" \ - "298CE04A5798" \ - "6FA4539C2DADDDD6BAB5167D61B436E1" \ - "D92BB16A562C")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "00010092537397ECA4F6145799D62B0A" \ - "19CE06FE26AD")); - params->cofactor = 0xFF6E; + params->name = ECCurve_X9_62_CHAR2_PNB176V1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB191V1: /* Populate params for c2tnb191v1 */ - params->fieldID.size = 191; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "0000000000000201")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "2866537B676752636A68F56554E12640" \ - "276B649EF7526267")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "2E45EF571F00786F67B0081B9495A3D9" \ - "5462F5DE0AA185EC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "36B3DAF8A23206F9C4F299D7B21A9C36" \ - "9137F2C84AE1AA0D" \ - "765BE73433B3F95E332932E70EA245CA" \ - "2418EA0EF98018FB")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "40000000000000000000000004A20E90" \ - "C39067C893BBB9A5")); - params->cofactor = 2; + params->name = ECCurve_X9_62_CHAR2_TNB191V1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB191V2: /* Populate params for c2tnb191v2 */ - params->fieldID.size = 191; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "0000000000000201")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "401028774D7777C7B7666D1366EA4320" \ - "71274F89FF01E718")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0620048D28BCBD03B6249C99182B7C8C" \ - "D19700C362C46A01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "3809B2B7CC1B28CC5A87926AAD83FD28" \ - "789E81E2C9E3BF10" \ - "17434386626D14F3DBF01760D9213A3E" \ - "1CF37AEC437D668A")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "20000000000000000000000050508CB8" \ - "9F652824E06B8173")); - params->cofactor = 4; + params->name = ECCurve_X9_62_CHAR2_TNB191V2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB191V3: /* Populate params for c2tnb191v3 */ - params->fieldID.size = 191; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "0000000000000201")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "6C01074756099122221056911C77D77E" \ - "77A777E7E7E77FCB")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "71FE1AF926CF847989EFEF8DB459F663" \ - "94D90F32AD3F15E8")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "375D4CE24FDE434489DE8746E7178601" \ - "5009E66E38A926DD" \ - "545A39176196575D985999366E6AD34C" \ - "E0A77CD7127B06BE")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "155555555555555555555555610C0B19" \ - "6812BFB6288A3EA3")); - params->cofactor = 6; + params->name = ECCurve_X9_62_CHAR2_TNB191V3; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB208W1: /* Populate params for c2pnb208w1 */ - params->fieldID.size = 208; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "01000000000000000000000000000000" \ - "0800000000000000000007")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "C8619ED45A62E6212E1160349E2BFA84" \ - "4439FAFC2A3FD1638F9E")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "89FDFBE4ABE193DF9559ECF07AC0CE78" \ - "554E2784EB8C1ED1A57A" \ - "0F55B51A06E78E9AC38A035FF520D8B0" \ - "1781BEB1A6BB08617DE3")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "000101BAF95C9723C57B6C21DA2EFF2D" \ - "5ED588BDD5717E212F9D")); - params->cofactor = 0xFE48; + params->name = ECCurve_X9_62_CHAR2_PNB208W1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB239V1: /* Populate params for c2tnb239v1 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "0000000000000000001000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "32010857077C5431123A46B808906756" \ - "F543423E8D27877578125778AC76")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "790408F2EEDAF392B012EDEFB3392F30" \ - "F4327C0CA3F31FC383C422AA8C16")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "57927098FA932E7C0A96D3FD5B706EF7" \ - "E5F5C156E16B7E7C86038552E91D" \ - "61D8EE5077C33FECF6F1A16B268DE469" \ - "C3C7744EA9A971649FC7A9616305")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "2000000000000000000000000000000F" \ - "4D42FFE1492A4993F1CAD666E447")); - params->cofactor = 4; + params->name = ECCurve_X9_62_CHAR2_TNB239V1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB239V2: /* Populate params for c2tnb239v2 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "0000000000000000001000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "4230017757A767FAE42398569B746325" \ - "D45313AF0766266479B75654E65F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "5037EA654196CFF0CD82B2C14A2FCF2E" \ - "3FF8775285B545722F03EACDB74B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "28F9D04E900069C8DC47A08534FE76D2" \ - "B900B7D7EF31F5709F200C4CA205" \ - "5667334C45AFF3B5A03BAD9DD75E2C71" \ - "A99362567D5453F7FA6E227EC833")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "1555555555555555555555555555553C" \ - "6F2885259C31E3FCDF154624522D")); - params->cofactor = 6; + params->name = ECCurve_X9_62_CHAR2_TNB239V2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB239V3: /* Populate params for c2tnb239v3 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "0000000000000000001000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01238774666A67766D6676F778E676B6" \ - "6999176666E687666D8766C66A9F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "6A941977BA9F6A435199ACFC51067ED5" \ - "87F519C5ECB541B8E44111DE1D40")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "70F6E9D04D289C4E89913CE3530BFDE9" \ - "03977D42B146D539BF1BDE4E9C92" \ - "2E5A0EAF6E5E1305B9004DCE5C0ED7FE" \ - "59A35608F33837C816D80B79F461")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC" \ - "4912D2D9DF903EF9888B8A0E4CFF")); - params->cofactor = 0x0A; + params->name = ECCurve_X9_62_CHAR2_TNB239V3; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB272W1: /* Populate params for c2pnb272w1 */ - params->fieldID.size = 272; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "01000000000000000000000000000000" \ - "00000000000000000000000100000000" \ - "00000B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "91A091F03B5FBA4AB2CCF49C4EDD220F" \ - "B028712D42BE752B2C40094DBACDB586" \ - "FB20")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "7167EFC92BB2E3CE7C8AAAFF34E12A9C" \ - "557003D7C73A6FAF003F99F6CC8482E5" \ - "40F7")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "6108BABB2CEEBCF787058A056CBE0CFE" \ - "622D7723A289E08A07AE13EF0D10D171" \ - "DD8D" \ - "10C7695716851EEF6BA7F6872E6142FB" \ - "D241B830FF5EFCACECCAB05E02005DDE" \ - "9D23")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "000100FAF51354E0E39E4892DF6E319C" \ - "72C8161603FA45AA7B998A167B8F1E62" \ - "9521")); - params->cofactor = 0xFF06; + params->name = ECCurve_X9_62_CHAR2_PNB272W1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB304W1: /* Populate params for c2pnb304w1 */ - params->fieldID.size = 304; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "01000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000807")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FD0D693149A118F651E6DCE680208537" \ - "7E5F882D1B510B44160074C128807836" \ - "5A0396C8E681")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "BDDB97E555A50A908E43B01C798EA5DA" \ - "A6788F1EA2794EFCF57166B8C1403960" \ - "1E55827340BE")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "197B07845E9BE2D96ADB0F5F3C7F2CFF" \ - "BD7A3EB8B6FEC35C7FD67F26DDF6285A" \ - "644F740A2614" \ - "E19FBEB76E0DA171517ECF401B50289B" \ - "F014103288527A9B416A105E80260B54" \ - "9FDC1B92C03B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "000101D556572AABAC800101D556572A" \ - "ABAC8001022D5C91DD173F8FB561DA68" \ - "99164443051D")); - params->cofactor = 0xFE2E; + params->name = ECCurve_X9_62_CHAR2_PNB304W1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB359V1: /* Populate params for c2tnb359v1 */ - params->fieldID.size = 359; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000100000000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "5667676A654B20754F356EA92017D946" \ - "567C46675556F19556A04616B567D223" \ - "A5E05656FB549016A96656A557")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "2472E2D0197C49363F1FE7F5B6DB075D" \ - "52B6947D135D8CA445805D39BC345626" \ - "089687742B6329E70680231988")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "3C258EF3047767E7EDE0F1FDAA79DAEE" \ - "3841366A132E163ACED4ED2401DF9C6B" \ - "DCDE98E8E707C07A2239B1B097" \ - "53D7E08529547048121E9C95F3791DD8" \ - "04963948F34FAE7BF44EA82365DC7868" \ - "FE57E4AE2DE211305A407104BD")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "01AF286BCA1AF286BCA1AF286BCA1AF2" \ - "86BCA1AF286BC9FB8F6B85C556892C20" \ - "A7EB964FE7719E74F490758D3B")); - params->cofactor = 0x4C; + params->name = ECCurve_X9_62_CHAR2_TNB359V1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2PNB368W1: /* Populate params for c2pnb368w1 */ - params->fieldID.size = 368; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "01000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "000000002000000000000000000007")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "E0D2EE25095206F5E2A4F9ED229F1F25" \ - "6E79A0E2B455970D8D0D865BD94778C5" \ - "76D62F0AB7519CCD2A1A906AE30D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "FC1217D4320A90452C760A58EDCD30C8" \ - "DD069B3C34453837A34ED50CB54917E1" \ - "C2112D84D164F444F8F74786046A")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "1085E2755381DCCCE3C1557AFA10C2F0" \ - "C0C2825646C5B34A394CBCFA8BC16B22" \ - "E7E789E927BE216F02E1FB136A5F" \ - "7B3EB1BDDCBA62D5D8B2059B525797FC" \ - "73822C59059C623A45FF3843CEE8F87C" \ - "D1855ADAA81E2A0750B80FDA2310")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "00010090512DA9AF72B08349D98A5DD4" \ - "C7B0532ECA51CE03E2D10F3B7AC579BD" \ - "87E909AE40A6F131E9CFCE5BD967")); - params->cofactor = 0xFF70; + params->name = ECCurve_X9_62_CHAR2_PNB368W1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_ANSIX962_EC_C2TNB431R1: /* Populate params for c2tnb431r1 */ - params->fieldID.size = 431; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000001000000000000000000" \ - "000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "1A827EF00DD6FC0E234CAF046C6A5D8A" \ - "85395B236CC4AD2CF32A0CADBDC9DDF6" \ - "20B0EB9906D0957F6C6FEACD615468DF" \ - "104DE296CD8F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "10D9B4A3D9047D8B154359ABFB1B7F54" \ - "85B04CEB868237DDC9DEDA982A679A5A" \ - "919B626D4E50A8DD731B107A9962381F" \ - "B5D807BF2618")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "120FC05D3C67A99DE161D2F4092622FE" \ - "CA701BE4F50F4758714E8A87BBF2A658" \ - "EF8C21E7C5EFE965361F6C2999C0C247" \ - "B0DBD70CE6B7" \ - "20D0AF8903A96F8D5FA2C255745D3C45" \ - "1B302C9346D9B7E485E7BCE41F6B591F" \ - "3E8F6ADDCBB0BC4C2F947A7DE1A89B62" \ - "5D6A598B3760")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "03403403403403403403403403403403" \ - "40340340340340340340340323C313FA" \ - "B50589703B5EC68D3587FEC60D161CC1" \ - "49C1AD4A91")); - params->cofactor = 0x2760; + params->name = ECCurve_X9_62_CHAR2_TNB431R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT113R1: /* Populate params for sect113r1 */ - params->fieldID.size = 113; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "020000000000000000000000000201")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "003088250CA6E7C7FE649CE85820F7")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "00E8BEE4D3E2260744188BE0E9C723")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "009D73616F35F4AB1407D73562C10F" \ - "00A52830277958EE84D1315ED31886")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0100000000000000D9CCEC8A39E56F")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_113R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT113R2: /* Populate params for sect113r2 */ - params->fieldID.size = 113; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "020000000000000000000000000201")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00689918DBEC7E5A0DD6DFC0AA55C7")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0095E9A9EC9B297BD4BF36E059184F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "01A57A6A7B26CA5EF52FCDB8164797" \ - "00B3ADC94ED1FE674C06E695BABA1D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "010000000000000108789B2496AF93")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_113R2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT131R1: /* Populate params for sect131r1 */ - params->fieldID.size = 131; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000001" \ - "0D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "07A11B09A76B562144418FF3FF8C2570" \ - "B8")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0217C05610884B63B9C6C7291678F9D3" \ - "41")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0081BAF91FDF9833C40F9C1813436383" \ - "99" \ - "078C6E7EA38C001F73C8134B1B4EF9E1" \ - "50")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0400000000000000023123953A9464B5" \ - "4D")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_131R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT131R2: /* Populate params for sect131r2 */ - params->fieldID.size = 131; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000001" \ - "0D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "03E5A88919D7CAFCBF415F07C2176573" \ - "B2")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "04B8266A46C55657AC734CE38F018F21" \ - "92")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0356DCD8F2F95031AD652D23951BB366" \ - "A8" \ - "0648F06D867940A5366D9E265DE9EB24" \ - "0F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0400000000000000016954A233049BA9" \ - "8F")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_131R2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT163K1: /* Populate params for sect163k1 * (the NIST K-163 curve) */ - params->fieldID.size = 163; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000C9")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "02FE13C0537BBC11ACAA07D793DE4E6D" \ - "5E5C94EEE8" \ - "0289070FB05D38FF58321F2E800536D5" \ - "38CCDAA3D9")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "04000000000000000000020108A2E0CC" \ - "0D99F8A5EF")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_163K1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT163R1: /* Populate params for sect163r1 */ - params->fieldID.size = 163; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000C9")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "07B6882CAAEFA84F9554FF8428BD88E2" \ - "46D2782AE2")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0713612DCDDCB40AAB946BDA29CA91F7" \ - "3AF958AFD9")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0369979697AB43897789566789567F78" \ - "7A7876A654" \ - "00435EDB42EFAFB2989D51FEFCE3C809" \ - "88F41FF883")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "03FFFFFFFFFFFFFFFFFFFF48AAB689C2" \ - "9CA710279B")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_163R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT163R2: /* Populate params for sect163r2 * (the NIST B-163 curve) */ - params->fieldID.size = 163; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000C9")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "020A601907B8C953CA1481EB10512F78" \ - "744A3205FD")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "03F0EBA16286A2D57EA0991168D49946" \ - "37E8343E36" \ - "00D51FBC6C71A0094FA2CDD545B11C5C" \ - "0C797324F1")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "040000000000000000000292FE77E70C" \ - "12A4234C33")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_163R2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT193R1: /* Populate params for sect193r1 */ - params->fieldID.size = 193; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "02000000000000000000000000000000" \ - "000000000000008001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "0017858FEB7A98975169E171F77B4087" \ - "DE098AC8A911DF7B01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "00FDFB49BFE6C3A89FACADAA7A1E5BBC" \ - "7CC1C2E5D831478814")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "01F481BC5F0FF84A74AD6CDF6FDEF4BF" \ - "6179625372D8C0C5E1" \ - "0025E399F2903712CCF3EA9E3A1AD17F" \ - "B0B3201B6AF7CE1B05")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "01000000000000000000000000C7F34A" \ - "778F443ACC920EBA49")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_193R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT193R2: /* Populate params for sect193r2 */ - params->fieldID.size = 193; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "02000000000000000000000000000000" \ - "000000000000008001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "0163F35A5137C2CE3EA6ED8667190B0B" \ - "C43ECD69977702709B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "00C9BB9E8927D4D64C377E2AB2856A5B" \ - "16E3EFB7F61D4316AE")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "00D9B67D192E0367C803F39E1A7E82CA1" \ - "4A651350AAE617E8F" \ - "01CE94335607C304AC29E7DEFBD9CA01" \ - "F596F927224CDECF6C")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "010000000000000000000000015AAB56" \ - "1B005413CCD4EE99D5")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_193R2; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT233K1: /* Populate params for sect233k1 * (the NIST K-233 curve) */ - params->fieldID.size = 233; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "02000000000000000000000000000000" \ - "0000000004000000000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "017232BA853A7E731AF129F22FF41495" \ - "63A419C26BF50A4C9D6EEFAD6126" \ - "01DB537DECE819B7F70F555A67C427A8" \ - "CD9BF18AEB9B56E0C11056FAE6A3")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "00800000000000000000000000000006" \ - "9D5BB915BCD46EFB1AD5F173ABDF")); - params->cofactor = 4; + params->name = ECCurve_SECG_CHAR2_233K1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT233R1: /* Populate params for sect233r1 * (the NIST B-233 curve) */ - params->fieldID.size = 233; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "02000000000000000000000000000000" \ - "0000000004000000000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00000000000000000000000000000000" \ - "0000000000000000000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0066647EDE6C332C7F8C0923BB58213B" \ - "333B20E9CE4281FE115F7D8F90AD")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "00FAC9DFCBAC8313BB2139F1BB755FEF" \ - "65BC391F8B36F8F8EB7371FD558B" \ - "01006A08A41903350678E58528BEBF8A" \ - "0BEFF867A7CA36716F7E01F81052")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "01000000000000000000000000000013" \ - "E974E72F8A6922031D2603CFE0D7")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_233R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT239K1: /* Populate params for sect239k1 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "80000000000000000000400000000000" \ - "0000000000000000000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "29A0B6A887A983E9730988A68727A8B2" \ - "D126C44CC2CC7B2A6555193035DC" \ - "76310804F12E549BDB011C103089E735" \ - "10ACB275FC312A5DC6B76553F0CA")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "2000000000000000000000000000005A" \ - "79FEC67CB6E91F1C1DA800E478A5")); - params->cofactor = 4; + params->name = ECCurve_SECG_CHAR2_239K1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT283K1: /* Populate params for sect283k1 * (the NIST K-283 curve) */ - params->fieldID.size = 283; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "000010A1")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0503213F78CA44883F1A3B8162F188E5" \ - "53CD265F23C1567A16876913B0C2AC24" \ - "58492836" \ - "01CCDA380F1C9E318D90F95D07E5426F" \ - "E87E45C0E8184698E45962364E341161" \ - "77DD2259")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFE9AE2ED07577265DFF7F94451E06" \ - "1E163C61")); - params->cofactor = 4; + params->name = ECCurve_SECG_CHAR2_283K1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT283R1: /* Populate params for sect283r1 * (the NIST B-283 curve) */ - params->fieldID.size = 283; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "000010A1")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "027B680AC8B8596DA5A4AF8A19A0303F" \ - "CA97FD7645309FA2A581485AF6263E31" \ - "3B79A2F5")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "05F939258DB7DD90E1934F8C70B0DFEC" \ - "2EED25B8557EAC9C80E2E198F8CDBECD" \ - "86B12053" \ - "03676854FE24141CB98FE6D4B20D02B4" \ - "516FF702350EDDB0826779C813F0DF45" \ - "BE8112F4")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFEF90399660FC938A90165B042A7C" \ - "EFADB307")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_283R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT409K1: /* Populate params for sect409k1 * (the NIST K-409 curve) */ - params->fieldID.size = 409; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "02000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000000000080000000000000" \ - "00000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0060F05F658F49C1AD3AB1890F718421" \ - "0EFD0987E307C84C27ACCFB8F9F67CC2" \ - "C460189EB5AAAA62EE222EB1B35540CF" \ - "E9023746" \ - "01E369050B7C4E42ACBA1DACBF04299C" \ - "3460782F918EA427E6325165E9EA10E3" \ - "DA5F6C42E9C55215AA9CA27A5863EC48" \ - "D8E0286B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "007FFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA" \ - "20400EC4557D5ED3E3E7CA5B4B5C83B8" \ - "E01E5FCF")); - params->cofactor = 4; + params->name = ECCurve_SECG_CHAR2_409K1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT409R1: /* Populate params for sect409r1 * (the NIST B-409 curve) */ - params->fieldID.size = 409; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "02000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000000000080000000000000" \ - "00000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0021A5C2C8EE9FEB5C4B9A753B7B476B" \ - "7FD6422EF1F3DD674761FA99D6AC27C8" \ - "A9A197B272822F6CD57A55AA4F50AE31" \ - "7B13545F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "015D4860D088DDB3496B0C6064756260" \ - "441CDE4AF1771D4DB01FFE5B34E59703" \ - "DC255A868A1180515603AEAB60794E54" \ - "BB7996A7" \ - "0061B1CFAB6BE5F32BBFA78324ED106A" \ - "7636B9C5A7BD198D0158AA4F5488D08F" \ - "38514F1FDF4B4F40D2181B3681C364BA" \ - "0273C706")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "01000000000000000000000000000000" \ - "0000000000000000000001E2AAD6A612" \ - "F33307BE5FA47C3C9E052F838164CD37" \ - "D9A21173")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_409R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT571K1: /* Populate params for sect571k1 * (the NIST K-571 curve) */ - params->fieldID.size = 571; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "0000000000000425")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "026EB7A859923FBC82189631F8103FE4" \ - "AC9CA2970012D5D46024804801841CA4" \ - "4370958493B205E647DA304DB4CEB08C" \ - "BBD1BA39494776FB988B47174DCA88C7" \ - "E2945283A01C8972" \ - "0349DC807F4FBF374F4AEADE3BCA9531" \ - "4DD58CEC9F307A54FFC61EFC006D8A2C" \ - "9D4979C0AC44AEA74FBEBBB9F772AEDC" \ - "B620B01A7BA7AF1B320430C8591984F6" \ - "01CD4C143EF1C7A3")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "02000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000131850E1F19A63E4B391A8DB" \ - "917F4138B630D84BE5D639381E91DEB4" \ - "5CFE778F637C1001")); - params->cofactor = 4; + params->name = ECCurve_SECG_CHAR2_571K1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; case SEC_OID_SECG_EC_SECT571R1: /* Populate params for sect571r1 * (the NIST B-571 curve) */ - params->fieldID.size = 571; - params->fieldID.type = ec_field_GF2m; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.poly, - "08000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "00000000000000000000000000000000" \ - "0000000000000425")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "02F40E7E2221F295DE297117B7F3D62F" \ - "5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD" \ - "84FFABBD8EFA59332BE7AD6756A66E29" \ - "4AFD185A78FF12AA520E4DE739BACA0C" \ - "7FFEFF7F2955727A")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0303001D34B856296C16C0D40D3CD775" \ - "0A93D1D2955FA80AA5F40FC8DB7B2ABD" \ - "BDE53950F4C0D293CDD711A35B67FB14" \ - "99AE60038614F1394ABFA3B4C850D927" \ - "E1E7769C8EEC2D19" \ - "037BF27342DA639B6DCCFFFEB73D69D7" \ - "8C6C27A6009CBBCA1980F8533921E8A6" \ - "84423E43BAB08A576291AF8F461BB2A8" \ - "B3531D2F0485C19B16E2F1516E23DD3C" \ - "1A4827AF1B8AC15B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFE661CE18FF55987308059B18" \ - "6823851EC7DD9CA1161DE93D5174D66E" \ - "8382E9BB2FE84E47")); - params->cofactor = 2; + params->name = ECCurve_SECG_CHAR2_571R1; + curveParams = ecCurve_map[params->name]; + GF2M_POPULATE break; +#define GFP_POPULATE \ + if ((params->name < ECCurve_noName) || \ + (params->name > ECCurve_pastLastCurve)) goto cleanup; \ + CHECK_OK(curveParams); \ + params->fieldID.size = curveParams->size; \ + params->fieldID.type = ec_field_GFp; \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, \ + curveParams->irr)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, \ + curveParams->curvea)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, \ + curveParams->curveb)); \ + genenc[0] = '0'; \ + genenc[1] = '4'; \ + genenc[2] = '\0'; \ + CHECK_OK(strcat(genenc, curveParams->genx)); \ + CHECK_OK(strcat(genenc, curveParams->geny)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, \ + genenc)); \ + CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, \ + curveParams->order)); \ + params->cofactor = curveParams->cofactor; + case SEC_OID_ANSIX962_EC_PRIME192V1: /* Populate params for prime192v1 aka secp192r1 * (the NIST P-192 curve) */ - params->fieldID.size = 192; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "64210519E59C80E70FA7E9AB72243049" \ - "FEB8DEECC146B9B1")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "188DA80EB03090F67CBF20EB43A18800" \ - "F4FF0AFD82FF1012" \ - "07192B95FFC8DA78631011ED6B24CDD5" \ - "73F977A11E794811")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836" \ - "146BC9B1B4D22831")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_192V1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_ANSIX962_EC_PRIME192V2: /* Populate params for prime192v2 */ - params->fieldID.size = 192; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "CC22D6DFB95C6B25E49C0D6364A4E598" \ - "0C393AA21668D953")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "EEA2BAE7E1497842F2DE7769CFE9C989" \ - "C072AD696F48034A" \ - "6574D11D69B6EC7A672BB82A083DF2F2" \ - "B0847DE970B2DE15")); - - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724" \ - "DC80418648D8DD31")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_192V2; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_ANSIX962_EC_PRIME192V3: /* Populate params for prime192v3 */ - params->fieldID.size = 192; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "22123DC2395A05CAA7423DAECCC94760" \ - "A7D462256BD56916")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "7D29778100C65A1DA1783716588DCE2B" \ - "8B4AEE8E228F1896" \ - "38A90F22637337334B49DCB66A6DC8F9" \ - "978ACA7648A943B0")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031" \ - "C83F4294F640EC13")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_192V3; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_ANSIX962_EC_PRIME239V1: /* Populate params for prime239v1 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF" \ - "FFFF8000000000007FFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF" \ - "FFFF8000000000007FFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "6B016C3BDCF18941D0D654921475CA71" \ - "A9DB2FB27D1D37796185C2942C0A")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "0FFA963CDCA8816CCC33B8642BEDF905" \ - "C3D358573D3F27FBBD3B3CB9AAAF" \ - "7DEBE8E4E90A5DAE6E4054CA530BA046" \ - "54B36818CE226B39FCCB7B02F1AE")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E" \ - "5E9A9F5D9071FBD1522688909D0B")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_239V1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_ANSIX962_EC_PRIME239V2: /* Populate params for prime239v2 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF" \ - "FFFF8000000000007FFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF" \ - "FFFF8000000000007FFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "617FAB6832576CBBFED50D99F0249C3F" \ - "EE58B94BA0038C7AE84C8C832F2C")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "38AF09D98727705120C921BB5E9E2629" \ - "6A3CDCF2F35757A0EAFD87B830E7" \ - "5B0125E4DBEA0EC7206DA0FC01D9B081" \ - "329FB555DE6EF460237DFF8BE4BA")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "7FFFFFFFFFFFFFFFFFFFFFFF800000CF" \ - "A7E8594377D414C03821BC582063")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_239V2; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_ANSIX962_EC_PRIME239V3: /* Populate params for prime239v3 */ - params->fieldID.size = 239; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF" \ - "FFFF8000000000007FFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF" \ - "FFFF8000000000007FFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "255705FA2A306654B1F4CB03D6A750A3" \ - "0C250102D4988717D9BA15AB6D3E")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "6768AE8E18BB92CFCF005C949AA2C6D9" \ - "4853D0E660BBF854B1C9505FE95A" \ - "1607E6898F390C06BC1D552BAD226F3B" \ - "6FCFE48B6E818499AF18E3ED6CF3")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF97" \ - "5DEB41B3A6057C3C432146526551")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_239V3; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_ANSIX962_EC_PRIME256V1: /* Populate params for prime256v1 aka secp256r1 * (the NIST P-256 curve) */ - params->fieldID.size = 256; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFF000000010000000000000000" \ - "00000000FFFFFFFFFFFFFFFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFF000000010000000000000000" \ - "00000000FFFFFFFFFFFFFFFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "5AC635D8AA3A93E7B3EBBD55769886BC" \ - "651D06B0CC53B0F63BCE3C3E27D2604B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "6B17D1F2E12C4247F8BCE6E563A440F2" \ - "77037D812DEB33A0F4A13945D898C296" \ - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" \ - "2BCE33576B315ECECBB6406837BF51F5")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFF00000000FFFFFFFFFFFFFFFF" \ - "BCE6FAADA7179E84F3B9CAC2FC632551")); - params->cofactor = 1; + params->name = ECCurve_X9_62_PRIME_256V1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP112R1: /* Populate params for secp112r1 */ - params->fieldID.size = 112; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "DB7C2ABF62E35E668076BEAD208B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "DB7C2ABF62E35E668076BEAD2088")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "659EF8BA043916EEDE8911702B22")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "09487239995A5EE76B55F9C2F098" \ - "A89CE5AF8724C0A23E0E0FF77500")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "DB7C2ABF62E35E7628DFAC6561C5")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_112R1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP112R2: /* Populate params for secp112r2 */ - params->fieldID.size = 112; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "DB7C2ABF62E35E668076BEAD208B")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "6127C24C05F38A0AAAF65C0EF02C")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "51DEF1815DB5ED74FCC34C85D709")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "4BA30AB5E892B4E1649DD0928643" \ - "ADCD46F5882E3747DEF36E956E97")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "36DF0AAFD8B8D7597CA10520D04B")); - params->cofactor = 4; + params->name = ECCurve_SECG_PRIME_112R2; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP128R1: /* Populate params for secp128r1 */ - params->fieldID.size = 128; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "E87579C11079F43DD824993C2CEE5ED3")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "161FF7528B899B2D0C28607CA52C5B86" \ - "CF5AC8395BAFEB13C02DA292DDED7A83")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFE0000000075A30D1B9038A115")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_128R1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP128R2: /* Populate params for secp128r2 */ - params->fieldID.size = 128; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "D6031998D1B3BBFEBF59CC9BBFF9AEE1")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "5EEEFCA380D02919DC2C6558BB6D8A5D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "7B6AA5D85E572983E6FB32A7CDEBC140" \ - "27B6916A894D3AEE7106FE805FC34B44")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "3FFFFFFF7FFFFFFFBE0024720613B5A3")); - params->cofactor = 4; + params->name = ECCurve_SECG_PRIME_128R2; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP160K1: /* Populate params for secp160k1 */ - params->fieldID.size = 160; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFAC73")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "07")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "3B4C382CE37AA192A4019E763036F4F5" \ - "DD4D7EBB" \ - "938CF935318FDCED6BC28286531733C3" \ - "F03C4FEE")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0100000000000000000001B8FA16DFAB" \ - "9ACA16B6B3")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_160K1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP160R1: /* Populate params for secp160r1 */ - params->fieldID.size = 160; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "7FFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "7FFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "1C97BEFC54BD7A8B65ACF89F81D4D4AD" \ - "C565FA45")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "4A96B5688EF573284664698968C38BB9" \ - "13CBFC82" \ - "23A628553168947D59DCC91204235137" \ - "7AC5FB32")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0100000000000000000001F4C8F927AE" \ - "D3CA752257")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_160R1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP160R2: /* Populate params for secp160r1 */ - params->fieldID.size = 160; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFAC73")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFAC70")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "B4E134D3FB59EB8BAB57274904664D5A" \ - "F50388BA")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "52DCB034293A117E1F4FF11B30F7199D" \ - "3144CE6D" \ - "FEAFFEF2E331F296E071FA0DF9982CFE" \ - "A7D43F2E")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "0100000000000000000000351EE786A8" \ - "18F3A1A16B")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_160R2; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP192K1: /* Populate params for secp192k1 */ - params->fieldID.size = 192; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFEFFFFEE37")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "03")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "DB4FF10EC057E9AE26B07D0280B7F434" \ - "1DA5D1B1EAE06C7D" \ - "9B2F2F6D9C5628A7844163D015BE8634" \ - "4082AA88D95E2F9D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC17" \ - "0F69466A74DEFD8D")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_192K1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP224K1: /* Populate params for secp224k1 */ - params->fieldID.size = 224; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFEFFFFE56D")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "05")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "A1455B334DF099DF30FC28A169A467E9" \ - "E47075A90F7E650EB6B7A45C" \ - "7E089FED7FBA344282CAFBD6F7E319F7" \ - "C0B0BD59E2CA4BDB556D61A5")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "010000000000000000000000000001DC" \ - "E8D2EC6184CAF0A971769FB1F7")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_224K1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP224R1: /* Populate params for secp224r1 * (the NIST P-224 curve) */ - params->fieldID.size = 224; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "000000000000000000000001")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFFFFFFFFFFFFFFFFFE")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "B4050A850C04B3ABF54132565044B0B7" \ - "D7BFD8BA270B39432355FFB4")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "B70E0CBD6BB4BF7F321390B94A03C1D3" \ - "56C21122343280D6115C1D21" \ - "BD376388B5F723FB4C22DFE6CD4375A0" \ - "5A07476444D5819985007E34")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2" \ - "E0B8F03E13DD29455C5C2A3D")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_224R1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP256K1: /* Populate params for secp256k1 */ - params->fieldID.size = 256; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "07")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "79BE667EF9DCBBAC55A06295CE870B07" \ - "029BFCDB2DCE28D959F2815B16F81798" \ - "483ADA7726A3C4655DA4FBFC0E1108A8" \ - "FD17B448A68554199C47D08FFB10D4B8")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "BAAEDCE6AF48A03BBFD25E8CD0364141")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_256K1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP384R1: /* Populate params for secp384r1 * (the NIST P-384 curve) */ - params->fieldID.size = 384; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFF0000000000000000FFFFFFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE" \ - "FFFFFFFF0000000000000000FFFFFFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "B3312FA7E23EE7E4988E056BE3F82D19" \ - "181D9C6EFE8141120314088F5013875A" \ - "C656398D8A2ED19D2A85C8EDD3EC2AEF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "AA87CA22BE8B05378EB1C71EF320AD74" \ - "6E1D3B628BA79B9859F741E082542A38" \ - "5502F25DBF55296C3A545E3872760AB7" \ - "3617DE4A96262C6F5D9E98BF9292DC29" \ - "F8F41DBD289A147CE9DA3113B5F0B8C0" \ - "0A60B1CE1D7E819D7A431D7C90EA0E5F")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFC7634D81F4372DDF" \ - "581A0DB248B0A77AECEC196ACCC52973")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_384R1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; case SEC_OID_SECG_EC_SECP521R1: /* Populate params for secp521r1 * (the NIST P-521 curve) */ - params->fieldID.size = 521; - params->fieldID.type = ec_field_GFp; - CHECK_OK(hexString2SECItem(params->arena, ¶ms->fieldID.u.prime, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFF")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.a, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFC")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->curve.b, - "0051953EB9618E1C9A1F929A21A0B685" \ - "40EEA2DA725B99B315F3B8B489918EF1" \ - "09E156193951EC7E937B1652C0BD3BB1" \ - "BF073573DF883D2C34F1EF451FD46B50" \ - "3F00")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->base, - "04" \ - "00C6858E06B70404E9CD9E3ECB662395" \ - "B4429C648139053FB521F828AF606B4D" \ - "3DBAA14B5E77EFE75928FE1DC127A2FF" \ - "A8DE3348B3C1856A429BF97E7E31C2E5" \ - "BD66" \ - "011839296A789A3BC0045C8A5FB42C7D" \ - "1BD998F54449579B446817AFBD17273E" \ - "662C97EE72995EF42640C550B9013FAD" \ - "0761353C7086A272C24088BE94769FD1" \ - "6650")); - CHECK_OK(hexString2SECItem(params->arena, ¶ms->order, - "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" \ - "FFFA51868783BF2F966B7FCC0148F709" \ - "A5D03BB5C9B8899C47AEBB6FB71E9138" \ - "6409")); - params->cofactor = 1; + params->name = ECCurve_SECG_PRIME_521R1; + curveParams = ecCurve_map[params->name]; + GFP_POPULATE break; default: diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 81eeda899bda..93470e681b3f 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -32,7 +36,7 @@ * * Private Key Database code * - * $Id: keydb.c,v 1.33 2003/01/09 18:15:09 relyea%netscape.com Exp $ + * $Id: keydb.c,v 1.34 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #include "lowkeyi.h" @@ -51,6 +55,12 @@ #include "keydbi.h" +#ifdef NSS_ENABLE_ECC +extern SECStatus EC_FillParams(PRArenaPool *arena, + const SECItem *encodedParams, + ECParams *params); +#endif + /* * Record keys for keydb */ @@ -1195,6 +1205,12 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer namekey.data = pubkey->u.dh.publicValue.data; namekey.size = pubkey->u.dh.publicValue.len; break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + namekey.data = pubkey->u.ec.publicValue.data; + namekey.size = pubkey->u.ec.publicValue.len; + break; +#endif /* NSS_ENABLE_ECC */ default: /* XXX We don't do Fortezza or DH yet. */ return PR_FALSE; @@ -1483,11 +1499,24 @@ seckey_rc4_decode(SECItem *key, SECItem *src) return dest; } + +#ifdef EC_DEBUG +#define SEC_PRINT(str1, str2, num, sitem) \ + printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ + str1, str2, num, sitem->len); \ + for (i = 0; i < sitem->len; i++) { \ + printf("%02x:", sitem->data[i]); \ + } \ + printf("\n") +#else +#define SEC_PRINT(a, b, c, d) +#endif /* EC_DEBUG */ + /* TNH - keydb is unused */ /* TNH - the pwitem should be the derived key for RC4 */ NSSLOWKEYEncryptedPrivateKeyInfo * seckey_encrypt_private_key( - NSSLOWKEYPrivateKey *pk, SECItem *pwitem, NSSLOWKEYDBHandle *keydb, + NSSLOWKEYPrivateKey *pk, SECItem *pwitem, NSSLOWKEYDBHandle *keydb, SECOidTag algorithm, SECItem **salt) { NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; @@ -1498,6 +1527,11 @@ seckey_encrypt_private_key( NSSPKCS5PBEParameter *param = NULL; SECItem *dummy = NULL, *dest = NULL; SECAlgorithmID *algid; +#ifdef NSS_ENABLE_ECC + SECItem *fordebug = NULL; + int savelen; + int i; +#endif *salt = NULL; permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); @@ -1582,6 +1616,46 @@ seckey_encrypt_private_key( goto loser; } break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + prepare_low_ec_priv_key_for_asn1(pk); + /* Public value is encoded as a bit string so adjust length + * to be in bits before ASN encoding and readjust + * immediately after. + * + * Since the SECG specification recommends not including the + * parameters as part of ECPrivateKey, we zero out the curveOID + * length before encoding and restore it later. + */ + pk->u.ec.publicValue.len <<= 3; + savelen = pk->u.ec.ecParams.curveOID.len; + pk->u.ec.ecParams.curveOID.len = 0; + dummy = SEC_ASN1EncodeItem(temparena, &(pki->privateKey), pk, + nsslowkey_ECPrivateKeyTemplate); + pk->u.ec.ecParams.curveOID.len = savelen; + pk->u.ec.publicValue.len >>= 3; + + if (dummy == NULL) { + rv = SECFailure; + goto loser; + } + + dummy = &pk->u.ec.ecParams.DEREncoding; + + /* At this point dummy should contain the encoded params */ + rv = SECOID_SetAlgorithmID(temparena, &(pki->algorithm), + SEC_OID_ANSIX962_EC_PUBLIC_KEY, dummy); + + if (rv == SECFailure) { + goto loser; + } + + fordebug = &(pki->privateKey); + SEC_PRINT("seckey_encrypt_private_key()", "PrivateKey", + pk->keyType, fordebug); + + break; +#endif /* NSS_ENABLE_ECC */ default: /* We don't support DH or Fortezza private keys yet */ PORT_Assert(PR_FALSE); @@ -1591,6 +1665,10 @@ seckey_encrypt_private_key( /* setup encrypted private key info */ dummy = SEC_ASN1EncodeItem(temparena, der_item, pki, nsslowkey_PrivateKeyInfoTemplate); + + SEC_PRINT("seckey_encrypt_private_key()", "PrivateKeyInfo", + pk->keyType, der_item); + if(dummy == NULL) { rv = SECFailure; goto loser; @@ -1749,6 +1827,11 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, PLArenaPool *temparena = NULL, *permarena = NULL; SECItem *salt = NULL, *dest = NULL, *key = NULL; NSSPKCS5PBEParameter *param; +#ifdef NSS_ENABLE_ECC + ECPrivateKey *ecpriv; + SECItem *fordebug = NULL; + int i; +#endif if((epki == NULL) || (pwitem == NULL)) goto loser; @@ -1805,6 +1888,9 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, if(dest != NULL) { + SEC_PRINT("seckey_decrypt_private_key()", "PrivateKeyInfo", -1, + dest); + rv = SEC_ASN1DecodeItem(temparena, pki, nsslowkey_PrivateKeyInfoTemplate, dest); if(rv == SECSuccess) @@ -1838,6 +1924,58 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, nsslowkey_DHPrivateKeyTemplate, &pki->privateKey); break; +#ifdef NSS_ENABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + pk->keyType = NSSLOWKEYECKey; + prepare_low_ec_priv_key_for_asn1(pk); + + fordebug = &pki->privateKey; + SEC_PRINT("seckey_decrypt_private_key()", "PrivateKey", + pk->keyType, fordebug); + rv = SEC_ASN1DecodeItem(permarena, pk, + nsslowkey_ECPrivateKeyTemplate, + &pki->privateKey); + if (rv != SECSuccess) + goto loser; + + prepare_low_ecparams_for_asn1(&pk->u.ec.ecParams); + + rv = SECITEM_CopyItem(permarena, + &pk->u.ec.ecParams.DEREncoding, + &pki->algorithm.parameters); + + if (rv != SECSuccess) + goto loser; + + /* Fill out the rest of EC params */ + rv = EC_FillParams(permarena, &pk->u.ec.ecParams.DEREncoding, + &pk->u.ec.ecParams); + + /* + * NOTE: Encoding of the publicValue is optional + * so we need to be able to regenerate the publicValue + * from the base point and the private key. + * + * XXX This part of the code needs more testing. + */ + if (pk->u.ec.publicValue.len == 0) { + rv = EC_NewKeyFromSeed(&pk->u.ec.ecParams, + &ecpriv, pk->u.ec.privateValue.data, + pk->u.ec.privateValue.len); + if (rv == SECSuccess) { + SECITEM_CopyItem(permarena, &pk->u.ec.publicValue, + &(ecpriv->publicValue)); + PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); + } + } else { + /* If publicValue was filled as part of DER decoding, + * change length in bits to length in bytes. + */ + pk->u.ec.publicValue.len >>= 3; + } + + break; +#endif /* NSS_ENABLE_ECC */ default: rv = SECFailure; break; @@ -2411,6 +2549,12 @@ ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, newkey.data = privkey->u.dh.publicValue.data; newkey.size = privkey->u.dh.publicValue.len; break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + newkey.data = privkey->u.ec.publicValue.data; + newkey.size = privkey->u.ec.publicValue.len; + break; +#endif /* NSS_ENABLE_ECC */ default: /* should we continue here and loose the key? */ PORT_SetError(SEC_ERROR_BAD_DATABASE); diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c index 210f86b51164..3c9300d96e29 100644 --- a/security/nss/lib/softoken/lowcert.c +++ b/security/nss/lib/softoken/lowcert.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -34,7 +38,7 @@ /* * Certificate handling code * - * $Id: lowcert.c,v 1.15 2003/09/19 04:08:50 jpierre%netscape.com Exp $ + * $Id: lowcert.c,v 1.16 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #include "seccomon.h" @@ -47,6 +51,12 @@ #include "secasn1.h" #include "secoid.h" +#ifdef NSS_ENABLE_ECC +extern SECStatus EC_FillParams(PRArenaPool *arena, + const SECItem *encodedParams, + ECParams *params); +#endif + static const SEC_ASN1Template nsslowcert_SubjectPublicKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWCERTSubjectPublicKeyInfo) }, { SEC_ASN1_INLINE, offsetof(NSSLOWCERTSubjectPublicKeyInfo,algorithm), @@ -582,6 +592,28 @@ nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *cert) nsslowcert_DHPublicKeyTemplate, &os); if (rv == SECSuccess) return pubk; break; +#ifdef NSS_ENABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + pubk->keyType = NSSLOWKEYECKey; + /* Since PKCS#11 directly takes the DER encoding of EC params + * and public value, we don't need any decoding here. + */ + rv = SECITEM_CopyItem(arena, &pubk->u.ec.ecParams.DEREncoding, + &spki.algorithm.parameters); + if ( rv != SECSuccess ) + break; + + /* Fill out the rest of the ecParams structure + * based on the encoded params + */ + if (EC_FillParams(arena, &pubk->u.ec.ecParams.DEREncoding, + &pubk->u.ec.ecParams) != SECSuccess) + break; + + rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, &os); + if (rv == SECSuccess) return pubk; + break; +#endif /* NSS_ENABLE_ECC */ default: rv = SECFailure; break; diff --git a/security/nss/lib/softoken/lowkey.c b/security/nss/lib/softoken/lowkey.c index 1e3c6144bb82..0b36b6e4a4a0 100644 --- a/security/nss/lib/softoken/lowkey.c +++ b/security/nss/lib/softoken/lowkey.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -39,6 +43,11 @@ #include "pcert.h" #include "secerr.h" +#ifdef NSS_ENABLE_ECC +extern SECStatus EC_CopyParams(PRArenaPool *arena, + ECParams *dstParams, + const ECParams *srcParams); +#endif const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) }, @@ -83,6 +92,54 @@ const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = { { 0, } }; +#ifdef NSS_ENABLE_ECC + +/* XXX This is just a placeholder for later when we support + * generic curves and need full-blown support for parsing EC + * parameters. For now, we only support named curves in which + * EC params are simply encoded as an object ID and we don't + * use nsslowkey_ECParamsTemplate. + */ +const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = { + { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) }, + { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named }, + { 0, } +}; + + +/* NOTE: The SECG specification allows the private key structure + * to contain curve parameters but recommends that they be stored + * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo + * instead. + */ +const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) }, + { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) }, + { SEC_ASN1_OCTET_STRING, + offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) }, + /* XXX The following template works for now since we only + * support named curves for which the parameters are + * encoded as an object ID. When we support generic curves, + * we'll need to define nsslowkey_ECParamsTemplate + */ +#if 1 + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID), + SEC_ObjectIDTemplate }, +#else + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams), + nsslowkey_ECParamsTemplate }, +#endif + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | + SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1, + offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue), + SEC_BitStringTemplate }, + { 0, } +}; +#endif /* NSS_ENABLE_ECC */ /* * See bugzilla bug 125359 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints, @@ -138,6 +195,25 @@ prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) key->u.dh.privateValue.type = siUnsignedInteger; } +#ifdef NSS_ENABLE_ECC +void +prepare_low_ecparams_for_asn1(ECParams *params) +{ + params->DEREncoding.type = siUnsignedInteger; + params->curveOID.type = siUnsignedInteger; +} + +void +prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key) +{ + key->u.ec.version.type = siUnsignedInteger; + key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger; + key->u.ec.ecParams.curveOID.type = siUnsignedInteger; + key->u.ec.privateValue.type = siUnsignedInteger; + key->u.ec.publicValue.type = siUnsignedInteger; +} +#endif /* NSS_ENABLE_ECC */ + void nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk) { @@ -265,6 +341,26 @@ nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk) if (rv == SECSuccess) return pubk; } break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena, + sizeof(NSSLOWKEYPublicKey)); + if (pubk != NULL) { + SECStatus rv; + + pubk->arena = arena; + pubk->keyType = privk->keyType; + rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue, + &privk->u.ec.publicValue); + if (rv != SECSuccess) break; + pubk->u.ec.ecParams.arena = arena; + /* Copy the rest of the params */ + rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams), + &(privk->u.ec.ecParams)); + if (rv == SECSuccess) return pubk; + } + break; +#endif /* NSS_ENABLE_ECC */ /* No Fortezza in Low Key implementations (Fortezza keys aren't * stored in our data base */ default: @@ -363,6 +459,24 @@ nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey) &(privKey->u.dh.base)); if(rv != SECSuccess) break; break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version), + &(privKey->u.ec.version)); + if(rv != SECSuccess) break; + rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue), + &(privKey->u.ec.publicValue)); + if(rv != SECSuccess) break; + rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue), + &(privKey->u.ec.privateValue)); + if(rv != SECSuccess) break; + returnKey->u.ec.ecParams.arena = poolp; + /* Copy the rest of the params */ + rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams), + &(privKey->u.ec.ecParams)); + if (rv != SECSuccess) break; + break; +#endif /* NSS_ENABLE_ECC */ default: rv = SECFailure; } diff --git a/security/nss/lib/softoken/lowkeyi.h b/security/nss/lib/softoken/lowkeyi.h index 9c8055387b41..3092186178ab 100644 --- a/security/nss/lib/softoken/lowkeyi.h +++ b/security/nss/lib/softoken/lowkeyi.h @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -32,7 +36,7 @@ * * key.h - public data structures and prototypes for the private key library * - * $Id: lowkeyi.h,v 1.7 2002/09/27 17:46:36 relyea%netscape.com Exp $ + * $Id: lowkeyi.h,v 1.8 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #ifndef _LOWKEYI_H_ @@ -59,6 +63,10 @@ extern void prepare_low_pqg_params_for_asn1(PQGParams *params); extern void prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key); extern void prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key); extern void prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key); +#ifdef NSS_ENABLE_ECC +extern void prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key); +extern void prepare_low_ecparams_for_asn1(ECParams *params); +#endif /* NSS_ENABLE_ECC */ typedef char * (* NSSLOWKEYDBNameFunc)(void *arg, int dbVersion); diff --git a/security/nss/lib/softoken/lowkeyti.h b/security/nss/lib/softoken/lowkeyti.h index 938686a06359..933ad051b9db 100644 --- a/security/nss/lib/softoken/lowkeyti.h +++ b/security/nss/lib/softoken/lowkeyti.h @@ -78,6 +78,11 @@ extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[]; extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[]; extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[]; extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[]; +#ifdef NSS_ENABLE_ECC +#define NSSLOWKEY_EC_PRIVATE_KEY_VERSION 1 /* as per SECG 1 C.4 */ +extern const SEC_ASN1Template nsslowkey_ECParamsTemplate[]; +extern const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[]; +#endif /* NSS_ENABLE_ECC */ extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[]; extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[]; diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index baf114426039..b73d4f8bf557 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -80,3 +80,8 @@ CSRCS = \ softkver.c \ tlsprf.c \ $(NULL) + +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index aec85f0e048d..c6db2072a671 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -1068,6 +1068,7 @@ pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object, if ( !pk11_hasAttribute(object, CKA_EC_POINT)) { return CKR_TEMPLATE_INCOMPLETE; } + pubKeyAttr = CKA_EC_POINT; derive = CK_TRUE; /* for ECDH */ verify = CK_TRUE; /* for ECDSA */ encrypt = CK_FALSE; @@ -1219,6 +1220,9 @@ pk11_handlePrivateKeyObject(PK11Session *session,PK11Object *object,CK_KEY_TYPE if ( !pk11_hasAttribute(object, CKA_VALUE)) { return CKR_TEMPLATE_INCOMPLETE; } + if ( !pk11_hasAttribute(object, CKA_NETSCAPE_DB)) { + return CKR_TEMPLATE_INCOMPLETE; + } encrypt = CK_FALSE; recover = CK_FALSE; wrap = CK_FALSE; @@ -1989,10 +1993,12 @@ pk11_mkPrivKey(PK11Object *object, CK_KEY_TYPE key_type, CK_RV *crvp) crv = pk11_Attribute2SSecItem(arena,&privKey->u.ec.privateValue, object,CKA_VALUE); if (crv != CKR_OK) break; - /* XXX Why does this break handlePrivateKeyObject ? - crv = pk11_Attribute2SSecItem(arena,&privKey->u.ec.publicValue, + crv = pk11_Attribute2SSecItem(arena, &privKey->u.ec.publicValue, object,CKA_NETSCAPE_DB); - */ + if (crv != CKR_OK) break; + rv = DER_SetUInteger(privKey->arena, &privKey->u.ec.version, + NSSLOWKEY_EC_PRIVATE_KEY_VERSION); + if (rv != SECSuccess) crv = CKR_HOST_MEMORY; break; #endif /* NSS_ENABLE_ECC */ diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index 970b292cfccf..a8061ab30777 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -98,6 +98,17 @@ static void pk11_Null(void *data, PRBool freeit) #ifdef NSS_ENABLE_ECC extern SECStatus EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); +#ifdef EC_DEBUG +#define SEC_PRINT(str1, str2, num, sitem) \ + printf("pkcs11c.c:%s:%s (keytype=%d) [len=%d]\n", \ + str1, str2, num, sitem->len); \ + for (i = 0; i < sitem->len; i++) { \ + printf("%02x:", sitem->data[i]); \ + } \ + printf("\n") +#else +#define SEC_PRINT(a, b, c, d) +#endif #endif /* NSS_ENABLE_ECC */ /* @@ -3223,6 +3234,7 @@ dhgn_done: case CKM_EC_KEY_PAIR_GEN: pk11_DeleteAttributeType(privateKey,CKA_EC_PARAMS); pk11_DeleteAttributeType(privateKey,CKA_VALUE); + pk11_DeleteAttributeType(privateKey,CKA_NETSCAPE_DB); key_type = CKK_EC; /* extract the necessary parameters and copy them to private keys */ @@ -3257,7 +3269,10 @@ dhgn_done: crv = pk11_AddAttributeType(privateKey, CKA_VALUE, pk11_item_expand(&ecPriv->privateValue)); + if (crv != CKR_OK) goto ecgn_done; + crv = pk11_AddAttributeType(privateKey,CKA_NETSCAPE_DB, + pk11_item_expand(&ecPriv->publicValue)); ecgn_done: /* should zeroize, since this function doesn't. */ PORT_FreeArena(ecPriv->ecParams.arena, PR_TRUE); @@ -3360,6 +3375,11 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key, CK_RV *crvp) void *dummy, *param = NULL; SECStatus rv = SECSuccess; SECItem *encodedKey = NULL; +#ifdef NSS_ENABLE_ECC + SECItem *fordebug; + int savelen; + int i; +#endif` if(!key) { *crvp = CKR_KEY_HANDLE_INVALID; /* really can't happen */ @@ -3411,6 +3431,34 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key, CK_RV *crvp) nsslowkey_PQGParamsTemplate); algorithm = SEC_OID_ANSIX9_DSA_SIGNATURE; break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + prepare_low_ec_priv_key_for_asn1(lk); + /* Public value is encoded as a bit string so adjust length + * to be in bits before ASN encoding and readjust + * immediately after. + * + * Since the SECG specification recommends not including the + * parameters as part of ECPrivateKey, we zero out the curveOID + * length before encoding and restore it later. + */ + lk->u.ec.publicValue.len <<= 3; + savelen = lk->u.ec.ecParams.curveOID.len; + lk->u.ec.ecParams.curveOID.len = 0; + dummy = SEC_ASN1EncodeItem(arena, &pki->privateKey, lk, + nsslowkey_ECPrivateKeyTemplate); + lk->u.ec.ecParams.curveOID.len = savelen; + lk->u.ec.publicValue.len >>= 3; + + fordebug = &pki->privateKey; + SEC_PRINT("pk11_PackagePrivateKey()", "PrivateKey", lk->keyType, + fordebug); + + param = SECITEM_DupItem(&lk->u.ec.ecParams.DEREncoding); + + algorithm = SEC_OID_ANSIX962_EC_PUBLIC_KEY; + break; +#endif /* NSS_ENABLE_ECC */ case NSSLOWKEYDHKey: default: dummy = NULL; @@ -3422,7 +3470,7 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key, CK_RV *crvp) rv = SECFailure; goto loser; } - + rv = SECOID_SetAlgorithmID(arena, &pki->algorithm, algorithm, (SECItem*)param); if(rv != SECSuccess) { @@ -3443,6 +3491,11 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key, CK_RV *crvp) nsslowkey_PrivateKeyInfoTemplate); *crvp = encodedKey ? CKR_OK : CKR_DEVICE_ERROR; +#ifdef NSS_ENABLE_ECC + fordebug = encodedKey; + SEC_PRINT("pk11_PackagePrivateKey()", "PrivateKeyInfo", lk->keyType, + fordebug); +#endif loser: if(arena) { PORT_FreeArena(arena, PR_TRUE); @@ -3640,6 +3693,16 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) prepare_low_pqg_params_for_asn1(&lpk->u.dsa.params); break; /* case NSSLOWKEYDHKey: */ +#ifdef NSS_ENABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + keyTemplate = nsslowkey_ECPrivateKeyTemplate; + paramTemplate = NULL; + paramDest = &(lpk->u.ec.ecParams.DEREncoding); + lpk->keyType = NSSLOWKEYECKey; + prepare_low_ec_priv_key_for_asn1(lpk); + prepare_low_ecparams_for_asn1(&lpk->u.ec.ecParams); + break; +#endif /* NSS_ENABLE_ECC */ default: keyTemplate = NULL; paramTemplate = NULL; @@ -3653,6 +3716,20 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) /* decode the private key and any algorithm parameters */ rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); + +#ifdef NSS_ENABLE_ECC + if (lpk->keyType == NSSLOWKEYECKey) { + /* convert length in bits to length in bytes */ + lpk->u.ec.publicValue.len >>= 3; + rv = SECITEM_CopyItem(arena, + &(lpk->u.ec.ecParams.DEREncoding), + &(pki->algorithm.parameters)); + if(rv != SECSuccess) { + goto loser; + } + } +#endif /* NSS_ENABLE_ECC */ + if(rv != SECSuccess) { goto loser; } @@ -3746,6 +3823,33 @@ pk11_unwrapPrivateKey(PK11Object *key, SECItem *bpki) break; #endif /* what about fortezza??? */ +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + keyType = CKK_EC; + crv = (pk11_hasAttribute(key, CKA_NETSCAPE_DB)) ? CKR_OK : + CKR_KEY_TYPE_INCONSISTENT; + if(crv != CKR_OK) break; + crv = pk11_AddAttributeType(key, CKA_KEY_TYPE, &keyType, + sizeof(keyType)); + if(crv != CKR_OK) break; + crv = pk11_AddAttributeType(key, CKA_SIGN, &cktrue, + sizeof(CK_BBOOL)); + if(crv != CKR_OK) break; + crv = pk11_AddAttributeType(key, CKA_SIGN_RECOVER, &cktrue, + sizeof(CK_BBOOL)); + if(crv != CKR_OK) break; + crv = pk11_AddAttributeType(key, CKA_DERIVE, &cktrue, + sizeof(CK_BBOOL)); + if(crv != CKR_OK) break; + crv = pk11_AddAttributeType(key, CKA_EC_PARAMS, + pk11_item_expand(&lpk->u.ec.ecParams.DEREncoding)); + if(crv != CKR_OK) break; + crv = pk11_AddAttributeType(key, CKA_VALUE, + pk11_item_expand(&lpk->u.ec.privateValue)); + if(crv != CKR_OK) break; + /* XXX Do we need to decode the EC Params here ?? */ + break; +#endif /* NSS_ENABLE_ECC */ default: crv = CKR_KEY_TYPE_INCONSISTENT; break; @@ -4931,31 +5035,12 @@ key_and_mac_derive_fail: { SECItem ecScalar, ecPoint; SECItem tmp; - ECParams *ecParams; PRBool withCofactor = PR_FALSE; unsigned char secret_hash[20]; unsigned char *secret; int secretlen; CK_ECDH1_DERIVE_PARAMS *mechParams; - - /* get params and value attributes */ - crv = pk11_Attribute2SecItem(NULL, &tmp, sourceKey, - CKA_EC_PARAMS); - if (crv != CKR_OK) break; - crv = pk11_Attribute2SecItem(NULL, &ecScalar, sourceKey, CKA_VALUE); - if (crv != CKR_OK) { - PORT_Free(tmp.data); - break; - } - - /* Check elliptic curve parameters */ - rv = EC_DecodeParams(&tmp, &ecParams); - PORT_Free(tmp.data); - if (rv != SECSuccess) { - crv = CKR_TEMPLATE_INCONSISTENT; - PORT_Free(ecScalar.data); - break; - } + NSSLOWKEYPrivateKey *privKey; /* Check mechanism parameters */ mechParams = (CK_ECDH1_DERIVE_PARAMS *) pMechanism->pParameter; @@ -4964,11 +5049,17 @@ key_and_mac_derive_fail: ((mechParams->ulSharedDataLen != 0) || (mechParams->pSharedData != NULL)))) { crv = CKR_MECHANISM_PARAM_INVALID; - PORT_FreeArena(ecParams->arena, PR_TRUE); - PORT_Free(ecScalar.data); break; } + privKey = pk11_GetPrivKey(sourceKey, CKK_EC, &crv); + if (privKey == NULL) { + break; + } + + /* Now we are working with a non-NULL private key */ + SECITEM_CopyItem(NULL, &ecScalar, &privKey->u.ec.privateValue); + ecPoint.data = mechParams->pPublicData; ecPoint.len = mechParams->ulPublicDataLen; @@ -4979,18 +5070,21 @@ key_and_mac_derive_fail: * validate the public key to avoid small subgroup * attacks. */ - if (EC_ValidatePublicKey(ecParams, &ecPoint) != SECSuccess) { + if (EC_ValidatePublicKey(&privKey->u.ec.ecParams, &ecPoint) + != SECSuccess) { crv = CKR_ARGUMENTS_BAD; - PORT_FreeArena(ecParams->arena, PR_TRUE); PORT_Free(ecScalar.data); + if (privKey != sourceKey->objectInfo) + nsslowkey_DestroyPrivateKey(privKey); break; } } - rv = ECDH_Derive(&ecPoint, ecParams, &ecScalar, + rv = ECDH_Derive(&ecPoint, &privKey->u.ec.ecParams, &ecScalar, withCofactor, &tmp); - PORT_FreeArena(ecParams->arena, PR_TRUE); PORT_Free(ecScalar.data); + if (privKey != sourceKey->objectInfo) + nsslowkey_DestroyPrivateKey(privKey); if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index bb5245b62580..22dadce7a734 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -16,7 +16,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -463,6 +467,11 @@ pk11_GetPubItem(NSSLOWKEYPublicKey *pubKey) { case NSSLOWKEYDHKey: pubItem = &pubKey->u.dh.publicValue; break; +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + pubItem = &pubKey->u.ec.publicValue; + break; +#endif /* NSS_ENABLE_ECC */ default: break; } @@ -578,6 +587,44 @@ pk11_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) return NULL; } +#ifdef NSS_ENABLE_ECC +static PK11Attribute * +pk11_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_EC; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash, key->u.ec.publicValue.data, + key->u.ec.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + case CKA_VERIFY: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_ENCRYPT: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_EC_PARAMS: + /* XXX Why is the last arg PR_FALSE? */ + return pk11_NewTokenAttributeSigned(type, + key->u.ec.ecParams.DEREncoding.data, + key->u.ec.ecParams.DEREncoding.len, + PR_FALSE); + case CKA_EC_POINT: + /* XXX Why is the last arg PR_FALSE? */ + return pk11_NewTokenAttributeSigned(type,key->u.ec.publicValue.data, + key->u.ec.publicValue.len, PR_FALSE); + default: + break; + } + return NULL; +} +#endif /* NSS_ENABLE_ECC */ + static PK11Attribute * pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { @@ -619,6 +666,10 @@ pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return pk11_FindDSAPublicKeyAttribute(key,type); case NSSLOWKEYDHKey: return pk11_FindDHPublicKeyAttribute(key,type); +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + return pk11_FindECPublicKeyAttribute(key,type); +#endif /* NSS_ENABLE_ECC */ default: break; } @@ -797,6 +848,41 @@ pk11_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) return NULL; } +#ifdef NSS_ENABLE_ECC +static PK11Attribute * +pk11_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_EC; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + case CKA_SIGN: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_DECRYPT: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_EC_PARAMS: + /* XXX Why is the last arg PR_FALSE? */ + return pk11_NewTokenAttributeSigned(type, + key->u.ec.ecParams.DEREncoding.data, + key->u.ec.ecParams.DEREncoding.len, + PR_FALSE); + default: + break; + } + return NULL; +} +#endif /* NSS_ENABLE_ECC */ + static PK11Attribute * pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { @@ -838,6 +924,10 @@ pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return pk11_FindDSAPrivateKeyAttribute(key,type); case NSSLOWKEYDHKey: return pk11_FindDHPrivateKeyAttribute(key,type); +#ifdef NSS_ENABLE_ECC + case NSSLOWKEYECKey: + return pk11_FindECPrivateKeyAttribute(key,type); +#endif /* NSS_ENABLE_ECC */ default: break; } diff --git a/security/nss/lib/ssl/manifest.mn b/security/nss/lib/ssl/manifest.mn index ae6431a2746f..c3720aeb54c7 100644 --- a/security/nss/lib/ssl/manifest.mn +++ b/security/nss/lib/ssl/manifest.mn @@ -79,5 +79,9 @@ CSRCS = \ REQUIRES = dbm +ifdef NSS_ENABLE_ECC +DEFINES += -DNSS_ENABLE_ECC +endif + LIBRARY_NAME = ssl LIBRARY_VERSION = 3 diff --git a/security/nss/lib/ssl/nsskea.c b/security/nss/lib/ssl/nsskea.c index 337d782cf23a..511fb0e9448d 100644 --- a/security/nss/lib/ssl/nsskea.c +++ b/security/nss/lib/ssl/nsskea.c @@ -18,7 +18,11 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * + * Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 + * Sun Microsystems, Inc. All Rights Reserved. + * * Contributor(s): + * Dr Vipul Gupta , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -32,7 +36,7 @@ * may use your version of this file under either the MPL or the * GPL. * - # $Id: nsskea.c,v 1.1 2000/03/31 19:32:56 relyea%netscape.com Exp $ + # $Id: nsskea.c,v 1.2 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #include "cert.h" @@ -63,6 +67,11 @@ NSS_FindCertKEAType(CERTCertificate * cert) case SEC_OID_X942_DIFFIE_HELMAN_KEY: keaType = kt_dh; break; +#ifdef NSS_ENABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + keaType = kt_ecdh; + break; +#endif /* NSS_ENABLE_ECC */ default: keaType = kt_null; } diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index e7db612ad9b9..5930996c48d5 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -23,7 +23,8 @@ * * Contributor(s): * Dr Stephen Henson - * Dr Vipul Gupta , Sun Microsystems Laboratories + * Dr Vipul Gupta and + * Douglas Stebila , Sun Microsystems Laboratories * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -37,7 +38,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: ssl3con.c,v 1.57 2003/10/07 02:24:01 nelsonb%netscape.com Exp $ + * $Id: ssl3con.c,v 1.58 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #include "nssrenam.h" @@ -171,6 +172,9 @@ static const int compressionMethodsCount = static const /*SSL3ClientCertificateType */ uint8 certificate_types [] = { ct_RSA_sign, ct_DSS_sign, +#ifdef NSS_ENABLE_ECC + ct_ECDSA_sign, +#endif /* NSS_ENABLE_ECC */ }; static const /*SSL3ClientCertificateType */ uint8 fortezza_certificate_types [] = { @@ -649,6 +653,15 @@ ssl3_config_match_init(sslSocket *ss) case kea_dhe_rsa: svrAuth = ss->serverCerts + kt_rsa; break; + case kea_ecdh_ecdsa: + case kea_ecdh_rsa: + /* + * XXX We ought to have different indices for + * ECDSA- and RSA-signed EC certificates so + * we could support both key exchange mechanisms + * simultaneously. For now, both of them use + * whatever is in the certificate slot for kt_ecdh + */ default: svrAuth = ss->serverCerts + exchKeyType; break; @@ -830,6 +843,13 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf, hashItem.data = hash->sha; hashItem.len = sizeof(hash->sha); break; +#ifdef NSS_ENABLE_ECC + case ecKey: + doDerEncode = PR_TRUE; + hashItem.data = hash->sha; + hashItem.len = sizeof(hash->sha); + break; +#endif /* NSS_ENABLE_ECC */ default: PORT_SetError(SEC_ERROR_INVALID_KEY); goto done; @@ -842,7 +862,8 @@ ssl3_SignHashes(SSL3Hashes *hash, SECKEYPrivateKey *key, SECItem *buf, } else if (doDerEncode) { SECItem derSig = {siBuffer, NULL, 0}; - rv = DSAU_EncodeDerSig(&derSig, buf); + /* This also works for an ECDSA signature */ + rv = DSAU_EncodeDerSigWithLen(&derSig, buf, (unsigned) signatureLen); if (rv == SECSuccess) { PORT_Free(buf->data); /* discard unencoded signature. */ *buf = derSig; /* give caller encoded signature. */ @@ -870,7 +891,7 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, SECStatus rv; SECItem hashItem; #ifdef NSS_ENABLE_ECC - int len; + unsigned int len; #endif /* NSS_ENABLE_ECC */ @@ -918,24 +939,11 @@ ssl3_VerifySignedHashes(SSL3Hashes *hash, CERTCertificate *cert, PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); return SECFailure; } - signature = SECITEM_AllocItem(NULL, NULL, len); - /* XXX Use a better decoder */ - if ((buf->len < len + 6) || - (buf->data[0] != 0x30) || /* must start with a SEQUENCE */ - (buf->data[1] != buf->len - 2) || - (buf->data[2] != 0x02) || /* 1st INTEGER, r */ - (buf->data[3] < len/2) || - (buf->data[4 + buf->data[3]] != 0x02) || /* 2nd INTEGER, s */ - (buf->data[5 + buf->data[3]] < len/2)) { - PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); - SECITEM_FreeItem(signature, PR_TRUE); - return SECFailure; + signature = DSAU_DecodeDerSigToLen(buf, len); + if (!signature) { + PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE); + return SECFailure; } - - PORT_Memcpy(signature->data, - buf->data + 4 + (buf->data[3]-len/2), len/2); - PORT_Memcpy(signature->data + len/2, - buf->data + buf->len - len/2, len/2); buf = signature; break; #endif /* NSS_ENABLE_ECC */ @@ -3719,6 +3727,7 @@ sendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) CK_MECHANISM_TYPE target; SECKEYPublicKey *pubKey = NULL; /* Ephemeral ECDH key */ SECKEYPrivateKey *privKey = NULL; /* Ephemeral ECDH key */ + CK_EC_KDF_TYPE kdf; PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); PORT_Assert( ssl_HaveXmitBufLock(ss)); @@ -3740,9 +3749,19 @@ sendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). + */ + if ((pubKey->u.ec.publicValue.len - 1) / 2 <= 24) { + kdf = CKD_SHA1_KDF; + } else { + kdf = CKD_NULL; + } + /* Determine the PMS */ - pms = PK11_PubDerive(privKey, svrPubKey, PR_FALSE, NULL, NULL, - CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, NULL); + pms = PK11_PubDeriveExtended(privKey, svrPubKey, PR_FALSE, NULL, NULL, + CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, NULL, + kdf, NULL); if (pms == NULL) { ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); @@ -6175,6 +6194,7 @@ const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; SECKEYPublicKey * ecdhePub; SECItem ec_params = {siBuffer, NULL, 0}; ECName curve; + SSL3KEAType certIndex; #endif /* NSS_ENABLE_ECC */ SSL_TRC(3, ("%d: SSL3[%d]: send server_key_exchange handshake", @@ -6301,12 +6321,15 @@ const ssl3KEADef * kea_def = ss->ssl3->hs.kea_def; isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); /* XXX SSLKEAType isn't really a good choice for - * indexing certificates. The following line of - * code will need to change when we support - * (EC)DHE-xxx ciphers on the server side where xxx - * is something other than RSA. + * indexing certificates but that's all we have + * for now. */ - rv = ssl3_SignHashes(&hashes, ss->serverCerts[kt_rsa].serverKey, + if (kea_def->kea == kea_ecdhe_rsa) + certIndex = kt_rsa; + else /* kea_def->kea == kea_ecdhe_ecdsa */ + certIndex = kt_ecdh; + + rv = ssl3_SignHashes(&hashes, ss->serverCerts[certIndex].serverKey, &signed_hash, isTLS); if (rv != SECSuccess) { goto loser; /* ssl3_SignHashes has set err. */ @@ -6928,6 +6951,7 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, SECKEYPublicKey clntPubKey; CK_MECHANISM_TYPE target; PRBool isTLS; + CK_EC_KDF_TYPE kdf; PORT_Assert( ssl_HaveRecvBufLock(ss) ); PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); @@ -6950,9 +6974,19 @@ ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b, if (isTLS) target = CKM_TLS_MASTER_KEY_DERIVE_DH; else target = CKM_SSL3_MASTER_KEY_DERIVE_DH; + /* If field size is not more than 24 octets, then use SHA-1 hash of result; + * otherwise, use result (see section 4.8 of draft-ietf-tls-ecc-03.txt). + */ + if (srvrPubKey->u.ec.size <= 24 * 8) { + kdf = CKD_SHA1_KDF; + } else { + kdf = CKD_NULL; + } + /* Determine the PMS */ - pms = PK11_PubDerive(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, - CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, NULL); + pms = PK11_PubDeriveExtended(srvrPrivKey, &clntPubKey, PR_FALSE, NULL, NULL, + CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0, NULL, + kdf, NULL); PORT_Free(clntPubKey.u.ec.publicValue.data); @@ -6982,6 +7016,9 @@ ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) SECKEYPrivateKey *serverKey = NULL; SECStatus rv; const ssl3KEADef * kea_def; +#ifdef NSS_ENABLE_ECC + SECKEYPublicKey *serverPubKey = NULL; +#endif /* NSS_ENABLE_ECC */ SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake", SSL_GETPID(), ss->fd)); @@ -6998,11 +7035,11 @@ const ssl3KEADef * kea_def; kea_def = ss->ssl3->hs.kea_def; #ifdef NSS_ENABLE_ECC - /* XXX We'll need additional code here to compute serverKey and - * ss->sec.keaKeyBits appropriately when we add server side - * support for (EC)DHE-xxx cipher suites where xxx is something - * other than rsa. Using SSLKEAType to index server certifiates - * does not work for (EC)DHE ciphers. + /* XXX Using SSLKEAType to index server certifiates + * does not work for (EC)DHE ciphers. Until we have + * an indexing mechanism general enough for all key + * exchange algorithms, we'll need to deal with each + * one seprately. */ if ((kea_def->kea == kea_ecdhe_rsa) || (kea_def->kea == kea_ecdhe_ecdsa)) { @@ -7068,9 +7105,27 @@ const ssl3KEADef * kea_def; #ifdef NSS_ENABLE_ECC case kt_ecdh: + /* XXX We really ought to be able to store multiple + * EC certs (a requirement if we wish to support both + * ECDH-RSA and ECDH-ECDSA key exchanges concurrently). + * When we make that change, we'll need an index other + * than kt_ecdh to pick the right EC certificate. + */ + if (((kea_def->kea == kea_ecdhe_ecdsa) || + (kea_def->kea == kea_ecdhe_rsa)) && + (ss->ephemeralECDHKeyPair != NULL)) { + serverPubKey = ss->ephemeralECDHKeyPair->pubKey; + } else { + serverPubKey = CERT_ExtractPublicKey( + ss->serverCerts[kt_ecdh].serverCert); + } + if (serverPubKey == NULL) { + /* XXX Is this the right error code? */ + PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE); + return SECFailure; + } rv = ssl3_HandleECDHClientKeyExchange(ss, b, length, - ss->ephemeralECDHKeyPair->pubKey, - serverKey); + serverPubKey, serverKey); if (rv != SECSuccess) { return SECFailure; /* error code set */ } diff --git a/security/nss/lib/ssl/ssl3prot.h b/security/nss/lib/ssl/ssl3prot.h index 8a9e3dd67918..6c1680658510 100644 --- a/security/nss/lib/ssl/ssl3prot.h +++ b/security/nss/lib/ssl/ssl3prot.h @@ -37,7 +37,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: ssl3prot.h,v 1.3 2003/02/27 01:31:30 nelsonb%netscape.com Exp $ + * $Id: ssl3prot.h,v 1.4 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #ifndef __ssl3proto_h_ @@ -251,6 +251,14 @@ typedef enum { ct_DSS_fixed_DH = 4, ct_RSA_ephemeral_DH = 5, ct_DSS_ephemeral_DH = 6, + /* XXX The numbers assigned to the following EC-based + * certificate types might change before the ECC in TLS + * draft becomes an IETF RFC. + */ + ct_ECDSA_sign = 7, + ct_RSA_fixed_ECDH = 8, + ct_ECDSA_fixed_ECDH = 9, + ct_Fortezza = 20 } SSL3ClientCertificateType; diff --git a/security/nss/lib/ssl/sslsecur.c b/security/nss/lib/ssl/sslsecur.c index bee005ba8b7a..89ede6825f0b 100644 --- a/security/nss/lib/ssl/sslsecur.c +++ b/security/nss/lib/ssl/sslsecur.c @@ -36,7 +36,7 @@ * may use your version of this file under either the MPL or the * GPL. * - * $Id: sslsecur.c,v 1.22 2003/02/27 01:31:35 nelsonb%netscape.com Exp $ + * $Id: sslsecur.c,v 1.23 2003/10/17 13:45:39 ian.mcgreer%sun.com Exp $ */ #include "cert.h" #include "secitem.h" @@ -583,6 +583,11 @@ ssl_FindCertKEAType(CERTCertificate * cert) case SEC_OID_X942_DIFFIE_HELMAN_KEY: keaType = kt_dh; break; +#ifdef NSS_ENABLE_ECC + case SEC_OID_ANSIX962_EC_PUBLIC_KEY: + keaType = kt_ecdh; + break; +#endif /* NSS_ENABLE_ECC */ default: keaType = kt_null; } diff --git a/security/nss/tests/cert/eccert.sh b/security/nss/tests/cert/eccert.sh new file mode 100644 index 000000000000..026f8827a83a --- /dev/null +++ b/security/nss/tests/cert/eccert.sh @@ -0,0 +1,889 @@ +#! /bin/sh +# +# 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 Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +# Sun Microsystems, Inc. All Rights Reserved. +# +# Contributor(s): +# Dr Vipul Gupta , Sun Microsystems Laboratories +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +######################################################################## +# +# mozilla/security/nss/tests/cert/rcert.sh +# +# Certificate generating and handeling for NSS QA, can be included +# multiple times from all.sh and the individual scripts +# +# needs to work on all Unix and Windows platforms +# +# included from (don't expect this to be up to date) +# -------------------------------------------------- +# all.sh +# ssl.sh +# smime.sh +# tools.sh +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +# FIXME - Netscape - NSS +######################################################################## + +############################## cert_init ############################### +# local shell function to initialize this script +######################################################################## +cert_init() +{ + SCRIPTNAME="cert.sh" + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + if [ -z "${INIT_SOURCED}" ] ; then + cd ../common + . ./init.sh + fi + SCRIPTNAME="cert.sh" + html_head "Certutil Tests" + + ################## Generate noise for our CA cert. ###################### + # NOTE: these keys are only suitable for testing, as this whole thing + # bypasses the entropy gathering. Don't use this method to generate + # keys and certs for product use or deployment. + # + ps -efl > ${NOISE_FILE} 2>&1 + ps aux >> ${NOISE_FILE} 2>&1 + noise + +} + +cert_log() ###################### write the cert_status file +{ + echo "$SCRIPTNAME $*" + echo $* >>${CERT_LOG_FILE} +} + +################################ noise ################################## +# Generate noise for our certs +# +# NOTE: these keys are only suitable for testing, as this whole thing bypasses +# the entropy gathering. Don't use this method to generate keys and certs for +# product use or deployment. +######################################################################### +noise() +{ + #netstat >> ${NOISE_FILE} 2>&1 + date >> ${NOISE_FILE} 2>&1 +} + +################################ certu ################################# +# local shell function to call certutil, also: writes action and options to +# stdout, sets variable RET and writes results to the html file results +######################################################################## +certu() +{ + echo "$SCRIPTNAME: ${CU_ACTION} --------------------------" + + if [ -n "${CU_SUBJECT}" ]; then + #the subject of the cert contains blanks, and the shell + #will strip the quotes off the string, if called otherwise... + echo "certutil -s \"${CU_SUBJECT}\" $*" + certutil -s "${CU_SUBJECT}" $* + RET=$? + CU_SUBJECT="" + else + echo "certutil $*" + certutil $* + RET=$? + fi + if [ "$RET" -ne 0 ]; then + CERTFAILED=$RET + html_failed "${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "${CU_ACTION}" + fi + + # echo "Contine?" + # cat > /dev/null + return $RET +} + +############################# cert_init_cert ########################## +# local shell function to initialize creation of client and server certs +######################################################################## +cert_init_cert() +{ + CERTDIR="$1" + CERTNAME="$2" + CERTSERIAL="$3" + DOMAIN="$4" + + if [ ! -d "${CERTDIR}" ]; then + mkdir -p "${CERTDIR}" + else + echo "$SCRIPTNAME: WARNING - ${CERTDIR} exists" + fi + cd "${CERTDIR}" + CERTDIR="." + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${DOMAIN}" + fi + + noise +} + +############################# hw_acc ################################# +# local shell function to add hw accelerator modules to the db +######################################################################## +hw_acc() +{ + HW_ACC_RET=0 + HW_ACC_ERR="" + if [ -n "$O_HWACC" -a "$O_HWACC" = ON -a -z "$USE_64" ] ; then + echo "creating $CERTNAME s cert with hwaccelerator..." + #case $ACCELERATOR in + #rainbow) + + + echo "modutil -add rainbow -libfile /usr/lib/libcryptoki22.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add rainbow -libfile /usr/lib/libcryptoki22.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add rainbow failed in `pwd`" + HW_ACC_RET=1 + HW_ACC_ERR="modutil -add rainbow" + fi + + echo "modutil -add ncipher " + echo " -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add ncipher \ + -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add ncipher failed in `pwd`" + HW_ACC_RET=`expr $HW_ACC_RET + 2` + HW_ACC_ERR="$HW_ACC_ERR,modutil -add ncipher" + fi + if [ "$HW_ACC_RET" -ne 0 ]; then + html_failed "Adding HW accelerators to certDB for ${CERTNAME} ($HW_ACC_RET) " + else + html_passed "Adding HW accelerators to certDB for ${CERTNAME}" + fi + + fi + return $HW_ACC_RET +} + +############################# cert_create_cert ######################### +# local shell function to create client certs +# initialize DB, import +# root cert +# add cert to DB +######################################################################## +cert_create_cert() +{ + cert_init_cert "$1" "$2" "$3" "$4" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + hw_acc + CU_ACTION="Import Root CA for $CERTNAME" + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/root.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + cert_add_cert "$5" + return $? +} + +############################# cert_create_certs ######################## +# local shell function to create client certs +# initialize DB, import +# root certs (RSA and EC) +# add certs (RSA and EC) to DB +######################################################################## +cert_create_certs() +{ + cert_init_cert "$1" "$2" "$3" "$4" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + hw_acc + CU_ACTION="Import Root CA for $CERTNAME" + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/root.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + CU_ACTION="Import EC Root CA for $CERTNAME" + certu -A -n "TestCA-ec" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/ecroot.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + cert_add_certs "$5" + return $? +} + +############################# cert_add_cert ############################ +# local shell function to add client certs to an existing CERT DB +# generate request +# sign request +# import Cert +# +######################################################################## +cert_add_cert() +{ + + CU_ACTION="Generate Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s Request" + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's Cert" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's Cert Created" + return 0 +} + +############################# cert_add_certs ############################ +# local shell function to add client certs to an existing CERT DB +# generate request +# sign request +# import Cert +# +# Do this for both RSA and EC certs +######################################################################## +cert_add_certs() +{ + CURVE="secp160r2" + + CU_ACTION="Generate Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s Request" + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's Cert" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's Cert Created" + +# +# Generate and add EC cert +# + CU_ACTION="Generate EC Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -k ec -q "${CURVE}" -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s EC Request" + certu -C -c "TestCA-ec" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}-ec.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's EC Cert" + certu -A -n "${CERTNAME}-ec" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}-ec.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's EC Cert Created" + + return 0 +} + +################################# cert_all_CA ################################ +# local shell function to build the additional Temp. Certificate Authority (CA) +# used for the "real life" ssl test with 2 different CA's in the +# client and in teh server's dir +########################################################################## +cert_all_CA() +{ + CA_CURVE="secp160r1" + + echo nss > ${PWFILE} + + ALL_CU_SUBJECT="CN=NSS Test CA, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + cert_CA $CADIR TestCA -x "CTu,CTu,CTu" ${D_CA} "1" + +# Create EC version of TestCA + ALL_CU_SUBJECT="CN=NSS Test CA (ECC), O=BOGUS NSS, L=Mountain View, ST=California, C=US" + cert_ec_CA $CADIR TestCA-ec -x "CTu,CTu,CTu" ${D_CA} "1" ${CA_CURVE} + + ALL_CU_SUBJECT="CN=NSS Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR serverCA -x "Cu,Cu,Cu" ${D_SERVER_CA} "2" + ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-1-serverCA "-c serverCA" "u,u,u" ${D_SERVER_CA} "3" + ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-2-serverCA "-c chain-1-serverCA" "u,u,u" ${D_SERVER_CA} "4" + +# +# Create EC versions of the above CA certs +# + ALL_CU_SUBJECT="CN=NSS Server Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $SERVER_CADIR serverCA-ec -x "Cu,Cu,Cu" ${D_SERVER_CA} "2" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $SERVER_CADIR chain-1-serverCA-ec "-c serverCA-ec" "u,u,u" ${D_SERVER_CA} "3" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $SERVER_CADIR chain-2-serverCA-ec "-c chain-1-serverCA-ec" "u,u,u" ${D_SERVER_CA} "4" ${CA_CURVE} + + + ALL_CU_SUBJECT="CN=NSS Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR clientCA -x "Tu,Cu,Cu" ${D_CLIENT_CA} "5" + ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-1-clientCA "-c clientCA" "u,u,u" ${D_CLIENT_CA} "6" + ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-2-clientCA "-c chain-1-clientCA" "u,u,u" ${D_CLIENT_CA} "7" + +# +# Create EC versions of the above CA certs +# + ALL_CU_SUBJECT="CN=NSS Client Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $CLIENT_CADIR clientCA-ec -x "Tu,Cu,Cu" ${D_CLIENT_CA} "5" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $CLIENT_CADIR chain-1-clientCA-ec "-c clientCA-ec" "u,u,u" ${D_CLIENT_CA} "6" ${CA_CURVE} + ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA (ECC), O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_ec_CA $CLIENT_CADIR chain-2-clientCA-ec "-c chain-1-clientCA-ec" "u,u,u" ${D_CLIENT_CA} "7" ${CA_CURVE} + + rm $CLIENT_CADIR/root.cert $SERVER_CADIR/root.cert + rm $CLIENT_CADIR/ecroot.cert $SERVER_CADIR/ecroot.cert + # root.cert in $CLIENT_CADIR and in $SERVER_CADIR is the one of the last + # in the chain +} + +################################# cert_CA ################################ +# local shell function to build the Temp. Certificate Authority (CA) +# used for testing purposes, creating a CA Certificate and a root cert +########################################################################## +cert_CA() +{ + CUR_CADIR=$1 + NICKNAME=$2 + SIGNER=$3 + TRUSTARG=$4 + DOMAIN=$5 + CERTSERIAL=$6 + + echo "$SCRIPTNAME: Creating a CA Certificate $NICKNAME ==========================" + + if [ ! -d "${CUR_CADIR}" ]; then + mkdir -p "${CUR_CADIR}" + fi + cd ${CUR_CADIR} + pwd + + LPROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + LPROFILE="multiaccess:${DOMAIN}" + fi + + if [ "$SIGNER" = "-x" ] ; then # self signed -> create DB + CU_ACTION="Creating CA Cert DB" + certu -N -d ${LPROFILE} -f ${R_PWFILE} 2>&1 + if [ "$RET" -ne 0 ]; then + Exit 5 "Fatal - failed to create CA $NICKNAME " + fi + echo "$SCRIPTNAME: Certificate initialized ----------" + fi + + + ################# Creating CA Cert ###################################### + # + CU_ACTION="Creating CA Cert $NICKNAME " + CU_SUBJECT=$ALL_CU_SUBJECT + certu -S -n $NICKNAME -t $TRUSTARG -v 60 $SIGNER -d ${LPROFILE} -1 -2 -5 \ + -f ${R_PWFILE} -z ${R_NOISE_FILE} -m $CERTSERIAL 2>&1 <&1 <&1 + + #CU_ACTION="Export Dave's Cert" + #cd ${DAVEDIR} + #certu -L -n "Dave" -r -d ${P_R_DAVE} -o Dave.cert + + ################# Importing Certificates for S/MIME tests ############### + # + echo "$SCRIPTNAME: Importing Certificates ==============================" + CU_ACTION="Import Alices's cert into Bob's db" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_ALICEDIR}/Alice.cert 2>&1 + + CU_ACTION="Import Bob's cert into Alice's db" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_BOBDIR}/Bob.cert 2>&1 + + CU_ACTION="Import Dave's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Dave's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Eve's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + CU_ACTION="Import Eve's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SMIME failed $RET" + else + cert_log "SUCCESS: SMIME passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for extended SSL test +######################################################################## +cert_extended_ssl() +{ + EC_CURVE="sect163r1" + + ################# Creating Certs for extended SSL test #################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Certificates, issued by the last ===============" + echo " of a chain of CA's which are not in the same database============" + + echo "Server Cert" + cert_init_cert ${EXT_SERVERDIR} "${HOSTADDR}" 1 ${D_EXT_SERVER} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${SERVER_CADIR} + certu -C -c "chain-2-serverCA" -m 200 -v 60 -d "${P_SERVER_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + + CU_ACTION="Import Client Root CA -t T,, for $CERTNAME (ext.)" + certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA.ca.cert" 2>&1 +# +# Repeat the above for EC certs +# + CU_ACTION="Generate EC Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s EC Request (ext)" + cp ${CERTDIR}/req ${SERVER_CADIR} + certu -C -c "chain-2-serverCA-ec" -m 200 -v 60 -d "${P_SERVER_CADIR}" \ + -i req -o "${CERTNAME}-ec.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's EC Cert -t u,u,u (ext)" + certu -A -n "${CERTNAME}-ec" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}-ec.cert" 2>&1 + + CU_ACTION="Import Client EC Root CA -t T,, for $CERTNAME (ext.)" + certu -A -n "clientCA-ec" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA-ec.ca.cert" 2>&1 +# +# done with EC certs +# + echo "Importing all the server's own CA chain into the servers DB" + for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "serverCA" ] ; then + T="-t C,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.) " + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done +#============ + echo "Client Cert" + cert_init_cert ${EXT_CLIENTDIR} ExtendedSSLUser 1 ${D_EXT_CLIENT} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${CLIENT_CADIR} + certu -C -c "chain-2-clientCA" -m 300 -v 60 -d "${P_CLIENT_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + CU_ACTION="Import Server Root CA -t C,C,C for $CERTNAME (ext.)" + certu -A -n "serverCA" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${SERVER_CADIR}/serverCA.ca.cert" 2>&1 +# +# Repeat the above for EC certs +# + CU_ACTION="Generate EC Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}-ec@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -k ec -q "${EC_CURVE}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s EC Request (ext)" + cp ${CERTDIR}/req ${CLIENT_CADIR} + certu -C -c "chain-2-clientCA-ec" -m 300 -v 60 -d "${P_CLIENT_CADIR}" \ + -i req -o "${CERTNAME}-ec.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's EC Cert -t u,u,u (ext)" + certu -A -n "${CERTNAME}-ec" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}-ec.cert" 2>&1 + CU_ACTION="Import Server EC Root CA -t C,C,C for $CERTNAME (ext.)" + certu -A -n "serverCA-ec" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${SERVER_CADIR}/serverCA-ec.ca.cert" 2>&1 +# +# done with EC certs +# + echo "Importing all the client's own CA chain into the servers DB" + for CA in `find ${CLIENT_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "clientCA" ] ; then + T="-t T,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.)" + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: EXT failed $RET" + else + cert_log "SUCCESS: EXT passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for SSL test +######################################################################## +cert_ssl() +{ + ################# Creating Certs for SSL test ########################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + cert_create_certs ${CLIENTDIR} "TestUser" 70 ${D_CLIENT} + + echo "$SCRIPTNAME: Creating Server CA Issued Certificate for \\" + echo " ${HOSTADDR} ------------------------------------" + cert_create_certs ${SERVERDIR} "${HOSTADDR}" 100 ${D_SERVER} + certu -M -n "TestCA" -t "TC,TC,TC" -d ${PROFILEDIR} + certu -M -n "TestCA-ec" -t "TC,TC,TC" -d ${PROFILEDIR} +# cert_init_cert ${SERVERDIR} "${HOSTADDR}" 1 ${D_SERVER} +# echo "************* Copying CA files to ${SERVERDIR}" +# cp ${CADIR}/*.db . +# hw_acc +# CU_ACTION="Creating ${CERTNAME}'s Server Cert" +# CU_SUBJECT="CN=${CERTNAME}, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" +# certu -S -n "${CERTNAME}" -c "TestCA" -t "Pu,Pu,Pu" -d ${PROFILEDIR} \ +# -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SSL failed $RET" + else + cert_log "SUCCESS: SSL passed" + fi +} +############################## cert_stresscerts ################################ +# local shell function to create client certs for SSL stresstest +######################################################################## +cert_stresscerts() +{ + + ############### Creating Certs for SSL stress test ####################### + # + CERTDIR="$CLIENTDIR" + cd "${CERTDIR}" + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${D_CLIENT}" + fi + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + + CONTINUE=$GLOB_MAX_CERT + CERTSERIAL=10 + + while [ $CONTINUE -ge $GLOB_MIN_CERT ] + do + CERTNAME="TestUser$CONTINUE" +# cert_add_cert ${CLIENTDIR} "TestUser$CONTINUE" $CERTSERIAL + cert_add_certs + CERTSERIAL=`expr $CERTSERIAL + 1 ` + CONTINUE=`expr $CONTINUE - 1 ` + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: StressCert failed $RET" + else + cert_log "SUCCESS: StressCert passed" + fi +} + +############################## cert_fips ##################################### +# local shell function to create certificates for FIPS tests +############################################################################## +cert_fips() +{ + CERTFAILED=0 + echo "$SCRIPTNAME: Creating FIPS 140-1 DSA Certificates ==============" + cert_init_cert "${FIPSDIR}" "FIPS PUB 140-1 Test Certificate" 1000 "${D_FIPS}" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" 2>&1 + + echo "$SCRIPTNAME: Enable FIPS mode on database -----------------------" + CU_ACTION="Enable FIPS mode on database for ${CERTNAME}" + echo "modutil -dbdir ${PROFILEDIR} -fips true " + modutil -dbdir ${PROFILEDIR} -fips true 2>&1 <${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "${CU_ACTION}" + fi + + CU_ACTION="Generate Certificate for ${CERTNAME}" + CU_SUBJECT="CN=${CERTNAME}, E=fips@bogus.com, O=BOGUS NSS, OU=FIPS PUB 140-1, L=Mountain View, ST=California, C=US" + certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -m 500 -z "${R_NOISE_FILE}" 2>&1 + if [ "$RET" -eq 0 ]; then + cert_log "SUCCESS: FIPS passed" + fi +} + +############################## cert_cleanup ############################ +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +cert_cleanup() +{ + cert_log "$SCRIPTNAME: finished $SCRIPTNAME" + html "
" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +cert_init +cert_all_CA +cert_extended_ssl +cert_ssl +cert_smime_client +cert_fips +if [ -n "$DO_DIST_ST" -a "$DO_DIST_ST" = "TRUE" ] ; then + cert_stresscerts + #following lines to be used when databases are to be reused + #cp -r /u/sonmi/tmp/stress/kentuckyderby.13/* $HOSTDIR + #cp -r $HOSTDIR/../${HOST}.2/* $HOSTDIR + +fi +cert_cleanup diff --git a/security/nss/tests/cert/noeccert.sh b/security/nss/tests/cert/noeccert.sh new file mode 100755 index 000000000000..6bb91b6a8615 --- /dev/null +++ b/security/nss/tests/cert/noeccert.sh @@ -0,0 +1,654 @@ +#! /bin/sh +# +# 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 Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# + +######################################################################## +# +# mozilla/security/nss/tests/cert/rcert.sh +# +# Certificate generating and handeling for NSS QA, can be included +# multiple times from all.sh and the individual scripts +# +# needs to work on all Unix and Windows platforms +# +# included from (don't expect this to be up to date) +# -------------------------------------------------- +# all.sh +# ssl.sh +# smime.sh +# tools.sh +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +# FIXME - Netscape - NSS +######################################################################## + +############################## cert_init ############################### +# local shell function to initialize this script +######################################################################## +cert_init() +{ + SCRIPTNAME="cert.sh" + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + if [ -z "${INIT_SOURCED}" ] ; then + cd ../common + . ./init.sh + fi + SCRIPTNAME="cert.sh" + html_head "Certutil Tests" + + ################## Generate noise for our CA cert. ###################### + # NOTE: these keys are only suitable for testing, as this whole thing + # bypasses the entropy gathering. Don't use this method to generate + # keys and certs for product use or deployment. + # + ps -efl > ${NOISE_FILE} 2>&1 + ps aux >> ${NOISE_FILE} 2>&1 + noise + +} + +cert_log() ###################### write the cert_status file +{ + echo "$SCRIPTNAME $*" + echo $* >>${CERT_LOG_FILE} +} + +################################ noise ################################## +# Generate noise for our certs +# +# NOTE: these keys are only suitable for testing, as this whole thing bypasses +# the entropy gathering. Don't use this method to generate keys and certs for +# product use or deployment. +######################################################################### +noise() +{ + #netstat >> ${NOISE_FILE} 2>&1 + date >> ${NOISE_FILE} 2>&1 +} + +################################ certu ################################# +# local shell function to call certutil, also: writes action and options to +# stdout, sets variable RET and writes results to the html file results +######################################################################## +certu() +{ + echo "$SCRIPTNAME: ${CU_ACTION} --------------------------" + + if [ -n "${CU_SUBJECT}" ]; then + #the subject of the cert contains blanks, and the shell + #will strip the quotes off the string, if called otherwise... + echo "certutil -s \"${CU_SUBJECT}\" $*" + certutil -s "${CU_SUBJECT}" $* + RET=$? + CU_SUBJECT="" + else + echo "certutil $*" + certutil $* + RET=$? + fi + if [ "$RET" -ne 0 ]; then + CERTFAILED=$RET + html_failed "${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "${CU_ACTION}" + fi + + # echo "Contine?" + # cat > /dev/null + return $RET +} + +############################# cert_init_cert ########################## +# local shell function to initialize creation of client and server certs +######################################################################## +cert_init_cert() +{ + CERTDIR="$1" + CERTNAME="$2" + CERTSERIAL="$3" + DOMAIN="$4" + + if [ ! -d "${CERTDIR}" ]; then + mkdir -p "${CERTDIR}" + else + echo "$SCRIPTNAME: WARNING - ${CERTDIR} exists" + fi + cd "${CERTDIR}" + CERTDIR="." + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${DOMAIN}" + fi + + noise +} + +############################# hw_acc ################################# +# local shell function to add hw accelerator modules to the db +######################################################################## +hw_acc() +{ + HW_ACC_RET=0 + HW_ACC_ERR="" + if [ -n "$O_HWACC" -a "$O_HWACC" = ON -a -z "$USE_64" ] ; then + echo "creating $CERTNAME s cert with hwaccelerator..." + #case $ACCELERATOR in + #rainbow) + + + echo "modutil -add rainbow -libfile /usr/lib/libcryptoki22.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add rainbow -libfile /usr/lib/libcryptoki22.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add rainbow failed in `pwd`" + HW_ACC_RET=1 + HW_ACC_ERR="modutil -add rainbow" + fi + + echo "modutil -add ncipher " + echo " -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so " + echo " -dbdir ${PROFILEDIR} 2>&1 " + echo | modutil -add ncipher \ + -libfile /opt/nfast/toolkits/pkcs11/libcknfast.so \ + -dbdir ${PROFILEDIR} 2>&1 + if [ "$?" -ne 0 ]; then + echo "modutil -add ncipher failed in `pwd`" + HW_ACC_RET=`expr $HW_ACC_RET + 2` + HW_ACC_ERR="$HW_ACC_ERR,modutil -add ncipher" + fi + if [ "$HW_ACC_RET" -ne 0 ]; then + html_failed "Adding HW accelerators to certDB for ${CERTNAME} ($HW_ACC_RET) " + else + html_passed "Adding HW accelerators to certDB for ${CERTNAME}" + fi + + fi + return $HW_ACC_RET +} + +############################# cert_create_cert ######################### +# local shell function to create client certs +# initialize DB, import +# root cert +# add cert to DB +######################################################################## +cert_create_cert() +{ + cert_init_cert "$1" "$2" "$3" "$4" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + hw_acc + CU_ACTION="Import Root CA for $CERTNAME" + certu -A -n "TestCA" -t "TC,TC,TC" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${R_CADIR}/root.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + cert_add_cert "$5" + return $? +} + +############################# cert_add_cert ############################ +# local shell function to add client certs to an existing CERT DB +# generate request +# sign request +# import Cert +# +######################################################################## +cert_add_cert() +{ + + CU_ACTION="Generate Cert Request for $CERTNAME" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Sign ${CERTNAME}'s Request" + certu -C -c "TestCA" -m "$CERTSERIAL" -v 60 -d "${P_R_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" "$1" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + CU_ACTION="Import $CERTNAME's Cert" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + if [ "$RET" -ne 0 ]; then + return $RET + fi + + cert_log "SUCCESS: $CERTNAME's Cert Created" + return 0 +} + +################################# cert_all_CA ################################ +# local shell function to build the additional Temp. Certificate Authority (CA) +# used for the "real life" ssl test with 2 different CA's in the +# client and in teh server's dir +########################################################################## +cert_all_CA() +{ + echo nss > ${PWFILE} + + ALL_CU_SUBJECT="CN=NSS Test CA, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + cert_CA $CADIR TestCA -x "CTu,CTu,CTu" ${D_CA} "1" + + ALL_CU_SUBJECT="CN=NSS Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR serverCA -x "Cu,Cu,Cu" ${D_SERVER_CA} "2" + ALL_CU_SUBJECT="CN=NSS Chain1 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-1-serverCA "-c serverCA" "u,u,u" ${D_SERVER_CA} "3" + ALL_CU_SUBJECT="CN=NSS Chain2 Server Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $SERVER_CADIR chain-2-serverCA "-c chain-1-serverCA" "u,u,u" ${D_SERVER_CA} "4" + + + + ALL_CU_SUBJECT="CN=NSS Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR clientCA -x "Tu,Cu,Cu" ${D_CLIENT_CA} "5" + ALL_CU_SUBJECT="CN=NSS Chain1 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-1-clientCA "-c clientCA" "u,u,u" ${D_CLIENT_CA} "6" + ALL_CU_SUBJECT="CN=NSS Chain2 Client Test CA, O=BOGUS NSS, L=Santa Clara, ST=California, C=US" + cert_CA $CLIENT_CADIR chain-2-clientCA "-c chain-1-clientCA" "u,u,u" ${D_CLIENT_CA} "7" + + rm $CLIENT_CADIR/root.cert $SERVER_CADIR/root.cert + # root.cert in $CLIENT_CADIR and in $SERVER_CADIR is the one of the last + # in the chain +} + +################################# cert_CA ################################ +# local shell function to build the Temp. Certificate Authority (CA) +# used for testing purposes, creating a CA Certificate and a root cert +########################################################################## +cert_CA() +{ + CUR_CADIR=$1 + NICKNAME=$2 + SIGNER=$3 + TRUSTARG=$4 + DOMAIN=$5 + CERTSERIAL=$6 + + echo "$SCRIPTNAME: Creating a CA Certificate $NICKNAME ==========================" + + if [ ! -d "${CUR_CADIR}" ]; then + mkdir -p "${CUR_CADIR}" + fi + cd ${CUR_CADIR} + pwd + + LPROFILE=. + if [ -n "${MULTIACCESS_DBM}" ]; then + LPROFILE="multiaccess:${DOMAIN}" + fi + + if [ "$SIGNER" = "-x" ] ; then # self signed -> create DB + CU_ACTION="Creating CA Cert DB" + certu -N -d ${LPROFILE} -f ${R_PWFILE} 2>&1 + if [ "$RET" -ne 0 ]; then + Exit 5 "Fatal - failed to create CA $NICKNAME " + fi + echo "$SCRIPTNAME: Certificate initialized ----------" + fi + + + ################# Creating CA Cert ###################################### + # + CU_ACTION="Creating CA Cert $NICKNAME " + CU_SUBJECT=$ALL_CU_SUBJECT + certu -S -n $NICKNAME -t $TRUSTARG -v 600 $SIGNER -d ${LPROFILE} -1 -2 -5 \ + -f ${R_PWFILE} -z ${R_NOISE_FILE} -m $CERTSERIAL 2>&1 <&1 + + #CU_ACTION="Export Dave's Cert" + #cd ${DAVEDIR} + #certu -L -n "Dave" -r -d ${P_R_DAVE} -o Dave.cert + + ################# Importing Certificates for S/MIME tests ############### + # + echo "$SCRIPTNAME: Importing Certificates ==============================" + CU_ACTION="Import Alices's cert into Bob's db" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_ALICEDIR}/Alice.cert 2>&1 + + CU_ACTION="Import Bob's cert into Alice's db" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_BOBDIR}/Bob.cert 2>&1 + + CU_ACTION="Import Dave's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Dave's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_DAVEDIR}/Dave.cert 2>&1 + + CU_ACTION="Import Eve's cert into Alice's DB" + certu -E -t "p,p,p" -d ${P_R_ALICEDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + CU_ACTION="Import Eve's cert into Bob's DB" + certu -E -t "p,p,p" -d ${P_R_BOBDIR} -f ${R_PWFILE} \ + -i ${R_EVEDIR}/Eve.cert 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SMIME failed $RET" + else + cert_log "SUCCESS: SMIME passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for extended SSL test +######################################################################## +cert_extended_ssl() +{ + ################# Creating Certs for extended SSL test #################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Certificates, issued by the last ===============" + echo " of a chain of CA's which are not in the same database============" + + echo "Server Cert" + cert_init_cert ${EXT_SERVERDIR} "${HOSTADDR}" 1 ${D_EXT_SERVER} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${SERVER_CADIR} + certu -C -c "chain-2-serverCA" -m 200 -v 60 -d "${P_SERVER_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + + CU_ACTION="Import Client Root CA -t T,, for $CERTNAME (ext.)" + certu -A -n "clientCA" -t "T,," -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CLIENT_CADIR}/clientCA.ca.cert" 2>&1 + echo "Importing all the server's own CA chain into the servers DB" + for CA in `find ${SERVER_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "serverCA" ] ; then + T="-t C,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.) " + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done +#============ + echo "Client Cert" + cert_init_cert ${EXT_CLIENTDIR} ExtendedSSLUser 1 ${D_EXT_CLIENT} + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB (ext.)" + certu -N -d "${PROFILEDIR}" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Generate Cert Request for $CERTNAME (ext)" + CU_SUBJECT="CN=$CERTNAME, E=${CERTNAME}@bogus.com, O=BOGUS NSS, L=Mountain View, ST=California, C=US" + certu -R -d "${PROFILEDIR}" -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -o req 2>&1 + + CU_ACTION="Sign ${CERTNAME}'s Request (ext)" + cp ${CERTDIR}/req ${CLIENT_CADIR} + certu -C -c "chain-2-clientCA" -m 300 -v 60 -d "${P_CLIENT_CADIR}" \ + -i req -o "${CERTNAME}.cert" -f "${R_PWFILE}" 2>&1 + + CU_ACTION="Import $CERTNAME's Cert -t u,u,u (ext)" + certu -A -n "$CERTNAME" -t "u,u,u" -d "${PROFILEDIR}" -f "${R_PWFILE}" \ + -i "${CERTNAME}.cert" 2>&1 + CU_ACTION="Import Server Root CA -t C,C,C for $CERTNAME (ext.)" + certu -A -n "serverCA" -t "C,C,C" -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${SERVER_CADIR}/serverCA.ca.cert" 2>&1 + echo "Importing all the client's own CA chain into the servers DB" + for CA in `find ${CLIENT_CADIR} -name "?*.ca.cert"` ; + do + N=`basename $CA | sed -e "s/.ca.cert//"` + if [ $N = "clientCA" ] ; then + T="-t T,C,C" + else + T="-t u,u,u" + fi + CU_ACTION="Import $N CA $T for $CERTNAME (ext.)" + certu -A -n $N $T -f "${R_PWFILE}" -d "${PROFILEDIR}" \ + -i "${CA}" 2>&1 + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: EXT failed $RET" + else + cert_log "SUCCESS: EXT passed" + fi +} + +############################## cert_ssl ################################ +# local shell function to create client + server certs for SSL test +######################################################################## +cert_ssl() +{ + ################# Creating Certs for SSL test ########################### + # + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + cert_create_cert ${CLIENTDIR} "TestUser" 70 ${D_CLIENT} + + echo "$SCRIPTNAME: Creating Server CA Issued Certificate for \\" + echo " ${HOSTADDR} ------------------------------------" + cert_create_cert ${SERVERDIR} "${HOSTADDR}" 100 ${D_SERVER} + certu -M -n "TestCA" -t "TC,TC,TC" -d ${PROFILEDIR} +# cert_init_cert ${SERVERDIR} "${HOSTADDR}" 1 ${D_SERVER} +# echo "************* Copying CA files to ${SERVERDIR}" +# cp ${CADIR}/*.db . +# hw_acc +# CU_ACTION="Creating ${CERTNAME}'s Server Cert" +# CU_SUBJECT="CN=${CERTNAME}, O=BOGUS Netscape, L=Mountain View, ST=California, C=US" +# certu -S -n "${CERTNAME}" -c "TestCA" -t "Pu,Pu,Pu" -d ${PROFILEDIR} \ +# -f "${R_PWFILE}" -z "${R_NOISE_FILE}" -v 60 2>&1 + + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: SSL failed $RET" + else + cert_log "SUCCESS: SSL passed" + fi +} +############################## cert_stresscerts ################################ +# local shell function to create client certs for SSL stresstest +######################################################################## +cert_stresscerts() +{ + + ############### Creating Certs for SSL stress test ####################### + # + CERTDIR="$CLIENTDIR" + cd "${CERTDIR}" + + PROFILEDIR=${CERTDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + PROFILEDIR="multiaccess:${D_CLIENT}" + fi + CERTFAILED=0 + echo "$SCRIPTNAME: Creating Client CA Issued Certificates ===============" + + CONTINUE=$GLOB_MAX_CERT + CERTSERIAL=10 + + while [ $CONTINUE -ge $GLOB_MIN_CERT ] + do + CERTNAME="TestUser$CONTINUE" +# cert_add_cert ${CLIENTDIR} "TestUser$CONTINUE" $CERTSERIAL + cert_add_cert + CERTSERIAL=`expr $CERTSERIAL + 1 ` + CONTINUE=`expr $CONTINUE - 1 ` + done + if [ "$CERTFAILED" != 0 ] ; then + cert_log "ERROR: StressCert failed $RET" + else + cert_log "SUCCESS: StressCert passed" + fi +} + +############################## cert_fips ##################################### +# local shell function to create certificates for FIPS tests +############################################################################## +cert_fips() +{ + CERTFAILED=0 + echo "$SCRIPTNAME: Creating FIPS 140-1 DSA Certificates ==============" + cert_init_cert "${FIPSDIR}" "FIPS PUB 140-1 Test Certificate" 1000 "${D_FIPS}" + + CU_ACTION="Initializing ${CERTNAME}'s Cert DB" + certu -N -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" 2>&1 + + echo "$SCRIPTNAME: Enable FIPS mode on database -----------------------" + CU_ACTION="Enable FIPS mode on database for ${CERTNAME}" + echo "modutil -dbdir ${PROFILEDIR} -fips true " + modutil -dbdir ${PROFILEDIR} -fips true 2>&1 <${CU_ACTION} ($RET) " + cert_log "ERROR: ${CU_ACTION} failed $RET" + else + html_passed "${CU_ACTION}" + fi + + CU_ACTION="Generate Certificate for ${CERTNAME}" + CU_SUBJECT="CN=${CERTNAME}, E=fips@bogus.com, O=BOGUS NSS, OU=FIPS PUB 140-1, L=Mountain View, ST=California, C=US" + certu -S -n ${FIPSCERTNICK} -x -t "Cu,Cu,Cu" -d "${PROFILEDIR}" -f "${R_FIPSPWFILE}" -k dsa -v 600 -m 500 -z "${R_NOISE_FILE}" 2>&1 + if [ "$RET" -eq 0 ]; then + cert_log "SUCCESS: FIPS passed" + fi +} + +############################## cert_cleanup ############################ +# local shell function to finish this script (no exit since it might be +# sourced) +######################################################################## +cert_cleanup() +{ + cert_log "$SCRIPTNAME: finished $SCRIPTNAME" + html "
" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +cert_init +cert_all_CA +cert_extended_ssl +cert_ssl +cert_smime_client +cert_fips +if [ -n "$DO_DIST_ST" -a "$DO_DIST_ST" = "TRUE" ] ; then + cert_stresscerts + #following lines to be used when databases are to be reused + #cp -r /u/sonmi/tmp/stress/kentuckyderby.13/* $HOSTDIR + #cp -r $HOSTDIR/../${HOST}.2/* $HOSTDIR + +fi +cert_cleanup diff --git a/security/nss/tests/fixtests.sh b/security/nss/tests/fixtests.sh new file mode 100755 index 000000000000..e5e90e192c88 --- /dev/null +++ b/security/nss/tests/fixtests.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# +# 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 test suite. +# +# 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): +# Dr Vipul Gupta , Sun Microsystems Laboratories +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. + +####################### fix_test_scripts ####################### +# +# Depending on the argument either enable or disable EC based +# tests in the cert and ssl directories. +# +################################################################ +fix_test_scripts() +{ + FLAG=$1 + CERT_DIR=cert + CERT_SCRIPT=cert.sh + SSL_DIR=ssl + SSLAUTH=sslauth.txt + SSLCOV=sslcov.txt + SSL_SCRIPT=ssl.sh + SSLSTRESS=sslstress.txt + TOOLS_DIR=tools + TOOLS_SCRIPT=tools.sh + EC_PREFIX=ec + NOEC_PREFIX=noec + + if [ xx$FLAG = xx"enable_ecc" ]; then + if [ -f $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLAUTH -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLCOV -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLSTRESS -a \ + -f $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT ]; then + echo "noecc files exist" + else + echo "noecc files are missing" + echo "Saving files as noec" + cp $CERT_DIR/$CERT_SCRIPT $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT + cp $SSL_DIR/$SSLAUTH $SSL_DIR/$NOEC_PREFIX$SSLAUTH + cp $SSL_DIR/$SSLCOV $SSL_DIR/$NOEC_PREFIX$SSLCOV + cp $SSL_DIR/$SSL_SCRIPT $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT + cp $SSL_DIR/$SSLSTRESS $SSL_DIR/$NOEC_PREFIX$SSLSTRESS + cp $TOOLS_DIR/$TOOLS_SCRIPT $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT + fi + echo "Overwriting with ec versions" + cp $CERT_DIR/$EC_PREFIX$CERT_SCRIPT $CERT_DIR/$CERT_SCRIPT + cp $SSL_DIR/$EC_PREFIX$SSLAUTH $SSL_DIR/$SSLAUTH + cp $SSL_DIR/$EC_PREFIX$SSLCOV $SSL_DIR/$SSLCOV + cp $SSL_DIR/$EC_PREFIX$SSL_SCRIPT $SSL_DIR/$SSL_SCRIPT + cp $SSL_DIR/$EC_PREFIX$SSLSTRESS $SSL_DIR/$SSLSTRESS + cp $TOOLS_DIR/$EC_PREFIX$TOOLS_SCRIPT $TOOLS_DIR/$TOOLS_SCRIPT + elif [ xx$FLAG = xx"disable_ecc" ]; then + if [ -f $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLAUTH -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLCOV -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT -a \ + -f $SSL_DIR/$NOEC_PREFIX$SSLSTRESS -a \ + -f $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT ]; then + echo "noecc files exist" + echo "Overwriting with noec versions" + cp $CERT_DIR/$NOEC_PREFIX$CERT_SCRIPT $CERT_DIR/$CERT_SCRIPT + cp $SSL_DIR/$NOEC_PREFIX$SSLAUTH $SSL_DIR/$SSLAUTH + cp $SSL_DIR/$NOEC_PREFIX$SSLCOV $SSL_DIR/$SSLCOV + cp $SSL_DIR/$NOEC_PREFIX$SSL_SCRIPT $SSL_DIR/$SSL_SCRIPT + cp $SSL_DIR/$NOEC_PREFIX$SSLSTRESS $SSL_DIR/$SSLSTRESS + cp $TOOLS_DIR/$NOEC_PREFIX$TOOLS_SCRIPT $TOOLS_DIR/$TOOLS_SCRIPT + else + echo "Already disabled." + fi + else + echo "Needs either \"enable_ecc\" or \"disable_ecc\" as argument." + fi +} + + +fix_test_scripts $1 diff --git a/security/nss/tests/tools/ectools.sh b/security/nss/tests/tools/ectools.sh new file mode 100644 index 000000000000..d3ce81fa46ae --- /dev/null +++ b/security/nss/tests/tools/ectools.sh @@ -0,0 +1,210 @@ +#! /bin/sh +# +# 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 Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Portions created by Sun Microsystems, Inc. are Copyright (C) 2003 +# Sun Microsystems, Inc. All Rights Reserved. +# +# Contributor(s): +# Dr Vipul Gupta , Sun Microsystems Laboratories +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# +######################################################################## +# +# mozilla/security/nss/tests/tools/tools.sh +# +# Script to test basic functionallity of NSS tools +# +# needs to work on all Unix and Windows platforms +# +# tests implemented: +# pk12util +# signtool +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +######################################################################## + +############################## tools_init ############################## +# local shell function to initialize this script +######################################################################## +tools_init() +{ + SCRIPTNAME=tools.sh # sourced - $0 would point to all.sh + + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + + if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then + cd ../common + . ./init.sh + fi + if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here + cd ../cert + . ./cert.sh + fi + SCRIPTNAME=tools.sh + html_head "Tools Tests" + + grep "SUCCESS: SMIME passed" $CERT_LOG_FILE >/dev/null || { + Exit 15 "Fatal - S/MIME of cert.sh needs to pass first" + } + + TOOLSDIR=${HOSTDIR}/tools + COPYDIR=${TOOLSDIR}/copydir + + R_TOOLSDIR=../tools + R_COPYDIR=../tools/copydir + P_R_COPYDIR=${R_COPYDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_COPYDIR="multiaccess:Tools.$version" + fi + + mkdir -p ${TOOLSDIR} + mkdir -p ${COPYDIR} + mkdir -p ${TOOLSDIR}/html + cp ${QADIR}/tools/sign*.html ${TOOLSDIR}/html + + cd ${TOOLSDIR} +} + +############################## tools_p12 ############################### +# local shell function to test basic functionality of pk12util +######################################################################## +tools_p12() +{ + echo "$SCRIPTNAME: Exporting Alice's email cert & key------------------" + echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" + echo " -w ${R_PWFILE}" + pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ + -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Exporting Alice's email cert & key (pk12util -o)" + check_tmpfile + + echo "$SCRIPTNAME: Importing Alice's email cert & key -----------------" + echo "pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Importing Alice's email cert & key (pk12util -i)" + check_tmpfile + + echo "$SCRIPTNAME: Exporting Alice's email EC cert & key---------------" + echo "pk12util -o Alice-ec.p12 -n \"Alice-ec\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" + echo " -w ${R_PWFILE}" + pk12util -o Alice-ec.p12 -n "Alice-ec" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ + -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Exporting Alice's email EC cert & key (pk12util -o)" + check_tmpfile + + echo "$SCRIPTNAME: Importing Alice's email EC cert & key --------------" + echo "pk12util -i Alice-ec.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice-ec.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Importing Alice's email EC cert & key (pk12util -i)" + check_tmpfile + +} + +############################## tools_sign ############################## +# local shell function pk12util uses a hardcoded tmp file, if this exists +# and is owned by another user we don't get reasonable errormessages +######################################################################## +check_tmpfile() +{ + if [ $ret != "0" -a -f /tmp/Pk12uTemp ] ; then + echo "Error: pk12util temp file exists. Please remove this file and" + echo " rerun the test (/tmp/Pk12uTemp) " + fi +} + +############################## tools_sign ############################## +# local shell function to test basic functionality of signtool +######################################################################## +tools_sign() +{ + echo "$SCRIPTNAME: Create objsign cert -------------------------------" + echo "signtool -G \"objectsigner\" -d ${P_R_ALICEDIR} -p \"nss\"" + signtool -G "objsigner" -d ${P_R_ALICEDIR} -p "nss" 2>&1 <
" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +tools_init + +tools_p12 + +tools_sign +tools_cleanup + + diff --git a/security/nss/tests/tools/noectools.sh b/security/nss/tests/tools/noectools.sh new file mode 100644 index 000000000000..b301fc72b62c --- /dev/null +++ b/security/nss/tests/tools/noectools.sh @@ -0,0 +1,189 @@ +#! /bin/sh +# +# 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 Netscape security libraries. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1994-2000 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): +# +# Alternatively, the contents of this file may be used under the +# terms of the GNU General Public License Version 2 or later (the +# "GPL"), in which case the provisions of the GPL are applicable +# instead of those above. If you wish to allow use of your +# version of this file only under the terms of the GPL and not to +# allow others to use your version of this file under the MPL, +# indicate your decision by deleting the provisions above and +# replace them with the notice and other provisions required by +# the GPL. If you do not delete the provisions above, a recipient +# may use your version of this file under either the MPL or the +# GPL. +# +# +######################################################################## +# +# mozilla/security/nss/tests/tools/tools.sh +# +# Script to test basic functionallity of NSS tools +# +# needs to work on all Unix and Windows platforms +# +# tests implemented: +# pk12util +# signtool +# +# special strings +# --------------- +# FIXME ... known problems, search for this string +# NOTE .... unexpected behavior +# +######################################################################## + +############################## tools_init ############################## +# local shell function to initialize this script +######################################################################## +tools_init() +{ + SCRIPTNAME=tools.sh # sourced - $0 would point to all.sh + + if [ -z "${CLEANUP}" ] ; then # if nobody else is responsible for + CLEANUP="${SCRIPTNAME}" # cleaning this script will do it + fi + + if [ -z "${INIT_SOURCED}" -o "${INIT_SOURCED}" != "TRUE" ]; then + cd ../common + . ./init.sh + fi + if [ ! -r $CERT_LOG_FILE ]; then # we need certificates here + cd ../cert + . ./cert.sh + fi + SCRIPTNAME=tools.sh + html_head "Tools Tests" + + grep "SUCCESS: SMIME passed" $CERT_LOG_FILE >/dev/null || { + Exit 15 "Fatal - S/MIME of cert.sh needs to pass first" + } + + TOOLSDIR=${HOSTDIR}/tools + COPYDIR=${TOOLSDIR}/copydir + + R_TOOLSDIR=../tools + R_COPYDIR=../tools/copydir + P_R_COPYDIR=${R_COPYDIR} + if [ -n "${MULTIACCESS_DBM}" ]; then + P_R_COPYDIR="multiaccess:Tools.$version" + fi + + mkdir -p ${TOOLSDIR} + mkdir -p ${COPYDIR} + mkdir -p ${TOOLSDIR}/html + cp ${QADIR}/tools/sign*.html ${TOOLSDIR}/html + + cd ${TOOLSDIR} +} + +############################## tools_p12 ############################### +# local shell function to test basic functionality of pk12util +######################################################################## +tools_p12() +{ + echo "$SCRIPTNAME: Exporting Alice's email cert & key------------------" + echo "pk12util -o Alice.p12 -n \"Alice\" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \\" + echo " -w ${R_PWFILE}" + pk12util -o Alice.p12 -n "Alice" -d ${P_R_ALICEDIR} -k ${R_PWFILE} \ + -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Exporting Alice's email cert & key (pk12util -o)" + check_tmpfile + + echo "$SCRIPTNAME: Importing Alice's email cert & key -----------------" + echo "pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE}" + pk12util -i Alice.p12 -d ${P_R_COPYDIR} -k ${R_PWFILE} -w ${R_PWFILE} 2>&1 + ret=$? + html_msg $ret 0 "Importing Alice's email cert & key (pk12util -i)" + check_tmpfile +} + +############################## tools_sign ############################## +# local shell function pk12util uses a hardcoded tmp file, if this exists +# and is owned by another user we don't get reasonable errormessages +######################################################################## +check_tmpfile() +{ + if [ $ret != "0" -a -f /tmp/Pk12uTemp ] ; then + echo "Error: pk12util temp file exists. Please remove this file and" + echo " rerun the test (/tmp/Pk12uTemp) " + fi +} + +############################## tools_sign ############################## +# local shell function to test basic functionality of signtool +######################################################################## +tools_sign() +{ + echo "$SCRIPTNAME: Create objsign cert -------------------------------" + echo "signtool -G \"objectsigner\" -d ${P_R_ALICEDIR} -p \"nss\"" + signtool -G "objsigner" -d ${P_R_ALICEDIR} -p "nss" 2>&1 <
" + cd ${QADIR} + . common/cleanup.sh +} + +################## main ################################################# + +tools_init + +tools_p12 + +tools_sign +tools_cleanup + +