6840752: Provide out-of-the-box support for ECC algorithms
authorvinnie
Tue Aug 11 16:52:26 2009 +0100 (3 years ago)
changeset 15451ff7163fc5f7
parent 153388229bdd8aae
child 1546485d3eb9b50b
6840752: Provide out-of-the-box support for ECC algorithms
Reviewed-by: alanb, mullan, wetmore
make/sun/security/Makefile
make/sun/security/ec/FILES_c.gmk
make/sun/security/ec/Makefile
make/sun/security/ec/mapfile-vers
make/sun/security/other/Makefile
src/share/classes/sun/security/ec/ECDHKeyAgreement.java
src/share/classes/sun/security/ec/ECDSASignature.java
src/share/classes/sun/security/ec/ECKeyPairGenerator.java
src/share/classes/sun/security/ec/SunEC.java
src/share/classes/sun/security/ec/SunECEntries.java
src/share/lib/security/java.security
src/share/lib/security/java.security-solaris
src/share/lib/security/java.security-windows
src/share/native/sun/security/ec/ECC_JNI.cpp
src/share/native/sun/security/ec/ec.c
src/share/native/sun/security/ec/ec.h
src/share/native/sun/security/ec/ec2.h
src/share/native/sun/security/ec/ec2_163.c
src/share/native/sun/security/ec/ec2_193.c
src/share/native/sun/security/ec/ec2_233.c
src/share/native/sun/security/ec/ec2_aff.c
src/share/native/sun/security/ec/ec2_mont.c
src/share/native/sun/security/ec/ec_naf.c
src/share/native/sun/security/ec/ecc_impl.h
src/share/native/sun/security/ec/ecdecode.c
src/share/native/sun/security/ec/ecl-curve.h
src/share/native/sun/security/ec/ecl-exp.h
src/share/native/sun/security/ec/ecl-priv.h
src/share/native/sun/security/ec/ecl.c
src/share/native/sun/security/ec/ecl.h
src/share/native/sun/security/ec/ecl_curve.c
src/share/native/sun/security/ec/ecl_gf.c
src/share/native/sun/security/ec/ecl_mult.c
src/share/native/sun/security/ec/ecp.h
src/share/native/sun/security/ec/ecp_192.c
src/share/native/sun/security/ec/ecp_224.c
src/share/native/sun/security/ec/ecp_256.c
src/share/native/sun/security/ec/ecp_384.c
src/share/native/sun/security/ec/ecp_521.c
src/share/native/sun/security/ec/ecp_aff.c
src/share/native/sun/security/ec/ecp_jac.c
src/share/native/sun/security/ec/ecp_jm.c
src/share/native/sun/security/ec/ecp_mont.c
src/share/native/sun/security/ec/logtab.h
src/share/native/sun/security/ec/mp_gf2m-priv.h
src/share/native/sun/security/ec/mp_gf2m.c
src/share/native/sun/security/ec/mp_gf2m.h
src/share/native/sun/security/ec/mpi-config.h
src/share/native/sun/security/ec/mpi-priv.h
src/share/native/sun/security/ec/mpi.c
src/share/native/sun/security/ec/mpi.h
src/share/native/sun/security/ec/mplogic.c
src/share/native/sun/security/ec/mplogic.h
src/share/native/sun/security/ec/mpmontg.c
src/share/native/sun/security/ec/mpprime.h
src/share/native/sun/security/ec/oid.c
src/share/native/sun/security/ec/secitem.c
src/share/native/sun/security/ec/secoidt.h
test/sun/security/ec/TestEC.java
test/sun/security/ec/p12passwords.txt
test/sun/security/ec/pkcs12/secp256r1server-secp384r1ca.p12
test/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12
--- a/make/sun/security/Makefile Fri Aug 07 18:15:03 2009 +0100
+++ b/make/sun/security/Makefile Tue Aug 11 16:52:26 2009 +0100
@@ -1,5 +1,5 @@
#
-# Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@ ifeq ($(PLATFORM), windows)
endif
endif
-SUBDIRS = other action util tools jgss krb5 smartcardio $(PKCS11) \
+SUBDIRS = ec other action util tools jgss krb5 smartcardio $(PKCS11) \
$(JGSS_WRAPPER) $(MSCAPI)
all build clean clobber::
--- a/make/sun/security/other/Makefile Fri Aug 07 18:15:03 2009 +0100
+++ b/make/sun/security/other/Makefile Tue Aug 11 16:52:26 2009 +0100
@@ -1,5 +1,5 @@
#
-# Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -33,7 +33,6 @@ include $(BUILDDIR)/common/Defs.gmk
#
AUTO_FILES_JAVA_DIRS = \
sun/security/acl \
- sun/security/ec \
sun/security/jca \
sun/security/pkcs \
sun/security/pkcs12 \
--- a/src/share/lib/security/java.security Fri Aug 07 18:15:03 2009 +0100
+++ b/src/share/lib/security/java.security Tue Aug 11 16:52:26 2009 +0100
@@ -45,12 +45,13 @@
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
-security.provider.3=com.sun.net.ssl.internal.ssl.Provider
-security.provider.4=com.sun.crypto.provider.SunJCE
-security.provider.5=sun.security.jgss.SunProvider
-security.provider.6=com.sun.security.sasl.Provider
-security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
-security.provider.8=sun.security.smartcardio.SunPCSC
+security.provider.3=sun.security.ec.SunEC
+security.provider.4=com.sun.net.ssl.internal.ssl.Provider
+security.provider.5=com.sun.crypto.provider.SunJCE
+security.provider.6=sun.security.jgss.SunProvider
+security.provider.7=com.sun.security.sasl.Provider
+security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
+security.provider.9=sun.security.smartcardio.SunPCSC
#
# Select the source of seed data for SecureRandom. By default an
--- a/src/share/lib/security/java.security-solaris Fri Aug 07 18:15:03 2009 +0100
+++ b/src/share/lib/security/java.security-solaris Tue Aug 11 16:52:26 2009 +0100
@@ -46,12 +46,13 @@ security.provider.1=sun.security.pkcs11.
security.provider.1=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-solaris.cfg
security.provider.2=sun.security.provider.Sun
security.provider.3=sun.security.rsa.SunRsaSign
-security.provider.4=com.sun.net.ssl.internal.ssl.Provider
-security.provider.5=com.sun.crypto.provider.SunJCE
-security.provider.6=sun.security.jgss.SunProvider
-security.provider.7=com.sun.security.sasl.Provider
-security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
-security.provider.9=sun.security.smartcardio.SunPCSC
+security.provider.4=sun.security.ec.SunEC
+security.provider.5=com.sun.net.ssl.internal.ssl.Provider
+security.provider.6=com.sun.crypto.provider.SunJCE
+security.provider.7=sun.security.jgss.SunProvider
+security.provider.8=com.sun.security.sasl.Provider
+security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
+security.provider.10=sun.security.smartcardio.SunPCSC
#
# Select the source of seed data for SecureRandom. By default an
--- a/src/share/lib/security/java.security-windows Fri Aug 07 18:15:03 2009 +0100
+++ b/src/share/lib/security/java.security-windows Tue Aug 11 16:52:26 2009 +0100
@@ -45,13 +45,14 @@
#
security.provider.1=sun.security.provider.Sun
security.provider.2=sun.security.rsa.SunRsaSign
-security.provider.3=com.sun.net.ssl.internal.ssl.Provider
-security.provider.4=com.sun.crypto.provider.SunJCE
-security.provider.5=sun.security.jgss.SunProvider
-security.provider.6=com.sun.security.sasl.Provider
-security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
-security.provider.8=sun.security.smartcardio.SunPCSC
-security.provider.9=sun.security.mscapi.SunMSCAPI
+security.provider.3=sun.security.ec.SunEC
+security.provider.4=com.sun.net.ssl.internal.ssl.Provider
+security.provider.5=com.sun.crypto.provider.SunJCE
+security.provider.6=sun.security.jgss.SunProvider
+security.provider.7=com.sun.security.sasl.Provider
+security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
+security.provider.9=sun.security.smartcardio.SunPCSC
+security.provider.10=sun.security.mscapi.SunMSCAPI
#
# Select the source of seed data for SecureRandom. By default an
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/security/ec/FILES_c.gmk Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,54 @@
+#
+# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+FILES_c = \
+ ec.c \
+ ec2_163.c \
+ ec2_193.c \
+ ec2_233.c \
+ ec2_aff.c \
+ ec2_mont.c \
+ ecdecode.c \
+ ecl.c \
+ ecl_curve.c \
+ ecl_gf.c \
+ ecl_mult.c \
+ ec_naf.c \
+ ecp_192.c \
+ ecp_224.c \
+ ecp_256.c \
+ ecp_384.c \
+ ecp_521.c \
+ ecp_aff.c \
+ ecp_jac.c \
+ ecp_jm.c \
+ ecp_mont.c \
+ mp_gf2m.c \
+ mpi.c \
+ mplogic.c \
+ mpmontg.c \
+ oid.c \
+ secitem.c
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/security/ec/Makefile Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,319 @@
+#
+# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+#
+# Makefile for building sunec.jar and sunecc native library.
+#
+# This file was derived from make/com/sun/crypto/provider/Makefile.
+#
+
+#
+# (The terms "OpenJDK" and "JDK" below refer to OpenJDK and Sun JDK builds
+# respectively.)
+#
+# JCE builds are very different between OpenJDK and JDK. The OpenJDK JCE
+# jar files do not require signing, but those for JDK do. If an unsigned
+# jar file is installed into JDK, things will break when the crypto
+# routines are called.
+#
+# This Makefile does the "real" build of the JCE files. For OpenJDK,
+# the jar files built here are installed directly into the OpenJDK.
+#
+# For JDK, the binaries use pre-built/pre-signed binary files stored in
+# the closed workspace that are not shipped in the OpenJDK workspaces.
+# We still build the JDK files here to verify the files compile, and in
+# preparation for possible signing. Developers working on JCE in JDK
+# must sign the JCE files before testing. The JCE signing key is kept
+# separate from the JDK workspace to prevent its disclosure.
+#
+# SPECIAL NOTE TO JCE/JDK developers: The source files must eventually
+# be built, signed, and then the resulting jar files MUST BE CHECKED
+# INTO THE CLOSED PART OF THE WORKSPACE*. This separate step *MUST NOT
+# BE FORGOTTEN*, otherwise a bug fixed in the source code will not be
+# reflected in the shipped binaries. The "release" target should be
+# used to generate the required files.
+#
+# There are a number of targets to help both JDK/OpenJDK developers.
+#
+# Main Targets (JDK/OPENJDK):
+#
+# all/clobber/clean The usual, plus the native libraries.
+# If OpenJDK, installs sunec.jar.
+# If JDK, installs prebuilt
+# sunec.jar.
+#
+# jar Builds/installs sunec.jar
+# If OpenJDK, does not sign.
+# If JDK, tries to sign.
+#
+# Other lesser-used Targets (JDK/OPENJDK):
+#
+# build-jar Builds sunec.jar
+# (does not sign/install)
+#
+# install-jar Alias for "jar" above.
+#
+# Other targets (JDK only):
+#
+# sign Alias for sign-jar
+# sign-jar Builds/signs sunec.jar (no install)
+#
+# release Builds all targets in preparation
+# for workspace integration.
+#
+# install-prebuilt Installs the pre-built jar files
+#
+# This makefile was written to support parallel target execution.
+#
+
+BUILDDIR = ../../..
+PACKAGE = sun.security.ec
+PRODUCT = sun
+
+#
+# The following is for when we need to do postprocessing
+# (signing) against a read-only build. If the OUTPUTDIR
+# isn't writable, the build currently crashes out.
+#
+ifndef OPENJDK
+ ifdef ALT_JCE_BUILD_DIR
+ # =====================================================
+ # Where to place the output, in case we're building from a read-only
+ # build area. (e.g. a release engineering build.)
+ JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
+ IGNORE_WRITABLE_OUTPUTDIR_TEST=true
+ else
+ JCE_BUILD_DIR=${TEMPDIR}
+ endif
+endif
+
+include $(BUILDDIR)/common/Defs.gmk
+
+#
+# Location for the newly built classfiles.
+#
+CLASSDESTDIR = $(TEMPDIR)/classes
+
+#
+# Java files
+#
+AUTO_FILES_JAVA_DIRS = $(PKGDIR)
+
+include $(BUILDDIR)/common/Classes.gmk
+
+#
+# Some licensees do not get the native ECC sources, but we still need to
+# be able to build "all" for them. Check here to see if the sources are
+# available. If not, then skip them.
+#
+
+NATIVE_ECC_AVAILABLE := $(shell \
+ if [ -d $(SHARE_SRC)/native/$(PKGDIR) ] ; then \
+ $(ECHO) true; \
+ else \
+ $(ECHO) false; \
+ fi)
+
+ifeq ($(NATIVE_ECC_AVAILABLE), true)
+
+ LIBRARY = sunecc
+
+ #
+ # Java files that define native methods
+ #
+ FILES_export = \
+ $(PKGDIR)/ECDHKeyAgreement.java \
+ $(PKGDIR)/ECDSASignature.java \
+ $(PKGDIR)/ECKeyPairGenerator.java
+
+ JAVAHFLAGS += -classpath $(CLASSDESTDIR)
+
+ #
+ # C and C++ files
+ #
+ include FILES_c.gmk
+
+ FILES_cpp = ECC_JNI.cpp
+
+ CPLUSPLUSLIBRARY=true
+
+ FILES_m = mapfile-vers
+
+ #
+ # Find native code
+ #
+ vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)
+
+ vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
+
+ #
+ # Find include files
+ #
+ OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)
+
+ #
+ # Compiler flags
+ #
+ OTHER_CFLAGS += -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B
+
+ #
+ # Libraries to link
+ #
+ ifeq ($(PLATFORM), windows)
+ OTHER_LDLIBS += $(JVMLIB)
+ else
+ OTHER_LDLIBS = -ldl $(JVMLIB) $(LIBCXX)
+ endif
+
+ include $(BUILDDIR)/common/Mapfile-vers.gmk
+
+ include $(BUILDDIR)/common/Library.gmk
+
+endif # NATIVE_ECC_AVAILABLE
+
+#
+# We use a variety of subdirectories in the $(TEMPDIR) depending on what
+# part of the build we're doing. Both OPENJDK/JDK builds are initially
+# done in the unsigned area. When files are signed in JDK,
+# they will be placed in the appropriate area.
+#
+UNSIGNED_DIR = $(TEMPDIR)/unsigned
+
+include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
+
+#
+# Rules
+#
+
+ifdef OPENJDK
+all: build-jar install-jar
+else
+all: build-jar install-prebuilt
+ $(build-warning)
+endif
+
+
+# =====================================================
+# Build the unsigned sunec.jar file.
+#
+
+JAR_DESTFILE = $(EXTDIR)/sunec.jar
+
+#
+# Since the -C option to jar is used below, each directory entry must be
+# preceded with the appropriate directory to "cd" into.
+#
+JAR_DIRS = $(patsubst %, -C $(CLASSDESTDIR) %, $(AUTO_FILES_JAVA_DIRS))
+
+build-jar: $(UNSIGNED_DIR)/sunec.jar
+
+#
+# Build sunec.jar.
+#
+$(UNSIGNED_DIR)/sunec.jar: build
+ $(prep-target)
+ $(BOOT_JAR_CMD) cf $@ $(JAR_DIRS) \
+ $(BOOT_JAR_JFLAGS)
+ @$(java-vm-cleanup)
+
+
+ifndef OPENJDK
+# =====================================================
+# Sign the provider jar file. Not needed for OpenJDK.
+#
+
+SIGNED_DIR = $(JCE_BUILD_DIR)/signed
+
+sign: sign-jar
+
+sign-jar: $(SIGNED_DIR)/sunec.jar
+
+ifndef ALT_JCE_BUILD_DIR
+$(SIGNED_DIR)/sunec.jar: $(UNSIGNED_DIR)/sunec.jar
+else
+#
+# We have to remove the build dependency, otherwise, we'll try to rebuild it
+# which we can't do on a read-only filesystem.
+#
+$(SIGNED_DIR)/sunec.jar:
+ @if [ ! -r $(UNSIGNED_DIR)/sunec.jar ] ; then \
+ $(ECHO) "Couldn't find $(UNSIGNED_DIR)/sunec.jar"; \
+ exit 1; \
+ fi
+endif
+ $(call sign-file, $(UNSIGNED_DIR)/sunec.jar)
+
+
+# =====================================================
+# Create the Release Engineering files. Signed builds, etc.
+#
+
+release: $(SIGNED_DIR)/sunec.jar
+ $(RM) $(JCE_BUILD_DIR)/release/sunec.jar
+ $(MKDIR) -p $(JCE_BUILD_DIR)/release
+ $(CP) $(SIGNED_DIR)/sunec.jar $(JCE_BUILD_DIR)/release
+ $(release-warning)
+
+endif # OPENJDK
+
+
+# =====================================================
+# Install routines.
+#
+
+#
+# Install sunec.jar, depending on which type is requested.
+#
+install-jar jar: $(JAR_DESTFILE)
+ifndef OPENJDK
+ $(release-warning)
+endif
+
+ifdef OPENJDK
+$(JAR_DESTFILE): $(UNSIGNED_DIR)/sunec.jar
+else
+$(JAR_DESTFILE): $(SIGNED_DIR)/sunec.jar
+endif
+ $(install-file)
+
+ifndef OPENJDK
+install-prebuilt:
+ @$(ECHO) "\n>>>Installing prebuilt SunEC provider..."
+ $(RM) $(JAR_DESTFILE)
+ $(CP) $(PREBUILT_DIR)/ec/sunec.jar $(JAR_DESTFILE)
+endif
+
+
+# =====================================================
+# Support routines.
+#
+
+clobber clean::
+ $(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
+
+.PHONY: build-jar jar install-jar
+ifndef OPENJDK
+.PHONY: sign sign-jar release install-prebuilt
+endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/make/sun/security/ec/mapfile-vers Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,37 @@
+#
+# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation. Sun designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Sun in the LICENSE file that accompanied this code.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# Define public interface.
+
+SUNWprivate_1.1 {
+ global:
+ Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair;
+ Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes;
+ Java_sun_security_ec_ECDSASignature_signDigest;
+ Java_sun_security_ec_ECDSASignature_verifySignedDigest;
+ Java_sun_security_ec_ECDHKeyAgreement_deriveKey;
+ local:
+ *;
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ec/ECDHKeyAgreement.java Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.ec;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+/**
+ * KeyAgreement implementation for ECDH.
+ *
+ * @since 1.7
+ */
+public final class ECDHKeyAgreement extends KeyAgreementSpi {
+
+ // flag indicating whether the native ECC implementation is present
+ private static boolean implementationPresent = true;
+ static {
+ try {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("sunecc");
+ return null;
+ }
+ });
+ } catch (UnsatisfiedLinkError e) {
+ implementationPresent = false;
+ }
+ }
+
+ // private key, if initialized
+ private ECPrivateKey privateKey;
+
+ // encoded public point, non-null between doPhase() & generateSecret() only
+ private byte[] publicValue;
+
+ // length of the secret to be derived
+ private int secretLen;
+
+ /**
+ * Constructs a new ECDHKeyAgreement.
+ *
+ * @exception ProviderException if the native ECC library is unavailable.
+ */
+ public ECDHKeyAgreement() {
+ if (!implementationPresent) {
+ throw new ProviderException("ECDH implementation is not available");
+ }
+ }
+
+ // see JCE spec
+ protected void engineInit(Key key, SecureRandom random)
+ throws InvalidKeyException {
+ if (!(key instanceof PrivateKey)) {
+ throw new InvalidKeyException
+ ("Key must be instance of PrivateKey");
+ }
+ privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
+ publicValue = null;
+ }
+
+ // see JCE spec
+ protected void engineInit(Key key, AlgorithmParameterSpec params,
+ SecureRandom random) throws InvalidKeyException,
+ InvalidAlgorithmParameterException {
+ if (params != null) {
+ throw new InvalidAlgorithmParameterException
+ ("Parameters not supported");
+ }
+ engineInit(key, random);
+ }
+
+ // see JCE spec
+ protected Key engineDoPhase(Key key, boolean lastPhase)
+ throws InvalidKeyException, IllegalStateException {
+ if (privateKey == null) {
+ throw new IllegalStateException("Not initialized");
+ }
+ if (publicValue != null) {
+ throw new IllegalStateException("Phase already executed");
+ }
+ if (!lastPhase) {
+ throw new IllegalStateException
+ ("Only two party agreement supported, lastPhase must be true");
+ }
+ if (!(key instanceof ECPublicKey)) {
+ throw new InvalidKeyException
+ ("Key must be a PublicKey with algorithm EC");
+ }
+
+ ECPublicKey ecKey = (ECPublicKey)key;
+ ECParameterSpec params = ecKey.getParams();
+
+ if (ecKey instanceof ECPublicKeyImpl) {
+ publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
+ } else { // instanceof ECPublicKey
+ publicValue =
+ ECParameters.encodePoint(ecKey.getW(), params.getCurve());
+ }
+ int keyLenBits = params.getCurve().getField().getFieldSize();
+ secretLen = (keyLenBits + 7) >> 3;
+
+ return null;
+ }
+
+ // see JCE spec
+ protected byte[] engineGenerateSecret() throws IllegalStateException {
+ if ((privateKey == null) || (publicValue == null)) {
+ throw new IllegalStateException("Not initialized correctly");
+ }
+
+ byte[] s = privateKey.getS().toByteArray();
+ byte[] encodedParams =
+ ECParameters.encodeParameters(privateKey.getParams()); // DER OID
+
+ try {
+
+ return deriveKey(s, publicValue, encodedParams);
+
+ } catch (GeneralSecurityException e) {
+ throw new ProviderException("Could not derive key", e);
+ }
+
+ }
+
+ // see JCE spec
+ protected int engineGenerateSecret(byte[] sharedSecret, int
+ offset) throws IllegalStateException, ShortBufferException {
+ if (offset + secretLen > sharedSecret.length) {
+ throw new ShortBufferException("Need " + secretLen
+ + " bytes, only " + (sharedSecret.length - offset) + " available");
+ }
+ byte[] secret = engineGenerateSecret();
+ System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
+ return secret.length;
+ }
+
+ // see JCE spec
+ protected SecretKey engineGenerateSecret(String algorithm)
+ throws IllegalStateException, NoSuchAlgorithmException,
+ InvalidKeyException {
+ if (algorithm == null) {
+ throw new NoSuchAlgorithmException("Algorithm must not be null");
+ }
+ if (!(algorithm.equals("TlsPremasterSecret"))) {
+ throw new NoSuchAlgorithmException
+ ("Only supported for algorithm TlsPremasterSecret");
+ }
+ return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
+ }
+
+ /**
+ * Generates a secret key using the public and private keys.
+ *
+ * @param s the private key's S value.
+ * @param w the public key's W point (in uncompressed form).
+ * @param encodedParams the curve's DER encoded object identifier.
+ *
+ * @return byte[] the secret key.
+ */
+ private static native byte[] deriveKey(byte[] s, byte[] w,
+ byte[] encodedParams) throws GeneralSecurityException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ec/ECDSASignature.java Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,447 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.ec;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.math.BigInteger;
+import java.util.Arrays;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.*;
+
+import sun.security.jca.JCAUtil;
+import sun.security.util.*;
+import sun.security.x509.AlgorithmId;
+
+/**
+ * ECDSA signature implementation. This class currently supports the
+ * following algorithm names:
+ *
+ * . "NONEwithECDSA"
+ * . "SHA1withECDSA"
+ * . "SHA256withECDSA"
+ * . "SHA384withECDSA"
+ * . "SHA512withECDSA"
+ *
+ * @since 1.7
+ */
+abstract class ECDSASignature extends SignatureSpi {
+
+ // flag indicating whether the native ECC implementation is present
+ private static boolean implementationPresent = true;
+ static {
+ try {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("sunecc");
+ return null;
+ }
+ });
+ } catch (UnsatisfiedLinkError e) {
+ implementationPresent = false;
+ }
+ }
+
+ // message digest implementation we use
+ private final MessageDigest messageDigest;
+
+ // supplied entropy
+ private SecureRandom random;
+
+ // flag indicating whether the digest has been reset
+ private boolean needsReset;
+
+ // private key, if initialized for signing
+ private ECPrivateKey privateKey;
+
+ // public key, if initialized for verifying
+ private ECPublicKey publicKey;
+
+ /**
+ * Constructs a new ECDSASignature. Used by Raw subclass.
+ *
+ * @exception ProviderException if the native ECC library is unavailable.
+ */
+ ECDSASignature() {
+ if (!implementationPresent) {
+ throw new
+ ProviderException("ECDSA implementation is not available");
+ }
+ messageDigest = null;
+ }
+
+ /**
+ * Constructs a new ECDSASignature. Used by subclasses.
+ *
+ * @exception ProviderException if the native ECC library is unavailable.
+ */
+ ECDSASignature(String digestName) {
+ if (!implementationPresent) {
+ throw new
+ ProviderException("ECDSA implementation is not available");
+ }
+
+ try {
+ messageDigest = MessageDigest.getInstance(digestName);
+ } catch (NoSuchAlgorithmException e) {
+ throw new ProviderException(e);
+ }
+ needsReset = false;
+ }
+
+ // Nested class for NONEwithECDSA signatures
+ public static final class Raw extends ECDSASignature {
+
+ // the longest supported digest is 512 bits (SHA-512)
+ private static final int RAW_ECDSA_MAX = 64;
+
+ private final byte[] precomputedDigest;
+ private int offset = 0;
+
+ public Raw() {
+ precomputedDigest = new byte[RAW_ECDSA_MAX];
+ }
+
+ // Stores the precomputed message digest value.
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ if (offset >= precomputedDigest.length) {
+ offset = RAW_ECDSA_MAX + 1;
+ return;
+ }
+ precomputedDigest[offset++] = b;
+ }
+
+ // Stores the precomputed message digest value.
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ if (offset >= precomputedDigest.length) {
+ offset = RAW_ECDSA_MAX + 1;
+ return;
+ }
+ System.arraycopy(b, off, precomputedDigest, offset, len);
+ offset += len;
+ }
+
+ // Stores the precomputed message digest value.
+ @Override
+ protected void engineUpdate(ByteBuffer byteBuffer) {
+ int len = byteBuffer.remaining();
+ if (len <= 0) {
+ return;
+ }
+ if (offset + len >= precomputedDigest.length) {
+ offset = RAW_ECDSA_MAX + 1;
+ return;
+ }
+ byteBuffer.get(precomputedDigest, offset, len);
+ offset += len;
+ }
+
+ @Override
+ protected void resetDigest(){
+ offset = 0;
+ }
+
+ // Returns the precomputed message digest value.
+ @Override
+ protected byte[] getDigestValue() throws SignatureException {
+ if (offset > RAW_ECDSA_MAX) {
+ throw new SignatureException("Message digest is too long");
+
+ }
+ byte[] result = new byte[offset];
+ System.arraycopy(precomputedDigest, 0, result, 0, offset);
+ offset = 0;
+
+ return result;
+ }
+ }
+
+ // Nested class for SHA1withECDSA signatures
+ public static final class SHA1 extends ECDSASignature {
+ public SHA1() {
+ super("SHA1");
+ }
+ }
+
+ // Nested class for SHA256withECDSA signatures
+ public static final class SHA256 extends ECDSASignature {
+ public SHA256() {
+ super("SHA-256");
+ }
+ }
+
+ // Nested class for SHA384withECDSA signatures
+ public static final class SHA384 extends ECDSASignature {
+ public SHA384() {
+ super("SHA-384");
+ }
+ }
+
+ // Nested class for SHA512withECDSA signatures
+ public static final class SHA512 extends ECDSASignature {
+ public SHA512() {
+ super("SHA-512");
+ }
+ }
+
+ // initialize for verification. See JCA doc
+ @Override
+ protected void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
+
+ // Should check that the supplied key is appropriate for signature
+ // algorithm (e.g. P-256 for SHA256withECDSA)
+ this.privateKey = null;
+ resetDigest();
+ }
+
+ // initialize for signing. See JCA doc
+ @Override
+ protected void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ engineInitSign(privateKey, null);
+ }
+
+ // initialize for signing. See JCA doc
+ @Override
+ protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
+ throws InvalidKeyException {
+ this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
+
+ // Should check that the supplied key is appropriate for signature
+ // algorithm (e.g. P-256 for SHA256withECDSA)
+ this.publicKey = null;
+ this.random = random;
+ resetDigest();
+ }
+
+ /**
+ * Resets the message digest if needed.
+ */
+ protected void resetDigest() {
+ if (needsReset) {
+ if (messageDigest != null) {
+ messageDigest.reset();
+ }
+ needsReset = false;
+ }
+ }
+
+ /**
+ * Returns the message digest value.
+ */
+ protected byte[] getDigestValue() throws SignatureException {
+ needsReset = false;
+ return messageDigest.digest();
+ }
+
+ // update the signature with the plaintext data. See JCA doc
+ @Override
+ protected void engineUpdate(byte b) throws SignatureException {
+ messageDigest.update(b);
+ needsReset = true;
+ }
+
+ // update the signature with the plaintext data. See JCA doc
+ @Override
+ protected void engineUpdate(byte[] b, int off, int len)
+ throws SignatureException {
+ messageDigest.update(b, off, len);
+ needsReset = true;
+ }
+
+ // update the signature with the plaintext data. See JCA doc
+ @Override
+ protected void engineUpdate(ByteBuffer byteBuffer) {
+ int len = byteBuffer.remaining();
+ if (len <= 0) {
+ return;
+ }
+
+ messageDigest.update(byteBuffer);
+ needsReset = true;
+ }
+
+ // sign the data and return the signature. See JCA doc
+ @Override
+ protected byte[] engineSign() throws SignatureException {
+ byte[] s = privateKey.getS().toByteArray();
+ ECParameterSpec params = privateKey.getParams();
+ byte[] encodedParams = ECParameters.encodeParameters(params); // DER OID
+ int keySize = params.getCurve().getField().getFieldSize();
+
+ // seed is twice the key size (in bytes)
+ byte[] seed = new byte[((keySize + 7) >> 3) * 2];
+ if (random == null) {
+ random = JCAUtil.getSecureRandom();
+ }
+ random.nextBytes(seed);
+
+ try {
+
+ return encodeSignature(
+ signDigest(getDigestValue(), s, encodedParams, seed));
+
+ } catch (GeneralSecurityException e) {
+ throw new SignatureException("Could not sign data", e);
+ }
+ }
+
+ // verify the data and return the result. See JCA doc
+ @Override
+ protected boolean engineVerify(byte[] signature) throws SignatureException {
+
+ byte[] w;
+ ECParameterSpec params = publicKey.getParams();
+ byte[] encodedParams = ECParameters.encodeParameters(params); // DER OID
+
+ if (publicKey instanceof ECPublicKeyImpl) {
+ w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
+ } else { // instanceof ECPublicKey
+ w = ECParameters.encodePoint(publicKey.getW(), params.getCurve());
+ }
+
+ try {
+
+ return verifySignedDigest(
+ decodeSignature(signature), getDigestValue(), w, encodedParams);
+
+ } catch (GeneralSecurityException e) {
+ throw new SignatureException("Could not verify signature", e);
+ }
+ }
+
+ // set parameter, not supported. See JCA doc
+ @Override
+ protected void engineSetParameter(String param, Object value)
+ throws InvalidParameterException {
+ throw new UnsupportedOperationException("setParameter() not supported");
+ }
+
+ // get parameter, not supported. See JCA doc
+ @Override
+ protected Object engineGetParameter(String param)
+ throws InvalidParameterException {
+ throw new UnsupportedOperationException("getParameter() not supported");
+ }
+
+ // Convert the concatenation of R and S into their DER encoding
+ private byte[] encodeSignature(byte[] signature) throws SignatureException {
+ try {
+
+ int n = signature.length >> 1;
+ byte[] bytes = new byte[n];
+ System.arraycopy(signature, 0, bytes, 0, n);
+ BigInteger r = new BigInteger(1, bytes);
+ System.arraycopy(signature, n, bytes, 0, n);
+ BigInteger s = new BigInteger(1, bytes);
+
+ DerOutputStream out = new DerOutputStream(signature.length + 10);
+ out.putInteger(r);
+ out.putInteger(s);
+ DerValue result =
+ new DerValue(DerValue.tag_Sequence, out.toByteArray());
+
+ return result.toByteArray();
+
+ } catch (Exception e) {
+ throw new SignatureException("Could not encode signature", e);
+ }
+ }
+
+ // Convert the DER encoding of R and S into a concatenation of R and S
+ private byte[] decodeSignature(byte[] signature) throws SignatureException {
+
+ try {
+ DerInputStream in = new DerInputStream(signature);
+ DerValue[] values = in.getSequence(2);
+ BigInteger r = values[0].getPositiveBigInteger();
+ BigInteger s = values[1].getPositiveBigInteger();
+ // trim leading zeroes
+ byte[] rBytes = trimZeroes(r.toByteArray());
+ byte[] sBytes = trimZeroes(s.toByteArray());
+ int k = Math.max(rBytes.length, sBytes.length);
+ // r and s each occupy half the array
+ byte[] result = new byte[k << 1];
+ System.arraycopy(rBytes, 0, result, k - rBytes.length,
+ rBytes.length);
+ System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
+ sBytes.length);
+ return result;
+
+ } catch (Exception e) {
+ throw new SignatureException("Could not decode signature", e);
+ }
+ }
+
+ // trim leading (most significant) zeroes from the result
+ private static byte[] trimZeroes(byte[] b) {
+ int i = 0;
+ while ((i < b.length - 1) && (b[i] == 0)) {
+ i++;
+ }
+ if (i == 0) {
+ return b;
+ }
+ byte[] t = new byte[b.length - i];
+ System.arraycopy(b, i, t, 0, t.length);
+ return t;
+ }
+
+ /**
+ * Signs the digest using the private key.
+ *
+ * @param digest the digest to be signed.
+ * @param s the private key's S value.
+ * @param encodedParams the curve's DER encoded object identifier.
+ * @param seed the random seed.
+ *
+ * @return byte[] the signature.
+ */
+ private static native byte[] signDigest(byte[] digest, byte[] s,
+ byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
+
+ /**
+ * Verifies the signed digest using the public key.
+ *
+ * @param signedDigest the signature to be verified. It is encoded
+ * as a concatenation of the key's R and S values.
+ * @param digest the digest to be used.
+ * @param w the public key's W point (in uncompressed form).
+ * @param encodedParams the curve's DER encoded object identifier.
+ *
+ * @return boolean true if the signature is successfully verified.
+ */
+ private static native boolean verifySignedDigest(byte[] signature,
+ byte[] digest, byte[] w, byte[] encodedParams)
+ throws GeneralSecurityException;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.ec;
+
+import java.math.BigInteger;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.ECGenParameterSpec;
+import java.security.spec.ECParameterSpec;
+import java.security.spec.ECPoint;
+
+import sun.security.ec.NamedCurve;
+import sun.security.ec.ECParameters;
+import sun.security.ec.ECPrivateKeyImpl;
+import sun.security.ec.ECPublicKeyImpl;
+import sun.security.jca.JCAUtil;
+
+/**
+ * EC keypair generator.
+ * Standard algorithm, minimum key length is 112 bits, maximum is 571 bits.
+ *
+ * @since 1.7
+ */
+public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
+
+ // flag indicating whether the native ECC implementation is present
+ private static boolean implementationPresent = true;
+ static {
+ try {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
+ System.loadLibrary("sunecc");
+ return null;
+ }
+ });
+ } catch (UnsatisfiedLinkError e) {
+ implementationPresent = false;
+ }
+ }
+ private static final int KEY_SIZE_MIN = 112; // min bits (see ecc_impl.h)
+ private static final int KEY_SIZE_MAX = 571; // max bits (see ecc_impl.h)
+ private static final int KEY_SIZE_DEFAULT = 256;
+
+ // used to seed the keypair generator
+ private SecureRandom random;
+
+ // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
+ private int keySize;
+
+ // parameters specified via init, if any
+ private AlgorithmParameterSpec params = null;
+
+ /**
+ * Constructs a new ECKeyPairGenerator.
+ *
+ * @exception ProviderException if the native ECC library is unavailable.
+ */
+ public ECKeyPairGenerator() {
+ if (!implementationPresent) {
+ throw new ProviderException("EC implementation is not available");
+ }
+ // initialize to default in case the app does not call initialize()
+ initialize(KEY_SIZE_DEFAULT, null);
+ }
+
+ // initialize the generator. See JCA doc
+ @Override
+ public void initialize(int keySize, SecureRandom random) {
+
+ checkKeySize(keySize);
+ this.params = NamedCurve.getECParameterSpec(keySize);
+ if (params == null) {
+ throw new InvalidParameterException(
+ "No EC parameters available for key size " + keySize + " bits");
+ }
+ this.random = random;
+ }
+
+ // second initialize method. See JCA doc
+ @Override
+ public void initialize(AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidAlgorithmParameterException {
+
+ if (params instanceof ECParameterSpec) {
+ this.params = ECParameters.getNamedCurve((ECParameterSpec)params);
+ if (this.params == null) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported curve: " + params);
+ }
+ } else if (params instanceof ECGenParameterSpec) {
+ String name = ((ECGenParameterSpec)params).getName();
+ this.params = NamedCurve.getECParameterSpec(name);
+ if (this.params == null) {
+ throw new InvalidAlgorithmParameterException(
+ "Unknown curve name: " + name);
+ }
+ } else {
+ throw new InvalidAlgorithmParameterException(
+ "ECParameterSpec or ECGenParameterSpec required for EC");
+ }
+ this.keySize =
+ ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
+ this.random = random;
+ }
+
+ // generate the keypair. See JCA doc
+ @Override
+ public KeyPair generateKeyPair() {
+
+ byte[] encodedParams =
+ ECParameters.encodeParameters((ECParameterSpec)params);
+
+ // seed is twice the key size (in bytes)
+ byte[] seed = new byte[2 * ((keySize + 7) >> 3)];
+ if (random == null) {
+ random = JCAUtil.getSecureRandom();
+ }
+ random.nextBytes(seed);
+
+ long[] handles = generateECKeyPair(keySize, encodedParams, seed);
+
+ // The 'params' object supplied above is equivalent to the native one
+ // so there is no need to fetch it.
+
+ // handles[0] points to the native private key
+ BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
+
+ try {
+ PrivateKey privateKey =
+ new ECPrivateKeyImpl(s, (ECParameterSpec)params);
+
+ // handles[1] points to the native public key
+ ECPoint w = ECParameters.decodePoint(getEncodedBytes(handles[1]),
+ ((ECParameterSpec)params).getCurve());
+ PublicKey publicKey =
+ new ECPublicKeyImpl(w, (ECParameterSpec)params);
+
+ return new KeyPair(publicKey, privateKey);
+
+ } catch (Exception e) {
+ throw new ProviderException(e);
+ }
+ }
+
+ private void checkKeySize(int keySize) throws InvalidParameterException {
+ if (keySize < KEY_SIZE_MIN) {
+ throw new InvalidParameterException
+ ("Key size must be at least " + KEY_SIZE_MIN + " bits");
+ }
+ if (keySize > KEY_SIZE_MAX) {
+ throw new InvalidParameterException
+ ("Key size must be at most " + KEY_SIZE_MAX + " bits");
+ }
+ this.keySize = keySize;
+ }
+
+ /*
+ * Generates the keypair and returns a 2-element array of handles.
+ * The first handle points to the private key, the second to the public key.
+ */
+ private static native long[] generateECKeyPair(int keySize,
+ byte[] encodedParams, byte[] seed);
+
+ /*
+ * Extracts the encoded key data using the supplied handle.
+ */
+ private static native byte[] getEncodedBytes(long handle);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ec/SunEC.java Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.ec;
+
+import java.util.*;
+import java.security.*;
+import sun.security.action.PutAllAction;
+
+/**
+ * Provider class for the Elliptic Curve provider.
+ * Supports EC keypair and parameter generation, ECDSA signing and
+ * ECDH key agreement.
+ *
+ * IMPLEMENTATION NOTE:
+ * The Java classes in this provider access a native ECC implementation
+ * via JNI to a C++ wrapper class which in turn calls C functions.
+ * The Java classes are packaged into the signed sunec.jar in the JRE
+ * extensions directory and the C++ and C functions are packaged into
+ * libsunecc.so or sunecc.dll in the JRE native libraries directory.
+ *
+ * @since 1.7
+ */
+public final class SunEC extends Provider {
+
+ private static final long serialVersionUID = -2279741672933606418L;
+
+ public SunEC() {
+ super("SunEC", 1.7d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
+
+ // if there is no security manager installed, put directly into
+ // the provider. Otherwise, create a temporary map and use a
+ // doPrivileged() call at the end to transfer the contents
+ if (System.getSecurityManager() == null) {
+ SunECEntries.putEntries(this);
+ } else {
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ SunECEntries.putEntries(map);
+ AccessController.doPrivileged(new PutAllAction(this, map));
+ }
+ }
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ec/SunECEntries.java Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package sun.security.ec;
+
+import java.util.Map;
+
+/**
+ * Defines the entries of the SunEC provider.
+ *
+ * @since 1.7
+ */
+final class SunECEntries {
+
+ private SunECEntries() {
+ // empty
+ }
+
+ static void putEntries(Map<Object, Object> map) {
+
+ /*
+ * Signature engines
+ */
+ map.put("Signature.NONEwithECDSA",
+ "sun.security.ec.ECDSASignature$Raw");
+ map.put("Signature.SHA1withECDSA",
+ "sun.security.ec.ECDSASignature$SHA1");
+ map.put("Signature.SHA256withECDSA",
+ "sun.security.ec.ECDSASignature$SHA256");
+ map.put("Signature.SHA384withECDSA",
+ "sun.security.ec.ECDSASignature$SHA384");
+ map.put("Signature.SHA512withECDSA",
+ "sun.security.ec.ECDSASignature$SHA512");
+
+ String ecKeyClasses = "java.security.interfaces.ECPublicKey" +
+ "|java.security.interfaces.ECPrivateKey";
+ map.put("Signature.NONEwithECDSA SupportedKeyClasses", ecKeyClasses);
+ map.put("Signature.SHA1withECDSA SupportedKeyClasses", ecKeyClasses);
+ map.put("Signature.SHA256withECDSA SupportedKeyClasses", ecKeyClasses);
+ map.put("Signature.SHA384withECDSA SupportedKeyClasses", ecKeyClasses);
+ map.put("Signature.SHA512withECDSA SupportedKeyClasses", ecKeyClasses);
+
+ /*
+ * Key Pair Generator engine
+ */
+ map.put("KeyPairGenerator.EC", "sun.security.ec.ECKeyPairGenerator");
+ map.put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC");
+
+ /*
+ * Key Factory engine
+ */
+ map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory");
+ map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC");
+
+ /*
+ * Algorithm Parameter engine
+ */
+ map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters");
+ map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC");
+
+ /*
+ * Key Agreement engine
+ */
+ map.put("KeyAgreement.ECDH", "sun.security.ec.ECDHKeyAgreement");
+ map.put("KeyAgreement.ECDH SupportedKeyClasses", ecKeyClasses);
+
+ /*
+ * Key sizes
+ */
+ map.put("Signature.SHA1withECDSA KeySize", "256");
+ map.put("KeyPairGenerator.EC KeySize", "256");
+ map.put("AlgorithmParameterGenerator.ECDSA KeySize", "256");
+
+ /*
+ * Implementation type: software or hardware
+ */
+ map.put("Signature.NONEwithECDSA ImplementedIn", "Software");
+ map.put("Signature.SHA1withECDSA ImplementedIn", "Software");
+ map.put("Signature.SHA256withECDSA ImplementedIn", "Software");
+ map.put("Signature.SHA384withECDSA ImplementedIn", "Software");
+ map.put("Signature.SHA512withECDSA ImplementedIn", "Software");
+ map.put("KeyPairGenerator.EC ImplementedIn", "Software");
+ map.put("KeyFactory.EC ImplementedIn", "Software");
+ map.put("KeyAgreement.ECDH ImplementedIn", "Software");
+ map.put("AlgorithmParameters.EC ImplementedIn", "Software");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ECC_JNI.cpp Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,418 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+#include <jni.h>
+#include "ecc_impl.h"
+
+#define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
+#define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
+ "java/security/InvalidAlgorithmParameterException"
+#define INVALID_PARAMETER_EXCEPTION \
+ "java/security/InvalidParameterException"
+#define KEY_EXCEPTION "java/security/KeyException"
+
+extern "C" {
+
+/*
+ * Throws an arbitrary Java exception.
+ */
+void ThrowException(JNIEnv *env, char *exceptionName)
+{
+ jclass exceptionClazz = env->FindClass(exceptionName);
+ env->ThrowNew(exceptionClazz, NULL);
+}
+
+/*
+ * Deep free of the ECParams struct
+ */
+void FreeECParams(ECParams *ecparams, jboolean freeStruct)
+{
+ // Use B_FALSE to free the SECItem->data element, but not the SECItem itself
+ // Use B_TRUE to free both
+
+ SECITEM_FreeItem(&ecparams->fieldID.u.prime, B_FALSE);
+ SECITEM_FreeItem(&ecparams->curve.a, B_FALSE);
+ SECITEM_FreeItem(&ecparams->curve.b, B_FALSE);
+ SECITEM_FreeItem(&ecparams->curve.seed, B_FALSE);
+ SECITEM_FreeItem(&ecparams->base, B_FALSE);
+ SECITEM_FreeItem(&ecparams->order, B_FALSE);
+ SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE);
+ SECITEM_FreeItem(&ecparams->curveOID, B_FALSE);
+ if (freeStruct)
+ free(ecparams);
+}
+
+/*
+ * Class: sun_security_ec_ECKeyPairGenerator
+ * Method: generateECKeyPair
+ * Signature: (I[B[B)[J
+ */
+JNIEXPORT jlongArray
+JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
+ (JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
+{
+ ECPrivateKey *privKey; /* contains both public and private values */
+ ECParams *ecparams = NULL;
+ SECKEYECParams params_item;
+ jint jSeedLength;
+ jbyte* pSeedBuffer = NULL;
+ jlongArray result = NULL;
+ jlong* resultElements = NULL;
+
+ // Initialize the ECParams struct
+ params_item.len = env->GetArrayLength(encodedParams);
+ params_item.data =
+ (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
+
+ // Fill a new ECParams using the supplied OID
+ if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+ /* bad curve OID */
+ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+ goto cleanup;
+ }
+
+ // Copy seed from Java to native buffer
+ jSeedLength = env->GetArrayLength(seed);
+ pSeedBuffer = new jbyte[jSeedLength];
+ env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
+
+ // Generate the new keypair (using the supplied seed)
+ if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,
+ jSeedLength, 0) != SECSuccess) {
+ ThrowException(env, KEY_EXCEPTION);
+ goto cleanup;
+ }
+
+ jboolean isCopy;
+ result = env->NewLongArray(2);
+ resultElements = env->GetLongArrayElements(result, &isCopy);
+
+ resultElements[0] = (jlong) &(privKey->privateValue); // private big integer
+ resultElements[1] = (jlong) &(privKey->publicValue); // encoded ec point
+
+ // If the array is a copy then we must write back our changes
+ if (isCopy == JNI_TRUE) {
+ env->ReleaseLongArrayElements(result, resultElements, 0);
+ }
+
+cleanup:
+ {
+ if (params_item.data)
+ env->ReleaseByteArrayElements(encodedParams,
+ (jbyte *) params_item.data, JNI_ABORT);
+
+ if (ecparams)
+ FreeECParams(ecparams, true);
+
+ if (privKey) {
+ FreeECParams(&privKey->ecParams, false);
+ SECITEM_FreeItem(&privKey->version, B_FALSE);
+ // Don't free privKey->privateValue and privKey->publicValue
+ }
+
+ if (pSeedBuffer)
+ delete [] pSeedBuffer;
+ }
+
+ return result;
+}
+
+/*
+ * Class: sun_security_ec_ECKeyPairGenerator
+ * Method: getEncodedBytes
+ * Signature: (J)[B
+ */
+JNIEXPORT jbyteArray
+JNICALL Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes
+ (JNIEnv *env, jclass clazz, jlong hSECItem)
+{
+ SECItem *s = (SECItem *)hSECItem;
+ jbyteArray jEncodedBytes = env->NewByteArray(s->len);
+
+ // Copy bytes from a native SECItem buffer to Java byte array
+ env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);
+
+ // Use B_FALSE to free only the SECItem->data
+ SECITEM_FreeItem(s, B_FALSE);
+
+ return jEncodedBytes;
+}
+
+/*
+ * Class: sun_security_ec_ECDSASignature
+ * Method: signDigest
+ * Signature: ([B[B[B[B)[B
+ */
+JNIEXPORT jbyteArray
+JNICALL Java_sun_security_ec_ECDSASignature_signDigest
+ (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed)
+{
+ jbyte* pDigestBuffer = NULL;
+ jint jDigestLength = env->GetArrayLength(digest);
+ jbyteArray jSignedDigest = NULL;
+
+ SECItem signature_item;
+ jbyte* pSignedDigestBuffer = NULL;
+ jbyteArray temp;
+
+ jint jSeedLength = env->GetArrayLength(seed);
+ jbyte* pSeedBuffer = NULL;
+
+ // Copy digest from Java to native buffer
+ pDigestBuffer = new jbyte[jDigestLength];
+ env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
+ SECItem digest_item;
+ digest_item.data = (unsigned char *) pDigestBuffer;
+ digest_item.len = jDigestLength;
+
+ ECPrivateKey privKey;
+
+ // Initialize the ECParams struct
+ ECParams *ecparams = NULL;
+ SECKEYECParams params_item;
+ params_item.len = env->GetArrayLength(encodedParams);
+ params_item.data =
+ (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
+
+ // Fill a new ECParams using the supplied OID
+ if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+ /* bad curve OID */
+ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+ goto cleanup;
+ }
+
+ // Extract private key data
+ privKey.ecParams = *ecparams; // struct assignment
+ privKey.privateValue.len = env->GetArrayLength(privateKey);
+ privKey.privateValue.data =
+ (unsigned char *) env->GetByteArrayElements(privateKey, 0);
+
+ // Prepare a buffer for the signature (twice the key length)
+ pSignedDigestBuffer = new jbyte[ecparams->order.len * 2];
+ signature_item.data = (unsigned char *) pSignedDigestBuffer;
+ signature_item.len = ecparams->order.len * 2;
+
+ // Copy seed from Java to native buffer
+ pSeedBuffer = new jbyte[jSeedLength];
+ env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
+
+ // Sign the digest (using the supplied seed)
+ if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
+ (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) {
+ ThrowException(env, KEY_EXCEPTION);
+ goto cleanup;
+ }
+
+ // Create new byte array
+ temp = env->NewByteArray(signature_item.len);
+
+ // Copy data from native buffer
+ env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer);
+ jSignedDigest = temp;
+
+cleanup:
+ {
+ if (params_item.data)
+ env->ReleaseByteArrayElements(encodedParams,
+ (jbyte *) params_item.data, JNI_ABORT);
+
+ if (pDigestBuffer)
+ delete [] pDigestBuffer;
+
+ if (pSignedDigestBuffer)
+ delete [] pSignedDigestBuffer;
+
+ if (pSeedBuffer)
+ delete [] pSeedBuffer;
+
+ if (ecparams)
+ FreeECParams(ecparams, true);
+ }
+
+ return jSignedDigest;
+}
+
+/*
+ * Class: sun_security_ec_ECDSASignature
+ * Method: verifySignedDigest
+ * Signature: ([B[B[B[B)Z
+ */
+JNIEXPORT jboolean
+JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
+ (JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)
+{
+ jboolean isValid = false;
+
+ // Copy signedDigest from Java to native buffer
+ jbyte* pSignedDigestBuffer = NULL;
+ jint jSignedDigestLength = env->GetArrayLength(signedDigest);
+ pSignedDigestBuffer = new jbyte[jSignedDigestLength];
+ env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength,
+ pSignedDigestBuffer);
+ SECItem signature_item;
+ signature_item.data = (unsigned char *) pSignedDigestBuffer;
+ signature_item.len = jSignedDigestLength;
+
+ // Copy digest from Java to native buffer
+ jbyte* pDigestBuffer = NULL;
+ jint jDigestLength = env->GetArrayLength(digest);
+ pDigestBuffer = new jbyte[jDigestLength];
+ env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
+ SECItem digest_item;
+ digest_item.data = (unsigned char *) pDigestBuffer;
+ digest_item.len = jDigestLength;
+
+ // Extract public key data
+ ECPublicKey pubKey;
+ pubKey.publicValue.data = NULL;
+ ECParams *ecparams = NULL;
+ SECKEYECParams params_item;
+
+ // Initialize the ECParams struct
+ params_item.len = env->GetArrayLength(encodedParams);
+ params_item.data =
+ (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
+
+ // Fill a new ECParams using the supplied OID
+ if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+ /* bad curve OID */
+ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+ goto cleanup;
+ }
+ pubKey.ecParams = *ecparams; // struct assignment
+ pubKey.publicValue.len = env->GetArrayLength(publicKey);
+ pubKey.publicValue.data =
+ (unsigned char *) env->GetByteArrayElements(publicKey, 0);
+
+ if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)
+ != SECSuccess) {
+ goto cleanup;
+ }
+
+ isValid = true;
+
+cleanup:
+ {
+ if (params_item.data)
+ env->ReleaseByteArrayElements(encodedParams,
+ (jbyte *) params_item.data, JNI_ABORT);
+
+ if (pubKey.publicValue.data)
+ env->ReleaseByteArrayElements(publicKey,
+ (jbyte *) pubKey.publicValue.data, JNI_ABORT);
+
+ if (ecparams)
+ FreeECParams(ecparams, true);
+
+ if (pSignedDigestBuffer)
+ delete [] pSignedDigestBuffer;
+
+ if (pDigestBuffer)
+ delete [] pDigestBuffer;
+ }
+
+ return isValid;
+}
+
+/*
+ * Class: sun_security_ec_ECDHKeyAgreement
+ * Method: deriveKey
+ * Signature: ([B[B[B)[B
+ */
+JNIEXPORT jbyteArray
+JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
+ (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)
+{
+ jbyteArray jSecret = NULL;
+
+ // Extract private key value
+ SECItem privateValue_item;
+ privateValue_item.len = env->GetArrayLength(privateKey);
+ privateValue_item.data =
+ (unsigned char *) env->GetByteArrayElements(privateKey, 0);
+
+ // Extract public key value
+ SECItem publicValue_item;
+ publicValue_item.len = env->GetArrayLength(publicKey);
+ publicValue_item.data =
+ (unsigned char *) env->GetByteArrayElements(publicKey, 0);
+
+ // Initialize the ECParams struct
+ ECParams *ecparams = NULL;
+ SECKEYECParams params_item;
+ params_item.len = env->GetArrayLength(encodedParams);
+ params_item.data =
+ (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
+
+ // Fill a new ECParams using the supplied OID
+ if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
+ /* bad curve OID */
+ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
+ goto cleanup;
+ }
+
+ // Prepare a buffer for the secret
+ SECItem secret_item;
+ secret_item.data = NULL;
+ secret_item.len = ecparams->order.len * 2;
+
+ if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,
+ &secret_item, 0) != SECSuccess) {
+ ThrowException(env, ILLEGAL_STATE_EXCEPTION);
+ goto cleanup;
+ }
+
+ // Create new byte array
+ jSecret = env->NewByteArray(secret_item.len);
+
+ // Copy bytes from the SECItem buffer to a Java byte array
+ env->SetByteArrayRegion(jSecret, 0, secret_item.len,
+ (jbyte *)secret_item.data);
+
+ // Free the SECItem data buffer
+ SECITEM_FreeItem(&secret_item, B_FALSE);
+
+cleanup:
+ {
+ if (privateValue_item.data)
+ env->ReleaseByteArrayElements(privateKey,
+ (jbyte *) privateValue_item.data, JNI_ABORT);
+
+ if (publicValue_item.data)
+ env->ReleaseByteArrayElements(publicKey,
+ (jbyte *) publicValue_item.data, JNI_ABORT);
+
+ if (params_item.data)
+ env->ReleaseByteArrayElements(encodedParams,
+ (jbyte *) params_item.data, JNI_ABORT);
+
+ if (ecparams)
+ FreeECParams(ecparams, true);
+ }
+
+ return jSecret;
+}
+
+} /* extern "C" */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,1099 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 Cryptography library.
+ *
+ * The Initial Developer of the Original Code is
+ * Sun Microsystems, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com> and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "mplogic.h"
+#include "ec.h"
+#include "ecl.h"
+
+#include <sys/types.h>
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _WIN32
+#include <strings.h>
+#endif /* _WIN32 */
+
+#endif
+#include "ecl-exp.h"
+#include "mpi.h"
+#include "ecc_impl.h"
+
+#ifdef _KERNEL
+#define PORT_ZFree(p, l) bzero((p), (l)); kmem_free((p), (l))
+#else
+#ifndef _WIN32
+#define PORT_ZFree(p, l) bzero((p), (l)); free((p))
+#else
+#define PORT_ZFree(p, l) memset((p), 0, (l)); free((p))
+#endif /* _WIN32 */
+#endif
+
+/*
+ * Returns true if pointP is the point at infinity, false otherwise
+ */
+PRBool
+ec_point_at_infinity(SECItem *pointP)
+{
+ unsigned int i;
+
+ for (i = 1; i < pointP->len; i++) {
+ if (pointP->data[i] != 0x00) return PR_FALSE;
+ }
+
+ return PR_TRUE;
+}
+
+/*
+ * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
+ * the curve whose parameters are encoded in params with base point G.
+ */
+SECStatus
+ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
+ const SECItem *pointP, SECItem *pointQ, int kmflag)
+{
+ mp_int Px, Py, Qx, Qy;
+ 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;
+
+#if EC_DEBUG
+ int i;
+ char mpstr[256];
+
+ 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");
+
+ 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);
+ }
+
+ 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 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, kmflag) );
+ CHECK_MPI_OK( mp_init(&Py, kmflag) );
+ CHECK_MPI_OK( mp_init(&Qx, kmflag) );
+ CHECK_MPI_OK( mp_init(&Qy, kmflag) );
+ CHECK_MPI_OK( mp_init(&Gx, kmflag) );
+ CHECK_MPI_OK( mp_init(&Gy, kmflag) );
+ CHECK_MPI_OK( mp_init(&order, kmflag) );
+ CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
+ CHECK_MPI_OK( mp_init(&a, kmflag) );
+ CHECK_MPI_OK( mp_init(&b, kmflag) );
+
+ 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, kmflag);
+ }
+
+#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 */
+ pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
+ CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
+ (mp_size) len) );
+ CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
+ (mp_size) len) );
+
+ rv = SECSuccess;
+
+#if EC_DEBUG
+ 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);
+ if (err) {
+ MP_TO_SEC_ERROR(err);
+ rv = SECFailure;
+ }
+
+ return rv;
+}
+
+/* Generates a new EC key pair. The private key is a supplied
+ * value and the public key is the result of performing a scalar
+ * point multiplication of that value with the curve's base point.
+ */
+SECStatus
+ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
+ const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ PRArenaPool *arena;
+ ECPrivateKey *key;
+ mp_int k;
+ mp_err err = MP_OKAY;
+ int len;
+
+#if EC_DEBUG
+ printf("ec_NewKey called\n");
+#endif
+
+#ifndef _WIN32
+int printf();
+#endif /* _WIN32 */
+
+ if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* Initialize an arena for the EC key. */
+ if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
+ return SECFailure;
+
+ key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
+ kmflag);
+ if (!key) {
+ PORT_FreeArena(arena, PR_TRUE);
+ return SECFailure;
+ }
+
+ /* Set the version number (SEC 1 section C.4 says it should be 1) */
+ SECITEM_AllocItem(arena, &key->version, 1, kmflag);
+ key->version.data[0] = 1;
+
+ /* Copy all of the fields from the ECParams argument to the
+ * ECParams structure within the private key.
+ */
+ key->ecParams.arena = arena;
+ key->ecParams.type = ecParams->type;
+ key->ecParams.fieldID.size = ecParams->fieldID.size;
+ key->ecParams.fieldID.type = ecParams->fieldID.type;
+ if (ecParams->fieldID.type == ec_field_GFp) {
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
+ &ecParams->fieldID.u.prime, kmflag));
+ } else {
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
+ &ecParams->fieldID.u.poly, kmflag));
+ }
+ key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
+ key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
+ key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
+ &ecParams->curve.a, kmflag));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
+ &ecParams->curve.b, kmflag));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
+ &ecParams->curve.seed, kmflag));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
+ &ecParams->base, kmflag));
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
+ &ecParams->order, kmflag));
+ key->ecParams.cofactor = ecParams->cofactor;
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
+ &ecParams->DEREncoding, kmflag));
+ key->ecParams.name = ecParams->name;
+ CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
+ &ecParams->curveOID, kmflag));
+
+ len = (ecParams->fieldID.size + 7) >> 3;
+ SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
+ len = ecParams->order.len;
+ SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
+
+ /* Copy private key */
+ if (privKeyLen >= len) {
+ memcpy(key->privateValue.data, privKeyBytes, len);
+ } else {
+ memset(key->privateValue.data, 0, (len - privKeyLen));
+ memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
+ }
+
+ /* Compute corresponding public key */
+ MP_DIGITS(&k) = 0;
+ CHECK_MPI_OK( mp_init(&k, kmflag) );
+ CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
+ (mp_size) len) );
+
+ rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
+ if (rv != SECSuccess) goto cleanup;
+ *privKey = key;
+
+cleanup:
+ mp_clear(&k);
+ if (rv)
+ PORT_FreeArena(arena, PR_TRUE);
+
+#if EC_DEBUG
+ printf("ec_NewKey returning %s\n",
+ (rv == SECSuccess) ? "success" : "failure");
+#endif
+
+ return rv;
+
+}
+
+/* Generates a new EC key pair. The private key is a supplied
+ * random value (in seed) and the public key is the result of
+ * performing a scalar point multiplication of that value with
+ * the curve's base point.
+ */
+SECStatus
+EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
+ const unsigned char *seed, int seedlen, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
+ return rv;
+}
+
+/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
+ * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
+ * random number generator.
+ *
+ * Parameters
+ * - order: a buffer that holds the curve's group order
+ * - len: the length in octets of the order buffer
+ * - random: a buffer of 2 * len random bytes
+ * - randomlen: the length in octets of the random buffer
+ *
+ * Return Value
+ * Returns a buffer of len octets that holds the private key. The caller
+ * is responsible for freeing the buffer with PORT_ZFree.
+ */
+static unsigned char *
+ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
+ const unsigned char *random, int randomlen, int kmflag)
+{
+ SECStatus rv = SECSuccess;
+ mp_err err;
+ unsigned char *privKeyBytes = NULL;
+ mp_int privKeyVal, order_1, one;
+
+ MP_DIGITS(&privKeyVal) = 0;
+ MP_DIGITS(&order_1) = 0;
+ MP_DIGITS(&one) = 0;
+ CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
+ CHECK_MPI_OK( mp_init(&order_1, kmflag) );
+ CHECK_MPI_OK( mp_init(&one, kmflag) );
+
+ /*
+ * Reduces the 2*len buffer of random bytes modulo the group order.
+ */
+ if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
+ if (randomlen != 2 * len) {
+ goto cleanup;
+ }
+ /* No need to generate - random bytes are now supplied */
+ /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
+ memcpy(privKeyBytes, random, randomlen);
+
+ CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
+ CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
+ CHECK_MPI_OK( mp_set_int(&one, 1) );
+ CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
+ CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
+ CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
+ CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
+ memset(privKeyBytes+len, 0, len);
+cleanup:
+ mp_clear(&privKeyVal);
+ mp_clear(&order_1);
+ mp_clear(&one);
+ if (err < MP_OKAY) {
+ MP_TO_SEC_ERROR(err);
+ rv = SECFailure;
+ }
+ if (rv != SECSuccess && privKeyBytes) {
+#ifdef _KERNEL
+ kmem_free(privKeyBytes, 2*len);
+#else
+ free(privKeyBytes);
+#endif
+ privKeyBytes = NULL;
+ }
+ return privKeyBytes;
+}
+
+/* Generates a new EC key pair. The private key is a random value and
+ * the public key is the result of performing a scalar point multiplication
+ * of that value with the curve's base point.
+ */
+SECStatus
+EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
+ const unsigned char* random, int randomlen, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ int len;
+ unsigned char *privKeyBytes = NULL;
+
+ if (!ecParams) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ len = ecParams->order.len;
+ privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
+ random, randomlen, kmflag);
+ if (privKeyBytes == NULL) goto cleanup;
+ /* generate public key */
+ CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
+
+cleanup:
+ if (privKeyBytes) {
+ PORT_ZFree(privKeyBytes, len * 2);
+ }
+#if EC_DEBUG
+ printf("EC_NewKey returning %s\n",
+ (rv == SECSuccess) ? "success" : "failure");
+#endif
+
+ return rv;
+}
+
+/* Validates an EC public key as described in Section 5.2.2 of
+ * X9.62. The ECDH primitive when used without the cofactor does
+ * not address small subgroup attacks, which may occur when the
+ * public key is not valid. These attacks can be prevented by
+ * validating the public key before using ECDH.
+ */
+SECStatus
+EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
+{
+ mp_int Px, Py;
+ ECGroup *group = NULL;
+ SECStatus rv = SECFailure;
+ mp_err err = MP_OKAY;
+ int len;
+
+ if (!ecParams || !publicValue) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* NOTE: We only support uncompressed points for now */
+ len = (ecParams->fieldID.size + 7) >> 3;
+ if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
+ return SECFailure;
+ } else if (publicValue->len != (2 * len + 1)) {
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ return SECFailure;
+ }
+
+ MP_DIGITS(&Px) = 0;
+ MP_DIGITS(&Py) = 0;
+ CHECK_MPI_OK( mp_init(&Px, kmflag) );
+ CHECK_MPI_OK( mp_init(&Py, kmflag) );
+
+ /* Initialize Px and Py */
+ CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
+ CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
+
+ /* construct from named params */
+ group = ECGroup_fromName(ecParams->name, kmflag);
+ if (group == NULL) {
+ /*
+ * ECGroup_fromName fails if ecParams->name is not a valid
+ * ECCurveName value, or if we run out of memory, or perhaps
+ * for other reasons. Unfortunately if ecParams->name is a
+ * valid ECCurveName value, we don't know what the right error
+ * code should be because ECGroup_fromName doesn't return an
+ * error code to the caller. Set err to MP_UNDEF because
+ * that's what ECGroup_fromName uses internally.
+ */
+ if ((ecParams->name <= ECCurve_noName) ||
+ (ecParams->name >= ECCurve_pastLastCurve)) {
+ err = MP_BADARG;
+ } else {
+ err = MP_UNDEF;
+ }
+ goto cleanup;
+ }
+
+ /* validate public point */
+ if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
+ if (err == MP_NO) {
+ PORT_SetError(SEC_ERROR_BAD_KEY);
+ rv = SECFailure;
+ err = MP_OKAY; /* don't change the error code */
+ }
+ goto cleanup;
+ }
+
+ rv = SECSuccess;
+
+cleanup:
+ ECGroup_free(group);
+ mp_clear(&Px);
+ mp_clear(&Py);
+ if (err) {
+ MP_TO_SEC_ERROR(err);
+ rv = SECFailure;
+ }
+ return rv;
+}
+
+/*
+** Performs an ECDH key derivation by computing the scalar point
+** multiplication of privateValue and publicValue (with or without the
+** cofactor) and returns the x-coordinate of the resulting elliptic
+** curve point in derived secret. If successful, derivedSecret->data
+** is set to the address of the newly allocated buffer containing the
+** derived secret, and derivedSecret->len is the size of the secret
+** produced. It is the caller's responsibility to free the allocated
+** buffer containing the derived secret.
+*/
+SECStatus
+ECDH_Derive(SECItem *publicValue,
+ ECParams *ecParams,
+ SECItem *privateValue,
+ PRBool withCofactor,
+ SECItem *derivedSecret,
+ int kmflag)
+{
+ SECStatus rv = SECFailure;
+ unsigned int len = 0;
+ SECItem pointQ = {siBuffer, NULL, 0};
+ mp_int k; /* to hold the private value */
+ mp_int cofactor;
+ mp_err err = MP_OKAY;
+#if EC_DEBUG
+ int i;
+#endif
+
+ if (!publicValue || !ecParams || !privateValue ||
+ !derivedSecret) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ memset(derivedSecret, 0, sizeof *derivedSecret);
+ len = (ecParams->fieldID.size + 7) >> 3;
+ pointQ.len = 2*len + 1;
+ if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
+
+ MP_DIGITS(&k) = 0;
+ CHECK_MPI_OK( mp_init(&k, kmflag) );
+ CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
+ (mp_size) privateValue->len) );
+
+ if (withCofactor && (ecParams->cofactor != 1)) {
+ /* multiply k with the cofactor */
+ MP_DIGITS(&cofactor) = 0;
+ CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
+ mp_set(&cofactor, ecParams->cofactor);
+ CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
+ }
+
+ /* Multiply our private key and peer's public point */
+ if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
+ ec_point_at_infinity(&pointQ))
+ goto cleanup;
+
+ /* Allocate memory for the derived secret and copy
+ * the x co-ordinate of pointQ into it.
+ */
+ SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
+ memcpy(derivedSecret->data, pointQ.data + 1, len);
+
+ rv = SECSuccess;
+
+#if EC_DEBUG
+ printf("derived_secret:\n");
+ for (i = 0; i < derivedSecret->len; i++)
+ printf("%02x:", derivedSecret->data[i]);
+ printf("\n");
+#endif
+
+cleanup:
+ mp_clear(&k);
+
+ if (pointQ.data) {
+ PORT_ZFree(pointQ.data, 2*len + 1);
+ }
+
+ return rv;
+}
+
+/* Computes the ECDSA signature (a concatenation of two values r and s)
+ * on the digest using the given key and the random value kb (used in
+ * computing s).
+ */
+SECStatus
+ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
+ const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ mp_int x1;
+ mp_int d, k; /* private key, random integer */
+ mp_int r, s; /* tuple (r, s) is the signature */
+ mp_int n;
+ mp_err err = MP_OKAY;
+ ECParams *ecParams = NULL;
+ SECItem kGpoint = { siBuffer, NULL, 0};
+ int flen = 0; /* length in bytes of the field size */
+ unsigned olen; /* length in bytes of the base point order */
+
+#if EC_DEBUG
+ char mpstr[256];
+#endif
+
+ /* Initialize MPI integers. */
+ /* must happen before the first potential call to cleanup */
+ MP_DIGITS(&x1) = 0;
+ MP_DIGITS(&d) = 0;
+ MP_DIGITS(&k) = 0;
+ MP_DIGITS(&r) = 0;
+ MP_DIGITS(&s) = 0;
+ MP_DIGITS(&n) = 0;
+
+ /* Check args */
+ if (!key || !signature || !digest || !kb || (kblen < 0)) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto cleanup;
+ }
+
+ ecParams = &(key->ecParams);
+ flen = (ecParams->fieldID.size + 7) >> 3;
+ olen = ecParams->order.len;
+ if (signature->data == NULL) {
+ /* a call to get the signature length only */
+ goto finish;
+ }
+ if (signature->len < 2*olen) {
+ PORT_SetError(SEC_ERROR_OUTPUT_LEN);
+ rv = SECBufferTooSmall;
+ goto cleanup;
+ }
+
+
+ CHECK_MPI_OK( mp_init(&x1, kmflag) );
+ CHECK_MPI_OK( mp_init(&d, kmflag) );
+ CHECK_MPI_OK( mp_init(&k, kmflag) );
+ CHECK_MPI_OK( mp_init(&r, kmflag) );
+ CHECK_MPI_OK( mp_init(&s, kmflag) );
+ CHECK_MPI_OK( mp_init(&n, kmflag) );
+
+ SECITEM_TO_MPINT( ecParams->order, &n );
+ SECITEM_TO_MPINT( key->privateValue, &d );
+ 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;
+ }
+
+ /*
+ ** ANSI X9.62, Section 5.3.2, Step 2
+ **
+ ** Compute kG
+ */
+ kGpoint.len = 2*flen + 1;
+ kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
+ if ((kGpoint.data == NULL) ||
+ (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
+ != SECSuccess))
+ goto cleanup;
+
+ /*
+ ** ANSI X9.62, Section 5.3.3, Step 1
+ **
+ ** Extract the x co-ordinate of kG into x1
+ */
+ CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
+ (mp_size) flen) );
+
+ /*
+ ** ANSI X9.62, Section 5.3.3, Step 2
+ **
+ ** r = x1 mod n NOTE: n is the order of the curve
+ */
+ CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
+
+ /*
+ ** ANSI X9.62, Section 5.3.3, Step 3
+ **
+ ** verify r != 0
+ */
+ if (mp_cmp_z(&r) == 0) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ goto cleanup;
+ }
+
+ /*
+ ** ANSI X9.62, Section 5.3.3, Step 4
+ **
+ ** s = (k**-1 * (HASH(M) + d*r)) mod n
+ */
+ SECITEM_TO_MPINT(*digest, &s); /* s = HASH(M) */
+
+ /* In the definition of EC signing, digests are truncated
+ * to the length of n in bits.
+ * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
+ if (digest->len*8 > ecParams->fieldID.size) {
+ mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
+ }
+
+#if EC_DEBUG
+ mp_todecimal(&n, mpstr);
+ printf("n : %s (dec)\n", mpstr);
+ mp_todecimal(&d, mpstr);
+ printf("d : %s (dec)\n", mpstr);
+ mp_tohex(&x1, mpstr);
+ printf("x1: %s\n", mpstr);
+ mp_todecimal(&s, mpstr);
+ 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 */
+ CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) ); /* d = d * r mod n */
+ CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) ); /* s = s + d mod n */
+ CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) ); /* s = s * k mod n */
+
+#if EC_DEBUG
+ mp_todecimal(&s, mpstr);
+ printf("s : %s (dec)\n", mpstr);
+ mp_tohex(&s, mpstr);
+ printf("s : %s\n", mpstr);
+#endif
+
+ /*
+ ** ANSI X9.62, Section 5.3.3, Step 5
+ **
+ ** verify s != 0
+ */
+ if (mp_cmp_z(&s) == 0) {
+ PORT_SetError(SEC_ERROR_NEED_RANDOM);
+ goto cleanup;
+ }
+
+ /*
+ **
+ ** Signature is tuple (r, s)
+ */
+ CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
+ CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
+finish:
+ signature->len = 2*olen;
+
+ rv = SECSuccess;
+ err = MP_OKAY;
+cleanup:
+ mp_clear(&x1);
+ mp_clear(&d);
+ mp_clear(&k);
+ mp_clear(&r);
+ mp_clear(&s);
+ mp_clear(&n);
+
+ if (kGpoint.data) {
+ PORT_ZFree(kGpoint.data, 2*flen + 1);
+ }
+
+ if (err) {
+ MP_TO_SEC_ERROR(err);
+ rv = SECFailure;
+ }
+
+#if EC_DEBUG
+ printf("ECDSA signing with seed %s\n",
+ (rv == SECSuccess) ? "succeeded" : "failed");
+#endif
+
+ return rv;
+}
+
+/*
+** Computes the ECDSA signature on the digest using the given key
+** and a random seed.
+*/
+SECStatus
+ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
+ const unsigned char* random, int randomLen, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ int len;
+ unsigned char *kBytes= NULL;
+
+ if (!key) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ /* Generate random value k */
+ len = key->ecParams.order.len;
+ kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
+ random, randomLen, kmflag);
+ if (kBytes == NULL) goto cleanup;
+
+ /* Generate ECDSA signature with the specified k value */
+ rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
+
+cleanup:
+ if (kBytes) {
+ PORT_ZFree(kBytes, len * 2);
+ }
+
+#if EC_DEBUG
+ printf("ECDSA signing %s\n",
+ (rv == SECSuccess) ? "succeeded" : "failed");
+#endif
+
+ return rv;
+}
+
+/*
+** Checks the signature on the given digest using the key provided.
+*/
+SECStatus
+ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
+ const SECItem *digest, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ mp_int r_, s_; /* tuple (r', s') is received signature) */
+ mp_int c, u1, u2, v; /* intermediate values used in verification */
+ mp_int x1;
+ mp_int n;
+ mp_err err = MP_OKAY;
+ ECParams *ecParams = NULL;
+ SECItem pointC = { siBuffer, NULL, 0 };
+ int slen; /* length in bytes of a half signature (r or s) */
+ int flen; /* length in bytes of the field size */
+ unsigned olen; /* length in bytes of the base point order */
+
+#if EC_DEBUG
+ char mpstr[256];
+ printf("ECDSA verification called\n");
+#endif
+
+ /* Initialize MPI integers. */
+ /* must happen before the first potential call to cleanup */
+ MP_DIGITS(&r_) = 0;
+ MP_DIGITS(&s_) = 0;
+ MP_DIGITS(&c) = 0;
+ MP_DIGITS(&u1) = 0;
+ MP_DIGITS(&u2) = 0;
+ MP_DIGITS(&x1) = 0;
+ MP_DIGITS(&v) = 0;
+ MP_DIGITS(&n) = 0;
+
+ /* Check args */
+ if (!key || !signature || !digest) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ goto cleanup;
+ }
+
+ ecParams = &(key->ecParams);
+ flen = (ecParams->fieldID.size + 7) >> 3;
+ olen = ecParams->order.len;
+ if (signature->len == 0 || signature->len%2 != 0 ||
+ signature->len > 2*olen) {
+ PORT_SetError(SEC_ERROR_INPUT_LEN);
+ goto cleanup;
+ }
+ slen = signature->len/2;
+
+ SECITEM_AllocItem(NULL, &pointC, 2*flen + 1, kmflag);
+ if (pointC.data == NULL)
+ goto cleanup;
+
+ CHECK_MPI_OK( mp_init(&r_, kmflag) );
+ CHECK_MPI_OK( mp_init(&s_, kmflag) );
+ CHECK_MPI_OK( mp_init(&c, kmflag) );
+ CHECK_MPI_OK( mp_init(&u1, kmflag) );
+ CHECK_MPI_OK( mp_init(&u2, kmflag) );
+ CHECK_MPI_OK( mp_init(&x1, kmflag) );
+ CHECK_MPI_OK( mp_init(&v, kmflag) );
+ CHECK_MPI_OK( mp_init(&n, kmflag) );
+
+ /*
+ ** Convert received signature (r', s') into MPI integers.
+ */
+ CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
+ CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
+
+ /*
+ ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
+ **
+ ** Verify that 0 < r' < n and 0 < s' < n
+ */
+ SECITEM_TO_MPINT(ecParams->order, &n);
+ if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
+ mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ goto cleanup; /* will return rv == SECFailure */
+ }
+
+ /*
+ ** ANSI X9.62, Section 5.4.2, Step 3
+ **
+ ** c = (s')**-1 mod n
+ */
+ CHECK_MPI_OK( mp_invmod(&s_, &n, &c) ); /* c = (s')**-1 mod n */
+
+ /*
+ ** ANSI X9.62, Section 5.4.2, Step 4
+ **
+ ** u1 = ((HASH(M')) * c) mod n
+ */
+ SECITEM_TO_MPINT(*digest, &u1); /* u1 = HASH(M) */
+
+ /* In the definition of EC signing, digests are truncated
+ * to the length of n in bits.
+ * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
+ if (digest->len*8 > ecParams->fieldID.size) { /* u1 = HASH(M') */
+ mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
+ }
+
+#if EC_DEBUG
+ mp_todecimal(&r_, mpstr);
+ printf("r_: %s (dec)\n", mpstr);
+ mp_todecimal(&s_, mpstr);
+ printf("s_: %s (dec)\n", mpstr);
+ mp_todecimal(&c, mpstr);
+ printf("c : %s (dec)\n", mpstr);
+ mp_todecimal(&u1, mpstr);
+ printf("digest: %s (dec)\n", mpstr);
+#endif
+
+ CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) ); /* u1 = u1 * c mod n */
+
+ /*
+ ** ANSI X9.62, Section 5.4.2, Step 4
+ **
+ ** u2 = ((r') * c) mod n
+ */
+ CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
+
+ /*
+ ** ANSI X9.62, Section 5.4.3, Step 1
+ **
+ ** Compute u1*G + u2*Q
+ ** 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_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag)
+ != SECSuccess) {
+ rv = SECFailure;
+ goto cleanup;
+ }
+ if (ec_point_at_infinity(&pointC)) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ rv = SECFailure;
+ goto cleanup;
+ }
+
+ CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );
+
+ /*
+ ** ANSI X9.62, Section 5.4.4, Step 2
+ **
+ ** v = x1 mod n
+ */
+ 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
+ **
+ ** Verification: v == r'
+ */
+ if (mp_cmp(&v, &r_)) {
+ PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
+ rv = SECFailure; /* Signature failed to verify. */
+ } else {
+ rv = SECSuccess; /* Signature verified. */
+ }
+
+#if EC_DEBUG
+ mp_todecimal(&u1, mpstr);
+ printf("u1: %s (dec)\n", mpstr);
+ mp_todecimal(&u2, mpstr);
+ printf("u2: %s (dec)\n", mpstr);
+ mp_tohex(&x1, mpstr);
+ printf("x1: %s\n", mpstr);
+ mp_todecimal(&v, mpstr);
+ printf("v : %s (dec)\n", mpstr);
+#endif
+
+cleanup:
+ mp_clear(&r_);
+ mp_clear(&s_);
+ mp_clear(&c);
+ mp_clear(&u1);
+ mp_clear(&u2);
+ mp_clear(&x1);
+ mp_clear(&v);
+ mp_clear(&n);
+
+ if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
+ if (err) {
+ MP_TO_SEC_ERROR(err);
+ rv = SECFailure;
+ }
+
+#if EC_DEBUG
+ printf("ECDSA verification %s\n",
+ (rv == SECSuccess) ? "succeeded" : "failed");
+#endif
+
+ return rv;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,72 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 Cryptography library.
+ *
+ * The Initial Developer of the Original Code is
+ * Sun Microsystems, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef __ec_h_
+#define __ec_h_
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#define EC_DEBUG 0
+#define EC_POINT_FORM_COMPRESSED_Y0 0x02
+#define EC_POINT_FORM_COMPRESSED_Y1 0x03
+#define EC_POINT_FORM_UNCOMPRESSED 0x04
+#define EC_POINT_FORM_HYBRID_Y0 0x06
+#define EC_POINT_FORM_HYBRID_Y1 0x07
+
+#define ANSI_X962_CURVE_OID_TOTAL_LEN 10
+#define SECG_CURVE_OID_TOTAL_LEN 7
+
+#endif /* __ec_h_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec2.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,146 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _EC2_H
+#define _EC2_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecl-priv.h"
+
+/* Checks if point P(px, py) is at infinity. Uses affine coordinates. */
+mp_err ec_GF2m_pt_is_inf_aff(const mp_int *px, const mp_int *py);
+
+/* Sets P(px, py) to be the point at infinity. Uses affine coordinates. */
+mp_err ec_GF2m_pt_set_inf_aff(mp_int *px, mp_int *py);
+
+/* Computes R = P + Q where R is (rx, ry), P is (px, py) and Q is (qx,
+ * qy). Uses affine coordinates. */
+mp_err ec_GF2m_pt_add_aff(const mp_int *px, const mp_int *py,
+ const mp_int *qx, const mp_int *qy, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+
+/* Computes R = P - Q. Uses affine coordinates. */
+mp_err ec_GF2m_pt_sub_aff(const mp_int *px, const mp_int *py,
+ const mp_int *qx, const mp_int *qy, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+
+/* Computes R = 2P. Uses affine coordinates. */
+mp_err ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+
+/* Validates a point on a GF2m curve. */
+mp_err ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group);
+
+/* by default, this routine is unused and thus doesn't need to be compiled */
+#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
+/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
+ * a, b and p are the elliptic curve coefficients and the irreducible that
+ * determines the field GF2m. Uses affine coordinates. */
+mp_err ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px,
+ const mp_int *py, mp_int *rx, mp_int *ry,
+ const ECGroup *group);
+#endif
+
+/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
+ * a, b and p are the elliptic curve coefficients and the irreducible that
+ * determines the field GF2m. Uses Montgomery projective coordinates. */
+mp_err ec_GF2m_pt_mul_mont(const mp_int *n, const mp_int *px,
+ const mp_int *py, mp_int *rx, mp_int *ry,
+ const ECGroup *group);
+
+#ifdef ECL_ENABLE_GF2M_PROJ
+/* Converts a point P(px, py) from affine coordinates to projective
+ * coordinates R(rx, ry, rz). */
+mp_err ec_GF2m_pt_aff2proj(const mp_int *px, const mp_int *py, mp_int *rx,
+ mp_int *ry, mp_int *rz, const ECGroup *group);
+
+/* Converts a point P(px, py, pz) from projective coordinates to affine
+ * coordinates R(rx, ry). */
+mp_err ec_GF2m_pt_proj2aff(const mp_int *px, const mp_int *py,
+ const mp_int *pz, mp_int *rx, mp_int *ry,
+ const ECGroup *group);
+
+/* Checks if point P(px, py, pz) is at infinity. Uses projective
+ * coordinates. */
+mp_err ec_GF2m_pt_is_inf_proj(const mp_int *px, const mp_int *py,
+ const mp_int *pz);
+
+/* Sets P(px, py, pz) to be the point at infinity. Uses projective
+ * coordinates. */
+mp_err ec_GF2m_pt_set_inf_proj(mp_int *px, mp_int *py, mp_int *pz);
+
+/* Computes R = P + Q where R is (rx, ry, rz), P is (px, py, pz) and Q is
+ * (qx, qy, qz). Uses projective coordinates. */
+mp_err ec_GF2m_pt_add_proj(const mp_int *px, const mp_int *py,
+ const mp_int *pz, const mp_int *qx,
+ const mp_int *qy, mp_int *rx, mp_int *ry,
+ mp_int *rz, const ECGroup *group);
+
+/* Computes R = 2P. Uses projective coordinates. */
+mp_err ec_GF2m_pt_dbl_proj(const mp_int *px, const mp_int *py,
+ const mp_int *pz, mp_int *rx, mp_int *ry,
+ mp_int *rz, const ECGroup *group);
+
+/* Computes R = nP where R is (rx, ry) and P is (px, py). The parameters
+ * a, b and p are the elliptic curve coefficients and the prime that
+ * determines the field GF2m. Uses projective coordinates. */
+mp_err ec_GF2m_pt_mul_proj(const mp_int *n, const mp_int *px,
+ const mp_int *py, mp_int *rx, mp_int *ry,
+ const ECGroup *group);
+#endif
+
+#endif /* _EC2_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec2_163.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,281 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang-Shantz <sheueling.chang@sun.com>,
+ * Stephen Fung <fungstep@hotmail.com>, and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ec2.h"
+#include "mp_gf2m.h"
+#include "mp_gf2m-priv.h"
+#include "mpi.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec2_193.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,298 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang-Shantz <sheueling.chang@sun.com>,
+ * Stephen Fung <fungstep@hotmail.com>, and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ec2.h"
+#include "mp_gf2m.h"
+#include "mp_gf2m-priv.h"
+#include "mpi.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec2_233.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,321 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang-Shantz <sheueling.chang@sun.com>,
+ * Stephen Fung <fungstep@hotmail.com>, and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ec2.h"
+#include "mp_gf2m.h"
+#include "mp_gf2m-priv.h"
+#include "mpi.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec2_aff.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,368 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ec2.h"
+#include "mplogic.h"
+#include "mp_gf2m.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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, FLAG(px)));
+ MP_CHECKOK(mp_init(&tempx, FLAG(px)));
+ MP_CHECKOK(mp_init(&tempy, FLAG(px)));
+ /* 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, FLAG(px)));
+ /* nqy = qx+qy */
+ MP_CHECKOK(group->meth->field_add(qx, qy, &nqy, group->meth));
+ MP_CHECKOK(group->point_add(px, py, qx, &nqy, rx, ry, group));
+ CLEANUP:
+ mp_clear(&nqy);
+ return res;
+}
+
+/* Computes R = 2P. Elliptic curve points P and R can be identical. Uses
+ * affine coordinates. */
+mp_err
+ec_GF2m_pt_dbl_aff(const mp_int *px, const mp_int *py, mp_int *rx,
+ mp_int *ry, const ECGroup *group)
+{
+ return group->point_add(px, py, px, py, rx, ry, group);
+}
+
+/* by default, this routine is unused and thus doesn't need to be compiled */
+#ifdef ECL_ENABLE_GF2M_PT_MUL_AFF
+/* Computes R = nP based on IEEE P1363 A.10.3. Elliptic curve points P and
+ * R can be identical. Uses affine coordinates. */
+mp_err
+ec_GF2m_pt_mul_aff(const mp_int *n, const mp_int *px, const mp_int *py,
+ mp_int *rx, mp_int *ry, const ECGroup *group)
+{
+ mp_err res = MP_OKAY;
+ mp_int k, k3, qx, qy, sx, sy;
+ int b1, b3, i, l;
+
+ MP_DIGITS(&k) = 0;
+ MP_DIGITS(&k3) = 0;
+ MP_DIGITS(&qx) = 0;
+ MP_DIGITS(&qy) = 0;
+ MP_DIGITS(&sx) = 0;
+ MP_DIGITS(&sy) = 0;
+ MP_CHECKOK(mp_init(&k));
+ MP_CHECKOK(mp_init(&k3));
+ MP_CHECKOK(mp_init(&qx));
+ MP_CHECKOK(mp_init(&qy));
+ MP_CHECKOK(mp_init(&sx));
+ MP_CHECKOK(mp_init(&sy));
+
+ /* if n = 0 then r = inf */
+ if (mp_cmp_z(n) == 0) {
+ mp_zero(rx);
+ mp_zero(ry);
+ res = MP_OKAY;
+ goto CLEANUP;
+ }
+ /* Q = P, k = n */
+ MP_CHECKOK(mp_copy(px, &qx));
+ MP_CHECKOK(mp_copy(py, &qy));
+ MP_CHECKOK(mp_copy(n, &k));
+ /* if n < 0 then Q = -Q, k = -k */
+ if (mp_cmp_z(n) < 0) {
+ MP_CHECKOK(group->meth->field_add(&qx, &qy, &qy, group->meth));
+ MP_CHECKOK(mp_neg(&k, &k));
+ }
+#ifdef ECL_DEBUG /* basic double and add method */
+ l = mpl_significant_bits(&k) - 1;
+ MP_CHECKOK(mp_copy(&qx, &sx));
+ MP_CHECKOK(mp_copy(&qy, &sy));
+ for (i = l - 1; i >= 0; i--) {
+ /* S = 2S */
+ MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
+ /* if k_i = 1, then S = S + Q */
+ if (mpl_get_bit(&k, i) != 0) {
+ MP_CHECKOK(group->
+ point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
+ }
+ }
+#else /* double and add/subtract method from
+ * standard */
+ /* k3 = 3 * k */
+ MP_CHECKOK(mp_set_int(&k3, 3));
+ MP_CHECKOK(mp_mul(&k, &k3, &k3));
+ /* S = Q */
+ MP_CHECKOK(mp_copy(&qx, &sx));
+ MP_CHECKOK(mp_copy(&qy, &sy));
+ /* l = index of high order bit in binary representation of 3*k */
+ l = mpl_significant_bits(&k3) - 1;
+ /* for i = l-1 downto 1 */
+ for (i = l - 1; i >= 1; i--) {
+ /* S = 2S */
+ MP_CHECKOK(group->point_dbl(&sx, &sy, &sx, &sy, group));
+ b3 = MP_GET_BIT(&k3, i);
+ b1 = MP_GET_BIT(&k, i);
+ /* if k3_i = 1 and k_i = 0, then S = S + Q */
+ if ((b3 == 1) && (b1 == 0)) {
+ MP_CHECKOK(group->
+ point_add(&sx, &sy, &qx, &qy, &sx, &sy, group));
+ /* if k3_i = 0 and k_i = 1, then S = S - Q */
+ } else if ((b3 == 0) && (b1 == 1)) {
+ MP_CHECKOK(group->
+ point_sub(&sx, &sy, &qx, &qy, &sx, &sy, group));
+ }
+ }
+#endif
+ /* output S */
+ MP_CHECKOK(mp_copy(&sx, rx));
+ MP_CHECKOK(mp_copy(&sy, ry));
+
+ CLEANUP:
+ mp_clear(&k);
+ mp_clear(&k3);
+ mp_clear(&qx);
+ mp_clear(&qy);
+ mp_clear(&sx);
+ mp_clear(&sy);
+ return res;
+}
+#endif
+
+/* Validates a point on a GF2m curve. */
+mp_err
+ec_GF2m_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
+{
+ mp_err res = MP_NO;
+ mp_int accl, accr, tmp, pxt, pyt;
+
+ MP_DIGITS(&accl) = 0;
+ MP_DIGITS(&accr) = 0;
+ MP_DIGITS(&tmp) = 0;
+ MP_DIGITS(&pxt) = 0;
+ MP_DIGITS(&pyt) = 0;
+ MP_CHECKOK(mp_init(&accl, FLAG(px)));
+ MP_CHECKOK(mp_init(&accr, FLAG(px)));
+ MP_CHECKOK(mp_init(&tmp, FLAG(px)));
+ MP_CHECKOK(mp_init(&pxt, FLAG(px)));
+ MP_CHECKOK(mp_init(&pyt, FLAG(px)));
+
+ /* 1: Verify that publicValue is not the point at infinity */
+ if (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+ /* 2: Verify that the coordinates of publicValue are elements
+ * of the field.
+ */
+ if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
+ (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+ /* 3: Verify that publicValue is on the curve. */
+ if (group->meth->field_enc) {
+ group->meth->field_enc(px, &pxt, group->meth);
+ group->meth->field_enc(py, &pyt, group->meth);
+ } else {
+ mp_copy(px, &pxt);
+ mp_copy(py, &pyt);
+ }
+ /* left-hand side: y^2 + x*y */
+ MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
+ MP_CHECKOK( group->meth->field_mul(&pxt, &pyt, &tmp, group->meth) );
+ MP_CHECKOK( group->meth->field_add(&accl, &tmp, &accl, group->meth) );
+ /* right-hand side: x^3 + a*x^2 + b */
+ MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
+ MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
+ MP_CHECKOK( group->meth->field_mul(&group->curvea, &tmp, &tmp, group->meth) );
+ MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
+ MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
+ /* check LHS - RHS == 0 */
+ MP_CHECKOK( group->meth->field_add(&accl, &accr, &accr, group->meth) );
+ if (mp_cmp_z(&accr) != 0) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+ /* 4: Verify that the order of the curve times the publicValue
+ * is the point at infinity.
+ */
+ MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
+ if (ec_GF2m_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+
+ res = MP_YES;
+
+CLEANUP:
+ mp_clear(&accl);
+ mp_clear(&accr);
+ mp_clear(&tmp);
+ mp_clear(&pxt);
+ mp_clear(&pyt);
+ return res;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec2_mont.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,296 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang-Shantz <sheueling.chang@sun.com>,
+ * Stephen Fung <fungstep@hotmail.com>, and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ec2.h"
+#include "mplogic.h"
+#include "mp_gf2m.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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, int kmflag)
+{
+ mp_err res = MP_OKAY;
+ mp_int t1;
+
+ MP_DIGITS(&t1) = 0;
+ MP_CHECKOK(mp_init(&t1, kmflag));
+
+ 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, int kmflag)
+{
+ mp_err res = MP_OKAY;
+ mp_int t1, t2;
+
+ MP_DIGITS(&t1) = 0;
+ MP_DIGITS(&t2) = 0;
+ MP_CHECKOK(mp_init(&t1, kmflag));
+ MP_CHECKOK(mp_init(&t2, kmflag));
+
+ 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, FLAG(x2)));
+ MP_CHECKOK(mp_init(&t4, FLAG(x2)));
+ MP_CHECKOK(mp_init(&t5, FLAG(x2)));
+
+ 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, FLAG(n)));
+ MP_CHECKOK(mp_init(&x2, FLAG(n)));
+ MP_CHECKOK(mp_init(&z1, FLAG(n)));
+ MP_CHECKOK(mp_init(&z2, FLAG(n)));
+
+ /* if result should be point at infinity */
+ if ((mp_cmp_z(n) == 0) || (ec_GF2m_pt_is_inf_aff(px, py) == MP_YES)) {
+ MP_CHECKOK(ec_GF2m_pt_set_inf_aff(rx, ry));
+ goto CLEANUP;
+ }
+
+ MP_CHECKOK(mp_copy(px, &x1)); /* x1 = px */
+ MP_CHECKOK(mp_set_int(&z1, 1)); /* z1 = 1 */
+ MP_CHECKOK(group->meth->field_sqr(&x1, &z2, group->meth)); /* z2 =
+ * x1^2 =
+ * px^2 */
+ MP_CHECKOK(group->meth->field_sqr(&z2, &x2, group->meth));
+ MP_CHECKOK(group->meth->field_add(&x2, &group->curveb, &x2, group->meth)); /* x2
+ * =
+ * px^4
+ * +
+ * b
+ */
+
+ /* find top-most bit and go one past it */
+ i = MP_USED(n) - 1;
+ j = MP_DIGIT_BIT - 1;
+ top_bit = 1;
+ top_bit <<= MP_DIGIT_BIT - 1;
+ mask = top_bit;
+ while (!(MP_DIGITS(n)[i] & mask)) {
+ mask >>= 1;
+ j--;
+ }
+ mask >>= 1;
+ j--;
+
+ /* if top most bit was at word break, go to next word */
+ if (!mask) {
+ i--;
+ j = MP_DIGIT_BIT - 1;
+ mask = top_bit;
+ }
+
+ for (; i >= 0; i--) {
+ for (; j >= 0; j--) {
+ if (MP_DIGITS(n)[i] & mask) {
+ MP_CHECKOK(gf2m_Madd(px, &x1, &z1, &x2, &z2, group, FLAG(n)));
+ MP_CHECKOK(gf2m_Mdouble(&x2, &z2, group, FLAG(n)));
+ } else {
+ MP_CHECKOK(gf2m_Madd(px, &x2, &z2, &x1, &z1, group, FLAG(n)));
+ MP_CHECKOK(gf2m_Mdouble(&x1, &z1, group, FLAG(n)));
+ }
+ 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ec_naf.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,123 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stephen Fung <fungstep@hotmail.com>, 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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;
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecc_impl.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,278 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com> and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ECC_IMPL_H
+#define _ECC_IMPL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include "ecl-exp.h"
+
+/*
+ * Multi-platform definitions
+ */
+#ifdef __linux__
+#define B_FALSE FALSE
+#define B_TRUE TRUE
+typedef unsigned char uint8_t;
+typedef unsigned long ulong_t;
+typedef enum { B_FALSE, B_TRUE } boolean_t;
+#endif /* __linux__ */
+
+#ifdef _WIN32
+typedef unsigned char uint8_t;
+typedef unsigned long ulong_t;
+typedef enum boolean { B_FALSE, B_TRUE } boolean_t;
+#endif /* _WIN32 */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif /* _KERNEL */
+
+#define EC_MAX_DIGEST_LEN 1024 /* max digest that can be signed */
+#define EC_MAX_POINT_LEN 145 /* max len of DER encoded Q */
+#define EC_MAX_VALUE_LEN 72 /* max len of ANSI X9.62 private value d */
+#define EC_MAX_SIG_LEN 144 /* max signature len for supported curves */
+#define EC_MIN_KEY_LEN 112 /* min key length in bits */
+#define EC_MAX_KEY_LEN 571 /* max key length in bits */
+#define EC_MAX_OID_LEN 10 /* max length of OID buffer */
+
+/*
+ * Various structures and definitions from NSS are here.
+ */
+
+#ifdef _KERNEL
+#define PORT_ArenaAlloc(a, n, f) kmem_alloc((n), (f))
+#define PORT_ArenaZAlloc(a, n, f) kmem_zalloc((n), (f))
+#define PORT_ArenaGrow(a, b, c, d) NULL
+#define PORT_ZAlloc(n, f) kmem_zalloc((n), (f))
+#define PORT_Alloc(n, f) kmem_alloc((n), (f))
+#else
+#define PORT_ArenaAlloc(a, n, f) malloc((n))
+#define PORT_ArenaZAlloc(a, n, f) calloc(1, (n))
+#define PORT_ArenaGrow(a, b, c, d) NULL
+#define PORT_ZAlloc(n, f) calloc(1, (n))
+#define PORT_Alloc(n, f) malloc((n))
+#endif
+
+#define PORT_NewArena(b) (char *)12345
+#define PORT_ArenaMark(a) NULL
+#define PORT_ArenaUnmark(a, b)
+#define PORT_ArenaRelease(a, m)
+#define PORT_FreeArena(a, b)
+#define PORT_Strlen(s) strlen((s))
+#define PORT_SetError(e)
+
+#define PRBool boolean_t
+#define PR_TRUE B_TRUE
+#define PR_FALSE B_FALSE
+
+#ifdef _KERNEL
+#define PORT_Assert ASSERT
+#define PORT_Memcpy(t, f, l) bcopy((f), (t), (l))
+#else
+#define PORT_Assert assert
+#define PORT_Memcpy(t, f, l) memcpy((t), (f), (l))
+#endif
+
+#define CHECK_OK(func) if (func == NULL) goto cleanup
+#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
+
+typedef enum {
+ siBuffer = 0,
+ siClearDataBuffer = 1,
+ siCipherDataBuffer = 2,
+ siDERCertBuffer = 3,
+ siEncodedCertBuffer = 4,
+ siDERNameBuffer = 5,
+ siEncodedNameBuffer = 6,
+ siAsciiNameString = 7,
+ siAsciiString = 8,
+ siDEROID = 9,
+ siUnsignedInteger = 10,
+ siUTCTime = 11,
+ siGeneralizedTime = 12
+} SECItemType;
+
+typedef struct SECItemStr SECItem;
+
+struct SECItemStr {
+ SECItemType type;
+ unsigned char *data;
+ unsigned int len;
+};
+
+typedef SECItem SECKEYECParams;
+
+typedef enum { ec_params_explicit,
+ ec_params_named
+} ECParamsType;
+
+typedef enum { ec_field_GFp = 1,
+ ec_field_GF2m
+} ECFieldType;
+
+struct ECFieldIDStr {
+ int size; /* field size in bits */
+ ECFieldType type;
+ union {
+ SECItem prime; /* prime p for (GFp) */
+ SECItem poly; /* irreducible binary polynomial for (GF2m) */
+ } u;
+ int k1; /* first coefficient of pentanomial or
+ * the only coefficient of trinomial
+ */
+ int k2; /* two remaining coefficients of pentanomial */
+ int k3;
+};
+typedef struct ECFieldIDStr ECFieldID;
+
+struct ECCurveStr {
+ SECItem a; /* contains octet stream encoding of
+ * field element (X9.62 section 4.3.3)
+ */
+ SECItem b;
+ SECItem seed;
+};
+typedef struct ECCurveStr ECCurve;
+
+typedef void PRArenaPool;
+
+struct ECParamsStr {
+ PRArenaPool * arena;
+ ECParamsType type;
+ ECFieldID fieldID;
+ ECCurve curve;
+ SECItem base;
+ SECItem order;
+ int cofactor;
+ SECItem DEREncoding;
+ ECCurveName name;
+ SECItem curveOID;
+};
+typedef struct ECParamsStr ECParams;
+
+struct ECPublicKeyStr {
+ ECParams ecParams;
+ SECItem publicValue; /* elliptic curve point encoded as
+ * octet stream.
+ */
+};
+typedef struct ECPublicKeyStr ECPublicKey;
+
+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;
+
+typedef enum _SECStatus {
+ SECBufferTooSmall = -3,
+ SECWouldBlock = -2,
+ SECFailure = -1,
+ SECSuccess = 0
+} SECStatus;
+
+#ifdef _KERNEL
+#define RNG_GenerateGlobalRandomBytes(p,l) ecc_knzero_random_generator((p), (l))
+#else
+/*
+ This function is no longer required because the random bytes are now
+ supplied by the caller. Force a failure.
+VR
+#define RNG_GenerateGlobalRandomBytes(p,l) SECFailure
+*/
+#define RNG_GenerateGlobalRandomBytes(p,l) SECSuccess
+#endif
+#define CHECK_MPI_OK(func) if (MP_OKAY > (err = func)) goto cleanup
+#define MP_TO_SEC_ERROR(err)
+
+#define SECITEM_TO_MPINT(it, mp) \
+ CHECK_MPI_OK(mp_read_unsigned_octets((mp), (it).data, (it).len))
+
+extern int ecc_knzero_random_generator(uint8_t *, size_t);
+extern ulong_t soft_nzero_random_generator(uint8_t *, ulong_t);
+
+extern SECStatus EC_DecodeParams(const SECItem *, ECParams **, int);
+extern SECItem * SECITEM_AllocItem(PRArenaPool *, SECItem *, unsigned int, int);
+extern SECStatus SECITEM_CopyItem(PRArenaPool *, SECItem *, const SECItem *,
+ int);
+extern void SECITEM_FreeItem(SECItem *, boolean_t);
+extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, const unsigned char* random, int randomlen, int);
+extern SECStatus EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
+ const unsigned char *seed, int seedlen, int kmflag);
+extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *,
+ const unsigned char* randon, int randomlen, int);
+extern SECStatus ECDSA_SignDigestWithSeed(ECPrivateKey *, SECItem *,
+ const SECItem *, const unsigned char *seed, int seedlen, int kmflag);
+extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
+ const SECItem *, int);
+extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
+ SECItem *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ECC_IMPL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecdecode.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,632 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 Cryptography library.
+ *
+ * The Initial Developer of the Original Code is
+ * Sun Microsystems, Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com> and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+
+#ifndef _WIN32
+#ifndef __linux__
+#include <sys/systm.h>
+#endif /* __linux__ */
+#include <sys/param.h>
+#endif /* _WIN32 */
+
+#ifdef _KERNEL
+#include <sys/kmem.h>
+#else
+#include <string.h>
+#endif
+#include "ec.h"
+#include "ecl-curve.h"
+#include "ecc_impl.h"
+
+#define MAX_ECKEY_LEN 72
+#define SEC_ASN1_OBJECT_ID 0x06
+
+/*
+ * Initializes a SECItem from a hexadecimal string
+ *
+ * Warning: This function ignores leading 00's, so any leading 00's
+ * in the hexadecimal string must be optional.
+ */
+static SECItem *
+hexString2SECItem(PRArenaPool *arena, SECItem *item, const char *str,
+ int kmflag)
+{
+ int i = 0;
+ int byteval = 0;
+ int tmp = strlen(str);
+
+ if ((tmp % 2) != 0) return NULL;
+
+ /* skip leading 00's unless the hex string is "00" */
+ while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
+ str += 2;
+ tmp -= 2;
+ }
+
+ item->data = (unsigned char *) PORT_ArenaAlloc(arena, tmp/2, kmflag);
+ if (item->data == NULL) return NULL;
+ item->len = tmp/2;
+
+ while (str[i]) {
+ if ((str[i] >= '0') && (str[i] <= '9'))
+ tmp = str[i] - '0';
+ else if ((str[i] >= 'a') && (str[i] <= 'f'))
+ tmp = str[i] - 'a' + 10;
+ else if ((str[i] >= 'A') && (str[i] <= 'F'))
+ tmp = str[i] - 'A' + 10;
+ else
+ return NULL;
+
+ byteval = byteval * 16 + tmp;
+ if ((i % 2) != 0) {
+ item->data[i/2] = byteval;
+ byteval = 0;
+ }
+ i++;
+ }
+
+ return item;
+}
+
+static SECStatus
+gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params,
+ int kmflag)
+{
+ SECStatus rv = SECFailure;
+ const ECCurveParams *curveParams;
+ /* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
+ char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
+
+ if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve)) goto cleanup;
+ params->name = name;
+ curveParams = ecCurve_map[params->name];
+ CHECK_OK(curveParams);
+ params->fieldID.size = curveParams->size;
+ params->fieldID.type = field_type;
+ if (field_type == ec_field_GFp) {
+ CHECK_OK(hexString2SECItem(NULL, &params->fieldID.u.prime,
+ curveParams->irr, kmflag));
+ } else {
+ CHECK_OK(hexString2SECItem(NULL, &params->fieldID.u.poly,
+ curveParams->irr, kmflag));
+ }
+ CHECK_OK(hexString2SECItem(NULL, &params->curve.a,
+ curveParams->curvea, kmflag));
+ CHECK_OK(hexString2SECItem(NULL, &params->curve.b,
+ curveParams->curveb, kmflag));
+ genenc[0] = '0';
+ genenc[1] = '4';
+ genenc[2] = '\0';
+ strcat(genenc, curveParams->genx);
+ strcat(genenc, curveParams->geny);
+ CHECK_OK(hexString2SECItem(NULL, &params->base, genenc, kmflag));
+ CHECK_OK(hexString2SECItem(NULL, &params->order,
+ curveParams->order, kmflag));
+ params->cofactor = curveParams->cofactor;
+
+ rv = SECSuccess;
+
+cleanup:
+ return rv;
+}
+
+ECCurveName SECOID_FindOIDTag(const SECItem *);
+
+SECStatus
+EC_FillParams(PRArenaPool *arena, const SECItem *encodedParams,
+ ECParams *params, int kmflag)
+{
+ SECStatus rv = SECFailure;
+ ECCurveName tag;
+ SECItem oid = { siBuffer, NULL, 0};
+
+#if EC_DEBUG
+ int i;
+
+ printf("Encoded params in EC_DecodeParams: ");
+ for (i = 0; i < encodedParams->len; i++) {
+ printf("%02x:", encodedParams->data[i]);
+ }
+ printf("\n");
+#endif
+
+ if ((encodedParams->len != ANSI_X962_CURVE_OID_TOTAL_LEN) &&
+ (encodedParams->len != SECG_CURVE_OID_TOTAL_LEN)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ };
+
+ oid.len = encodedParams->len - 2;
+ oid.data = encodedParams->data + 2;
+ if ((encodedParams->data[0] != SEC_ASN1_OBJECT_ID) ||
+ ((tag = SECOID_FindOIDTag(&oid)) == ECCurve_noName)) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+ return SECFailure;
+ }
+
+ 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(NULL, oid.len,
+ kmflag);
+ if (params->curveOID.data == NULL) goto cleanup;
+ memcpy(params->curveOID.data, oid.data, oid.len);
+
+#if EC_DEBUG
+#ifndef SECOID_FindOIDTagDescription
+ printf("Curve: %s\n", ecCurve_map[tag]->text);
+#else
+ printf("Curve: %s\n", SECOID_FindOIDTagDescription(tag));
+#endif
+#endif
+
+ switch (tag) {
+
+ /* Binary curves */
+
+ case ECCurve_X9_62_CHAR2_PNB163V1:
+ /* Populate params for c2pnb163v1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB163V2:
+ /* Populate params for c2pnb163v2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB163V3:
+ /* Populate params for c2pnb163v3 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB163V3, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB176V1:
+ /* Populate params for c2pnb176v1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB176V1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB191V1:
+ /* Populate params for c2tnb191v1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB191V2:
+ /* Populate params for c2tnb191v2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB191V3:
+ /* Populate params for c2tnb191v3 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB191V3, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB208W1:
+ /* Populate params for c2pnb208w1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB208W1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB239V1:
+ /* Populate params for c2tnb239v1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB239V2:
+ /* Populate params for c2tnb239v2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB239V3:
+ /* Populate params for c2tnb239v3 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB239V3, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB272W1:
+ /* Populate params for c2pnb272w1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB272W1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB304W1:
+ /* Populate params for c2pnb304w1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB304W1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB359V1:
+ /* Populate params for c2tnb359v1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB359V1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_PNB368W1:
+ /* Populate params for c2pnb368w1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_PNB368W1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_CHAR2_TNB431R1:
+ /* Populate params for c2tnb431r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_CHAR2_TNB431R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_113R1:
+ /* Populate params for sect113r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_113R2:
+ /* Populate params for sect113r2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_113R2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_131R1:
+ /* Populate params for sect131r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_131R2:
+ /* Populate params for sect131r2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_131R2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_163K1:
+ /* Populate params for sect163k1
+ * (the NIST K-163 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163K1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_163R1:
+ /* Populate params for sect163r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_163R2:
+ /* Populate params for sect163r2
+ * (the NIST B-163 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_163R2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_193R1:
+ /* Populate params for sect193r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_193R2:
+ /* Populate params for sect193r2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_193R2, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_233K1:
+ /* Populate params for sect233k1
+ * (the NIST K-233 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233K1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_233R1:
+ /* Populate params for sect233r1
+ * (the NIST B-233 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_233R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_239K1:
+ /* Populate params for sect239k1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_239K1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_283K1:
+ /* Populate params for sect283k1
+ * (the NIST K-283 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283K1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_283R1:
+ /* Populate params for sect283r1
+ * (the NIST B-283 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_283R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_409K1:
+ /* Populate params for sect409k1
+ * (the NIST K-409 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409K1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_409R1:
+ /* Populate params for sect409r1
+ * (the NIST B-409 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_409R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_571K1:
+ /* Populate params for sect571k1
+ * (the NIST K-571 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571K1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_CHAR2_571R1:
+ /* Populate params for sect571r1
+ * (the NIST B-571 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_CHAR2_571R1, ec_field_GF2m,
+ params, kmflag) );
+ break;
+
+ /* Prime curves */
+
+ case ECCurve_X9_62_PRIME_192V1:
+ /* Populate params for prime192v1 aka secp192r1
+ * (the NIST P-192 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_PRIME_192V2:
+ /* Populate params for prime192v2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V2, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_PRIME_192V3:
+ /* Populate params for prime192v3 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_192V3, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_PRIME_239V1:
+ /* Populate params for prime239v1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_PRIME_239V2:
+ /* Populate params for prime239v2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V2, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_PRIME_239V3:
+ /* Populate params for prime239v3 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_239V3, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_X9_62_PRIME_256V1:
+ /* Populate params for prime256v1 aka secp256r1
+ * (the NIST P-256 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_112R1:
+ /* Populate params for secp112r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_112R2:
+ /* Populate params for secp112r2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_112R2, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_128R1:
+ /* Populate params for secp128r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_128R2:
+ /* Populate params for secp128r2 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_128R2, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_160K1:
+ /* Populate params for secp160k1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160K1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_160R1:
+ /* Populate params for secp160r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_160R2:
+ /* Populate params for secp160r1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_160R2, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_192K1:
+ /* Populate params for secp192k1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_192K1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_224K1:
+ /* Populate params for secp224k1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224K1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_224R1:
+ /* Populate params for secp224r1
+ * (the NIST P-224 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_224R1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_256K1:
+ /* Populate params for secp256k1 */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_256K1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_384R1:
+ /* Populate params for secp384r1
+ * (the NIST P-384 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ case ECCurve_SECG_PRIME_521R1:
+ /* Populate params for secp521r1
+ * (the NIST P-521 curve)
+ */
+ CHECK_SEC_OK( gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
+ params, kmflag) );
+ break;
+
+ default:
+ break;
+ };
+
+cleanup:
+ if (!params->cofactor) {
+ PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
+#if EC_DEBUG
+ printf("Unrecognized curve, returning NULL params\n");
+#endif
+ }
+
+ return rv;
+}
+
+SECStatus
+EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams, int kmflag)
+{
+ PRArenaPool *arena;
+ ECParams *params;
+ SECStatus rv = SECFailure;
+
+ /* Initialize an arena for the ECParams structure */
+ if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
+ return SECFailure;
+
+ params = (ECParams *)PORT_ArenaZAlloc(NULL, sizeof(ECParams), kmflag);
+ if (!params) {
+ PORT_FreeArena(NULL, B_TRUE);
+ return SECFailure;
+ }
+
+ /* Copy the encoded params */
+ SECITEM_AllocItem(arena, &(params->DEREncoding), encodedParams->len,
+ kmflag);
+ memcpy(params->DEREncoding.data, encodedParams->data, encodedParams->len);
+
+ /* Fill out the rest of the ECParams structure based on
+ * the encoded params
+ */
+ rv = EC_FillParams(NULL, encodedParams, params, kmflag);
+ if (rv == SECFailure) {
+ PORT_FreeArena(NULL, B_TRUE);
+ return SECFailure;
+ } else {
+ *ecparams = params;;
+ return SECSuccess;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl-curve.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,710 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ECL_CURVE_H
+#define _ECL_CURVE_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecl-exp.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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 /* _ECL_CURVE_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl-exp.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,216 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ECL_EXP_H
+#define _ECL_EXP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl-priv.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,304 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stephen Fung <fungstep@hotmail.com> and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ECL_PRIV_H
+#define _ECL_PRIV_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecl.h"
+#include "mpi.h"
+#include "mplogic.h"
+
+/* MAX_FIELD_SIZE_DIGITS is the maximum size of field element supported */
+/* the following needs to go away... */
+#if defined(MP_USE_LONG_LONG_DIGIT) || defined(MP_USE_LONG_DIGIT)
+#define ECL_SIXTY_FOUR_BIT
+#else
+#define ECL_THIRTY_TWO_BIT
+#endif
+
+#define ECL_CURVE_DIGITS(curve_size_in_bits) \
+ (((curve_size_in_bits)+(sizeof(mp_digit)*8-1))/(sizeof(mp_digit)*8))
+#define ECL_BITS (sizeof(mp_digit)*8)
+#define ECL_MAX_FIELD_SIZE_DIGITS (80/sizeof(mp_digit))
+
+/* 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))
+
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
+ { mp_word w; \
+ w = ((mp_word)(cin)) + (a1) + (a2); \
+ s = ACCUM(w); \
+ cout = CARRYOUT(w); }
+
+#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
+ { mp_word w; \
+ w = ((mp_word)(a1)) - (a2) - (bin); \
+ s = ACCUM(w); \
+ bout = (w >> MP_DIGIT_BIT) & 1; }
+
+#else
+/* NOTE,
+ * cin and cout could be the same variable.
+ * bin and bout could be the same variable.
+ * a1 or a2 and s could be the same variable.
+ * don't trash those outputs until their respective inputs have
+ * been read. */
+#define MP_ADD_CARRY(a1, a2, s, cin, cout) \
+ { mp_digit tmp,sum; \
+ tmp = (a1); \
+ sum = tmp + (a2); \
+ tmp = (sum < tmp); /* detect overflow */ \
+ s = sum += (cin); \
+ cout = tmp + (sum < (cin)); }
+
+#define MP_SUB_BORROW(a1, a2, s, bin, bout) \
+ { mp_digit tmp; \
+ tmp = (a1); \
+ s = tmp - (a2); \
+ tmp = (s > tmp); /* detect borrow */ \
+ if ((bin) && !s--) tmp++; \
+ bout = tmp; }
+#endif
+
+
+struct GFMethodStr;
+typedef struct GFMethodStr GFMethod;
+struct GFMethodStr {
+ /* Indicates whether the structure was constructed from dynamic memory
+ * or statically created. */
+ int constructed;
+ /* Irreducible that defines the field. For prime fields, this is the
+ * prime p. For binary polynomial fields, this is the bitstring
+ * representation of the irreducible polynomial. */
+ mp_int irr;
+ /* For prime fields, the value irr_arr[0] is the number of bits in the
+ * field. For binary polynomial fields, the irreducible polynomial
+ * f(t) is represented as an array of unsigned int[], where f(t) is
+ * of the form: f(t) = t^p[0] + t^p[1] + ... + t^p[4] where m = p[0]
+ * > p[1] > ... > p[4] = 0. */
+ unsigned int irr_arr[5];
+ /* Field arithmetic methods. All methods (except field_enc and
+ * field_dec) are assumed to take field-encoded parameters and return
+ * field-encoded values. All methods (except field_enc and field_dec)
+ * are required to be implemented. */
+ mp_err (*field_add) (const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+ mp_err (*field_neg) (const mp_int *a, mp_int *r, const GFMethod *meth);
+ mp_err (*field_sub) (const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+ mp_err (*field_mod) (const mp_int *a, mp_int *r, const GFMethod *meth);
+ mp_err (*field_mul) (const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+ mp_err (*field_sqr) (const mp_int *a, mp_int *r, const GFMethod *meth);
+ mp_err (*field_div) (const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+ mp_err (*field_enc) (const mp_int *a, mp_int *r, const GFMethod *meth);
+ mp_err (*field_dec) (const mp_int *a, mp_int *r, const GFMethod *meth);
+ /* Extra storage for implementation-specific data. Any memory
+ * allocated to these extra fields will be cleared by extra_free. */
+ void *extra1;
+ void *extra2;
+ void (*extra_free) (GFMethod *meth);
+};
+
+/* 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;
+#ifdef _KERNEL
+ int text_len;
+#endif
+ /* Curve parameters, field-encoded. */
+ mp_int curvea, curveb;
+ /* x and y coordinates of the base point, field-encoded. */
+ mp_int genx, geny;
+ /* Order and cofactor of the base point. */
+ mp_int order;
+ int cofactor;
+ /* Point arithmetic methods. All methods are assumed to take
+ * field-encoded parameters and return field-encoded values. All
+ * methods (except base_point_mul and points_mul) are required to be
+ * implemented. */
+ mp_err (*point_add) (const mp_int *px, const mp_int *py,
+ const mp_int *qx, const mp_int *qy, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+ mp_err (*point_sub) (const mp_int *px, const mp_int *py,
+ const mp_int *qx, const mp_int *qy, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+ mp_err (*point_dbl) (const mp_int *px, const mp_int *py, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+ mp_err (*point_mul) (const mp_int *n, const mp_int *px,
+ const mp_int *py, mp_int *rx, mp_int *ry,
+ const ECGroup *group);
+ mp_err (*base_point_mul) (const mp_int *n, mp_int *rx, mp_int *ry,
+ const ECGroup *group);
+ mp_err (*points_mul) (const mp_int *k1, const mp_int *k2,
+ const mp_int *px, const mp_int *py, mp_int *rx,
+ mp_int *ry, const ECGroup *group);
+ mp_err (*validate_point) (const mp_int *px, const mp_int *py, const ECGroup *group);
+ /* Extra storage for implementation-specific data. Any memory
+ * allocated to these extra fields will be cleared by extra_free. */
+ void *extra1;
+ void *extra2;
+ void (*extra_free) (ECGroup *group);
+};
+
+/* Wrapper functions for generic prime field arithmetic. */
+mp_err ec_GFp_add(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+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);
+
+/* fixed length in-line adds. Count is in words */
+mp_err ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth);
+mp_err ec_GFp_sub_6(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_gfp256(ECGroup *group, ECCurveName);
+mp_err ec_group_set_gfp384(ECGroup *group, ECCurveName);
+mp_err ec_group_set_gfp521(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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,475 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "mpi.h"
+#include "mplogic.h"
+#include "ecl.h"
+#include "ecl-priv.h"
+#include "ec2.h"
+#include "ecp.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+/* Allocate memory for a new ECGroup object. */
+ECGroup *
+ECGroup_new(int kmflag)
+{
+ mp_err res = MP_OKAY;
+ ECGroup *group;
+#ifdef _KERNEL
+ group = (ECGroup *) kmem_alloc(sizeof(ECGroup), kmflag);
+#else
+ group = (ECGroup *) malloc(sizeof(ECGroup));
+#endif
+ if (group == NULL)
+ return NULL;
+ group->constructed = MP_YES;
+ group->meth = NULL;
+ group->text = NULL;
+ MP_DIGITS(&group->curvea) = 0;
+ MP_DIGITS(&group->curveb) = 0;
+ MP_DIGITS(&group->genx) = 0;
+ MP_DIGITS(&group->geny) = 0;
+ MP_DIGITS(&group->order) = 0;
+ group->base_point_mul = NULL;
+ group->points_mul = NULL;
+ group->validate_point = NULL;
+ group->extra1 = NULL;
+ group->extra2 = NULL;
+ group->extra_free = NULL;
+ MP_CHECKOK(mp_init(&group->curvea, kmflag));
+ MP_CHECKOK(mp_init(&group->curveb, kmflag));
+ MP_CHECKOK(mp_init(&group->genx, kmflag));
+ MP_CHECKOK(mp_init(&group->geny, kmflag));
+ MP_CHECKOK(mp_init(&group->order, kmflag));
+
+ 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(FLAG(irr));
+ if (group == NULL)
+ return NULL;
+
+ group->meth = GFMethod_consGFp(irr);
+ if (group->meth == NULL) {
+ res = MP_MEM;
+ goto CLEANUP;
+ }
+ MP_CHECKOK(mp_copy(curvea, &group->curvea));
+ MP_CHECKOK(mp_copy(curveb, &group->curveb));
+ MP_CHECKOK(mp_copy(genx, &group->genx));
+ MP_CHECKOK(mp_copy(geny, &group->geny));
+ MP_CHECKOK(mp_copy(order, &group->order));
+ group->cofactor = cofactor;
+ group->point_add = &ec_GFp_pt_add_aff;
+ group->point_sub = &ec_GFp_pt_sub_aff;
+ group->point_dbl = &ec_GFp_pt_dbl_aff;
+ group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
+ group->base_point_mul = NULL;
+ group->points_mul = &ec_GFp_pts_mul_jac;
+ group->validate_point = &ec_GFp_validate_point;
+
+ 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(FLAG(irr));
+ if (group == NULL)
+ return NULL;
+
+ group->meth = GFMethod_consGFp_mont(irr);
+ if (group->meth == NULL) {
+ res = MP_MEM;
+ goto CLEANUP;
+ }
+ MP_CHECKOK(group->meth->
+ field_enc(curvea, &group->curvea, group->meth));
+ MP_CHECKOK(group->meth->
+ field_enc(curveb, &group->curveb, group->meth));
+ MP_CHECKOK(group->meth->field_enc(genx, &group->genx, group->meth));
+ MP_CHECKOK(group->meth->field_enc(geny, &group->geny, group->meth));
+ MP_CHECKOK(mp_copy(order, &group->order));
+ group->cofactor = cofactor;
+ group->point_add = &ec_GFp_pt_add_aff;
+ group->point_sub = &ec_GFp_pt_sub_aff;
+ group->point_dbl = &ec_GFp_pt_dbl_aff;
+ group->point_mul = &ec_GFp_pt_mul_jm_wNAF;
+ group->base_point_mul = NULL;
+ group->points_mul = &ec_GFp_pts_mul_jac;
+ group->validate_point = &ec_GFp_validate_point;
+
+ CLEANUP:
+ if (res != MP_OKAY) {
+ ECGroup_free(group);
+ return NULL;
+ }
+ return group;
+}
+
+#ifdef NSS_ECC_MORE_THAN_SUITE_B
+/* Construct a generic ECGroup for elliptic curves over binary polynomial
+ * fields. */
+ECGroup *
+ECGroup_consGF2m(const mp_int *irr, const unsigned int irr_arr[5],
+ const mp_int *curvea, const mp_int *curveb,
+ const mp_int *genx, const mp_int *geny,
+ const mp_int *order, int cofactor)
+{
+ mp_err res = MP_OKAY;
+ ECGroup *group = NULL;
+
+ group = ECGroup_new(FLAG(irr));
+ if (group == NULL)
+ return NULL;
+
+ group->meth = GFMethod_consGF2m(irr, irr_arr);
+ if (group->meth == NULL) {
+ res = MP_MEM;
+ goto CLEANUP;
+ }
+ MP_CHECKOK(mp_copy(curvea, &group->curvea));
+ MP_CHECKOK(mp_copy(curveb, &group->curveb));
+ MP_CHECKOK(mp_copy(genx, &group->genx));
+ MP_CHECKOK(mp_copy(geny, &group->geny));
+ MP_CHECKOK(mp_copy(order, &group->order));
+ group->cofactor = cofactor;
+ group->point_add = &ec_GF2m_pt_add_aff;
+ group->point_sub = &ec_GF2m_pt_sub_aff;
+ group->point_dbl = &ec_GF2m_pt_dbl_aff;
+ group->point_mul = &ec_GF2m_pt_mul_mont;
+ group->base_point_mul = NULL;
+ group->points_mul = &ec_pts_mul_basic;
+ group->validate_point = &ec_GF2m_validate_point;
+
+ CLEANUP:
+ if (res != MP_OKAY) {
+ ECGroup_free(group);
+ return NULL;
+ }
+ return group;
+}
+#endif
+
+/* Construct ECGroup from hex parameters and name, if any. Called by
+ * ECGroup_fromHex and ECGroup_fromName. */
+ECGroup *
+ecgroup_fromNameAndHex(const ECCurveName name,
+ const ECCurveParams * params, int kmflag)
+{
+ 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, kmflag));
+ MP_CHECKOK(mp_init(&curvea, kmflag));
+ MP_CHECKOK(mp_init(&curveb, kmflag));
+ MP_CHECKOK(mp_init(&genx, kmflag));
+ MP_CHECKOK(mp_init(&geny, kmflag));
+ MP_CHECKOK(mp_init(&order, kmflag));
+ 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) {
+#ifdef NSS_ECC_MORE_THAN_SUITE_B
+ switch (name) {
+#ifdef ECL_USE_FP
+ case ECCurve_SECG_PRIME_160R1:
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_secp160r1_fp(group));
+ break;
+#endif
+ case ECCurve_SECG_PRIME_192R1:
+#ifdef ECL_USE_FP
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_nistp192_fp(group));
+#else
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_gfp192(group, name));
+#endif
+ break;
+ case ECCurve_SECG_PRIME_224R1:
+#ifdef ECL_USE_FP
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_nistp224_fp(group));
+#else
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_gfp224(group, name));
+#endif
+ break;
+ case ECCurve_SECG_PRIME_256R1:
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_gfp256(group, name));
+ break;
+ case ECCurve_SECG_PRIME_521R1:
+ group =
+ ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ MP_CHECKOK(ec_group_set_gfp521(group, name));
+ break;
+ default:
+ /* use generic arithmetic */
+#endif
+ group =
+ ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
+ &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+#ifdef NSS_ECC_MORE_THAN_SUITE_B
+ }
+ } else if (params->field == ECField_GF2m) {
+ group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx, &geny, &order, params->cofactor);
+ if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
+ if ((name == ECCurve_NIST_K163) ||
+ (name == ECCurve_NIST_B163) ||
+ (name == ECCurve_SECG_CHAR2_163R1)) {
+ MP_CHECKOK(ec_group_set_gf2m163(group, name));
+ } else if ((name == ECCurve_SECG_CHAR2_193R1) ||
+ (name == ECCurve_SECG_CHAR2_193R2)) {
+ MP_CHECKOK(ec_group_set_gf2m193(group, name));
+ } else if ((name == ECCurve_NIST_K233) ||
+ (name == ECCurve_NIST_B233)) {
+ MP_CHECKOK(ec_group_set_gf2m233(group, name));
+ }
+#endif
+ } else {
+ res = MP_UNDEF;
+ goto CLEANUP;
+ }
+
+ /* set name, if any */
+ if ((group != NULL) && (params->text != NULL)) {
+#ifdef _KERNEL
+ int n = strlen(params->text) + 1;
+
+ group->text = kmem_alloc(n, kmflag);
+ if (group->text == NULL) {
+ res = MP_MEM;
+ goto CLEANUP;
+ }
+ bcopy(params->text, group->text, n);
+ group->text_len = n;
+#else
+ group->text = strdup(params->text);
+ if (group->text == NULL) {
+ res = MP_MEM;
+ }
+#endif
+ }
+
+ CLEANUP:
+ mp_clear(&irr);
+ mp_clear(&curvea);
+ mp_clear(&curveb);
+ mp_clear(&genx);
+ mp_clear(&geny);
+ mp_clear(&order);
+ if (res != MP_OKAY) {
+ ECGroup_free(group);
+ return NULL;
+ }
+ return group;
+}
+
+/* Construct ECGroup from hexadecimal representations of parameters. */
+ECGroup *
+ECGroup_fromHex(const ECCurveParams * params, int kmflag)
+{
+ return ecgroup_fromNameAndHex(ECCurve_noName, params, kmflag);
+}
+
+/* Construct ECGroup from named parameters. */
+ECGroup *
+ECGroup_fromName(const ECCurveName name, int kmflag)
+{
+ ECGroup *group = NULL;
+ ECCurveParams *params = NULL;
+ mp_err res = MP_OKAY;
+
+ params = EC_GetNamedCurveParams(name, kmflag);
+ if (params == NULL) {
+ res = MP_UNDEF;
+ goto CLEANUP;
+ }
+
+ /* construct actual group */
+ group = ecgroup_fromNameAndHex(name, params, kmflag);
+ if (group == NULL) {
+ res = MP_UNDEF;
+ goto CLEANUP;
+ }
+
+ CLEANUP:
+ EC_FreeCurveParams(params);
+ if (res != MP_OKAY) {
+ ECGroup_free(group);
+ return NULL;
+ }
+ return group;
+}
+
+/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
+mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
+ mp_int *py)
+{
+ /* 1: Verify that publicValue is not the point at infinity */
+ /* 2: Verify that the coordinates of publicValue are elements
+ * of the field.
+ */
+ /* 3: Verify that publicValue is on the curve. */
+ /* 4: Verify that the order of the curve times the publicValue
+ * is the point at infinity.
+ */
+ return group->validate_point(px, py, group);
+}
+
+/* Free the memory allocated (if any) to an ECGroup object. */
+void
+ECGroup_free(ECGroup *group)
+{
+ if (group == NULL)
+ return;
+ GFMethod_free(group->meth);
+ if (group->constructed == MP_NO)
+ return;
+ mp_clear(&group->curvea);
+ mp_clear(&group->curveb);
+ mp_clear(&group->genx);
+ mp_clear(&group->geny);
+ mp_clear(&group->order);
+ if (group->text != NULL)
+#ifdef _KERNEL
+ kmem_free(group->text, group->text_len);
+#else
+ free(group->text);
+#endif
+ if (group->extra_free != NULL)
+ group->extra_free(group);
+#ifdef _KERNEL
+ kmem_free(group, sizeof (ECGroup));
+#else
+ free(group);
+#endif
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,111 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ECL_H
+#define _ECL_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Although this is not an exported header file, code which uses elliptic
+ * curve point operations will need to include it. */
+
+#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, int kmflag);
+
+/* Construct ECGroup from named parameters. */
+ECGroup *ECGroup_fromName(const ECCurveName name, int kmflag);
+
+/* Free an allocated ECGroup. */
+void ECGroup_free(ECGroup *group);
+
+/* Construct ECCurveParams from an ECCurveName */
+ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name, int kmflag);
+
+/* Duplicates an ECCurveParams */
+ECCurveParams *ECCurveParams_dup(const ECCurveParams * params, int kmflag);
+
+/* 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);
+
+/* Validates an EC public key as described in Section 5.2.2 of X9.62.
+ * Returns MP_YES if the public key is valid, MP_NO if the public key
+ * is invalid, or an error code if the validation could not be
+ * performed. */
+mp_err ECPoint_validate(const ECGroup *group, const mp_int *px, const
+ mp_int *py);
+
+#endif /* _ECL_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl_curve.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,216 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecl.h"
+#include "ecl-curve.h"
+#include "ecl-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#define CHECK(func) if ((func) == NULL) { res = 0; goto CLEANUP; }
+
+/* Duplicates an ECCurveParams */
+ECCurveParams *
+ECCurveParams_dup(const ECCurveParams * params, int kmflag)
+{
+ int res = 1;
+ ECCurveParams *ret = NULL;
+
+#ifdef _KERNEL
+ ret = (ECCurveParams *) kmem_zalloc(sizeof(ECCurveParams), kmflag);
+#else
+ CHECK(ret = (ECCurveParams *) calloc(1, sizeof(ECCurveParams)));
+#endif
+ if (params->text != NULL) {
+#ifdef _KERNEL
+ ret->text = kmem_alloc(strlen(params->text) + 1, kmflag);
+ bcopy(params->text, ret->text, strlen(params->text) + 1);
+#else
+ CHECK(ret->text = strdup(params->text));
+#endif
+ }
+ ret->field = params->field;
+ ret->size = params->size;
+ if (params->irr != NULL) {
+#ifdef _KERNEL
+ ret->irr = kmem_alloc(strlen(params->irr) + 1, kmflag);
+ bcopy(params->irr, ret->irr, strlen(params->irr) + 1);
+#else
+ CHECK(ret->irr = strdup(params->irr));
+#endif
+ }
+ if (params->curvea != NULL) {
+#ifdef _KERNEL
+ ret->curvea = kmem_alloc(strlen(params->curvea) + 1, kmflag);
+ bcopy(params->curvea, ret->curvea, strlen(params->curvea) + 1);
+#else
+ CHECK(ret->curvea = strdup(params->curvea));
+#endif
+ }
+ if (params->curveb != NULL) {
+#ifdef _KERNEL
+ ret->curveb = kmem_alloc(strlen(params->curveb) + 1, kmflag);
+ bcopy(params->curveb, ret->curveb, strlen(params->curveb) + 1);
+#else
+ CHECK(ret->curveb = strdup(params->curveb));
+#endif
+ }
+ if (params->genx != NULL) {
+#ifdef _KERNEL
+ ret->genx = kmem_alloc(strlen(params->genx) + 1, kmflag);
+ bcopy(params->genx, ret->genx, strlen(params->genx) + 1);
+#else
+ CHECK(ret->genx = strdup(params->genx));
+#endif
+ }
+ if (params->geny != NULL) {
+#ifdef _KERNEL
+ ret->geny = kmem_alloc(strlen(params->geny) + 1, kmflag);
+ bcopy(params->geny, ret->geny, strlen(params->geny) + 1);
+#else
+ CHECK(ret->geny = strdup(params->geny));
+#endif
+ }
+ if (params->order != NULL) {
+#ifdef _KERNEL
+ ret->order = kmem_alloc(strlen(params->order) + 1, kmflag);
+ bcopy(params->order, ret->order, strlen(params->order) + 1);
+#else
+ CHECK(ret->order = strdup(params->order));
+#endif
+ }
+ 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, int kmflag)
+{
+ if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
+ (ecCurve_map[name] == NULL)) {
+ return NULL;
+ } else {
+ return ECCurveParams_dup(ecCurve_map[name], kmflag);
+ }
+}
+
+/* Free the memory allocated (if any) to an ECCurveParams object. */
+void
+EC_FreeCurveParams(ECCurveParams * params)
+{
+ if (params == NULL)
+ return;
+ if (params->text != NULL)
+#ifdef _KERNEL
+ kmem_free(params->text, strlen(params->text) + 1);
+#else
+ free(params->text);
+#endif
+ if (params->irr != NULL)
+#ifdef _KERNEL
+ kmem_free(params->irr, strlen(params->irr) + 1);
+#else
+ free(params->irr);
+#endif
+ if (params->curvea != NULL)
+#ifdef _KERNEL
+ kmem_free(params->curvea, strlen(params->curvea) + 1);
+#else
+ free(params->curvea);
+#endif
+ if (params->curveb != NULL)
+#ifdef _KERNEL
+ kmem_free(params->curveb, strlen(params->curveb) + 1);
+#else
+ free(params->curveb);
+#endif
+ if (params->genx != NULL)
+#ifdef _KERNEL
+ kmem_free(params->genx, strlen(params->genx) + 1);
+#else
+ free(params->genx);
+#endif
+ if (params->geny != NULL)
+#ifdef _KERNEL
+ kmem_free(params->geny, strlen(params->geny) + 1);
+#else
+ free(params->geny);
+#endif
+ if (params->order != NULL)
+#ifdef _KERNEL
+ kmem_free(params->order, strlen(params->order) + 1);
+#else
+ free(params->order);
+#endif
+#ifdef _KERNEL
+ kmem_free(params, sizeof(ECCurveParams));
+#else
+ free(params);
+#endif
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl_gf.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,1062 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stephen Fung <fungstep@hotmail.com> and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "mpi.h"
+#include "mp_gf2m.h"
+#include "ecl-priv.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* Allocate memory for a new GFMethod object. */
+GFMethod *
+GFMethod_new(int kmflag)
+{
+ mp_err res = MP_OKAY;
+ GFMethod *meth;
+#ifdef _KERNEL
+ meth = (GFMethod *) kmem_alloc(sizeof(GFMethod), kmflag);
+#else
+ meth = (GFMethod *) malloc(sizeof(GFMethod));
+ if (meth == NULL)
+ return NULL;
+#endif
+ meth->constructed = MP_YES;
+ MP_DIGITS(&meth->irr) = 0;
+ meth->extra_free = NULL;
+ MP_CHECKOK(mp_init(&meth->irr, kmflag));
+
+ 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(FLAG(irr));
+ if (meth == NULL)
+ return NULL;
+
+ MP_CHECKOK(mp_copy(irr, &meth->irr));
+ meth->irr_arr[0] = mpl_significant_bits(irr);
+ meth->irr_arr[1] = meth->irr_arr[2] = meth->irr_arr[3] =
+ meth->irr_arr[4] = 0;
+ switch(MP_USED(&meth->irr)) {
+ /* maybe we need 1 and 2 words here as well?*/
+ case 3:
+ meth->field_add = &ec_GFp_add_3;
+ meth->field_sub = &ec_GFp_sub_3;
+ break;
+ case 4:
+ meth->field_add = &ec_GFp_add_4;
+ meth->field_sub = &ec_GFp_sub_4;
+ break;
+ case 5:
+ meth->field_add = &ec_GFp_add_5;
+ meth->field_sub = &ec_GFp_sub_5;
+ break;
+ case 6:
+ meth->field_add = &ec_GFp_add_6;
+ meth->field_sub = &ec_GFp_sub_6;
+ break;
+ default:
+ meth->field_add = &ec_GFp_add;
+ meth->field_sub = &ec_GFp_sub;
+ }
+ meth->field_neg = &ec_GFp_neg;
+ meth->field_mod = &ec_GFp_mod;
+ meth->field_mul = &ec_GFp_mul;
+ meth->field_sqr = &ec_GFp_sqr;
+ meth->field_div = &ec_GFp_div;
+ meth->field_enc = NULL;
+ meth->field_dec = NULL;
+ meth->extra1 = NULL;
+ meth->extra2 = NULL;
+ meth->extra_free = NULL;
+
+ CLEANUP:
+ if (res != MP_OKAY) {
+ GFMethod_free(meth);
+ return NULL;
+ }
+ return meth;
+}
+
+/* Construct a generic GFMethod for arithmetic over binary polynomial
+ * fields with irreducible irr that has array representation irr_arr (see
+ * ecl-priv.h for description of the representation). If irr_arr is NULL,
+ * then it is constructed from the bitstring representation. */
+GFMethod *
+GFMethod_consGF2m(const mp_int *irr, const unsigned int irr_arr[5])
+{
+ mp_err res = MP_OKAY;
+ int ret;
+ GFMethod *meth = NULL;
+
+ meth = GFMethod_new(FLAG(irr));
+ 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;
+ mp_clear(&meth->irr);
+ if (meth->extra_free != NULL)
+ meth->extra_free(meth);
+#ifdef _KERNEL
+ kmem_free(meth, sizeof(GFMethod));
+#else
+ free(meth);
+#endif
+}
+
+/* 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;
+}
+/*
+ * Inline adds for small curve lengths.
+ */
+/* 3 words */
+mp_err
+ec_GFp_add_3(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit a0 = 0, a1 = 0, a2 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0;
+ mp_digit carry;
+
+ switch(MP_USED(a)) {
+ case 3:
+ a2 = MP_DIGIT(a,2);
+ case 2:
+ a1 = MP_DIGIT(a,1);
+ case 1:
+ a0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 3:
+ r2 = MP_DIGIT(b,2);
+ case 2:
+ r1 = MP_DIGIT(b,1);
+ case 1:
+ r0 = MP_DIGIT(b,0);
+ }
+
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(a0, r0, r0, 0, carry);
+ MP_ADD_CARRY(a1, r1, r1, carry, carry);
+ MP_ADD_CARRY(a2, r2, r2, carry, carry);
+#else
+ __asm__ (
+ "xorq %3,%3 \n\t"
+ "addq %4,%0 \n\t"
+ "adcq %5,%1 \n\t"
+ "adcq %6,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
+ : "r" (a0), "r" (a1), "r" (a2),
+ "0" (r0), "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+
+ MP_CHECKOK(s_mp_pad(r, 3));
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 3;
+
+ /* Do quick 'subract' if we've gone over
+ * (add the 2's complement of the curve field) */
+ a2 = MP_DIGIT(&meth->irr,2);
+ if (carry || r2 > a2 ||
+ ((r2 == a2) && mp_cmp(r,&meth->irr) != MP_LT)) {
+ a1 = MP_DIGIT(&meth->irr,1);
+ a0 = MP_DIGIT(&meth->irr,0);
+#ifndef MPI_AMD64_ADD
+ MP_SUB_BORROW(r0, a0, r0, 0, carry);
+ MP_SUB_BORROW(r1, a1, r1, carry, carry);
+ MP_SUB_BORROW(r2, a2, r2, carry, carry);
+#else
+ __asm__ (
+ "subq %3,%0 \n\t"
+ "sbbq %4,%1 \n\t"
+ "sbbq %5,%2 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2)
+ : "r" (a0), "r" (a1), "r" (a2),
+ "0" (r0), "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ }
+
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/* 4 words */
+mp_err
+ec_GFp_add_4(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
+ mp_digit carry;
+
+ switch(MP_USED(a)) {
+ case 4:
+ a3 = MP_DIGIT(a,3);
+ case 3:
+ a2 = MP_DIGIT(a,2);
+ case 2:
+ a1 = MP_DIGIT(a,1);
+ case 1:
+ a0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 4:
+ r3 = MP_DIGIT(b,3);
+ case 3:
+ r2 = MP_DIGIT(b,2);
+ case 2:
+ r1 = MP_DIGIT(b,1);
+ case 1:
+ r0 = MP_DIGIT(b,0);
+ }
+
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(a0, r0, r0, 0, carry);
+ MP_ADD_CARRY(a1, r1, r1, carry, carry);
+ MP_ADD_CARRY(a2, r2, r2, carry, carry);
+ MP_ADD_CARRY(a3, r3, r3, carry, carry);
+#else
+ __asm__ (
+ "xorq %4,%4 \n\t"
+ "addq %5,%0 \n\t"
+ "adcq %6,%1 \n\t"
+ "adcq %7,%2 \n\t"
+ "adcq %8,%3 \n\t"
+ "adcq $0,%4 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(carry)
+ : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
+ "0" (r0), "1" (r1), "2" (r2), "3" (r3)
+ : "%cc" );
+#endif
+
+ MP_CHECKOK(s_mp_pad(r, 4));
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 4;
+
+ /* Do quick 'subract' if we've gone over
+ * (add the 2's complement of the curve field) */
+ a3 = MP_DIGIT(&meth->irr,3);
+ if (carry || r3 > a3 ||
+ ((r3 == a3) && mp_cmp(r,&meth->irr) != MP_LT)) {
+ a2 = MP_DIGIT(&meth->irr,2);
+ a1 = MP_DIGIT(&meth->irr,1);
+ a0 = MP_DIGIT(&meth->irr,0);
+#ifndef MPI_AMD64_ADD
+ MP_SUB_BORROW(r0, a0, r0, 0, carry);
+ MP_SUB_BORROW(r1, a1, r1, carry, carry);
+ MP_SUB_BORROW(r2, a2, r2, carry, carry);
+ MP_SUB_BORROW(r3, a3, r3, carry, carry);
+#else
+ __asm__ (
+ "subq %4,%0 \n\t"
+ "sbbq %5,%1 \n\t"
+ "sbbq %6,%2 \n\t"
+ "sbbq %7,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
+ : "r" (a0), "r" (a1), "r" (a2), "r" (a3),
+ "0" (r0), "1" (r1), "2" (r2), "3" (r3)
+ : "%cc" );
+#endif
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ }
+
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/* 5 words */
+mp_err
+ec_GFp_add_5(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
+ mp_digit carry;
+
+ switch(MP_USED(a)) {
+ case 5:
+ a4 = MP_DIGIT(a,4);
+ case 4:
+ a3 = MP_DIGIT(a,3);
+ case 3:
+ a2 = MP_DIGIT(a,2);
+ case 2:
+ a1 = MP_DIGIT(a,1);
+ case 1:
+ a0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 5:
+ r4 = MP_DIGIT(b,4);
+ case 4:
+ r3 = MP_DIGIT(b,3);
+ case 3:
+ r2 = MP_DIGIT(b,2);
+ case 2:
+ r1 = MP_DIGIT(b,1);
+ case 1:
+ r0 = MP_DIGIT(b,0);
+ }
+
+ MP_ADD_CARRY(a0, r0, r0, 0, carry);
+ MP_ADD_CARRY(a1, r1, r1, carry, carry);
+ MP_ADD_CARRY(a2, r2, r2, carry, carry);
+ MP_ADD_CARRY(a3, r3, r3, carry, carry);
+ MP_ADD_CARRY(a4, r4, r4, carry, carry);
+
+ MP_CHECKOK(s_mp_pad(r, 5));
+ MP_DIGIT(r, 4) = r4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 5;
+
+ /* Do quick 'subract' if we've gone over
+ * (add the 2's complement of the curve field) */
+ a4 = MP_DIGIT(&meth->irr,4);
+ if (carry || r4 > a4 ||
+ ((r4 == a4) && mp_cmp(r,&meth->irr) != MP_LT)) {
+ a3 = MP_DIGIT(&meth->irr,3);
+ a2 = MP_DIGIT(&meth->irr,2);
+ a1 = MP_DIGIT(&meth->irr,1);
+ a0 = MP_DIGIT(&meth->irr,0);
+ MP_SUB_BORROW(r0, a0, r0, 0, carry);
+ MP_SUB_BORROW(r1, a1, r1, carry, carry);
+ MP_SUB_BORROW(r2, a2, r2, carry, carry);
+ MP_SUB_BORROW(r3, a3, r3, carry, carry);
+ MP_SUB_BORROW(r4, a4, r4, carry, carry);
+ MP_DIGIT(r, 4) = r4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ }
+
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/* 6 words */
+mp_err
+ec_GFp_add_6(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit a0 = 0, a1 = 0, a2 = 0, a3 = 0, a4 = 0, a5 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
+ mp_digit carry;
+
+ switch(MP_USED(a)) {
+ case 6:
+ a5 = MP_DIGIT(a,5);
+ case 5:
+ a4 = MP_DIGIT(a,4);
+ case 4:
+ a3 = MP_DIGIT(a,3);
+ case 3:
+ a2 = MP_DIGIT(a,2);
+ case 2:
+ a1 = MP_DIGIT(a,1);
+ case 1:
+ a0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 6:
+ r5 = MP_DIGIT(b,5);
+ case 5:
+ r4 = MP_DIGIT(b,4);
+ case 4:
+ r3 = MP_DIGIT(b,3);
+ case 3:
+ r2 = MP_DIGIT(b,2);
+ case 2:
+ r1 = MP_DIGIT(b,1);
+ case 1:
+ r0 = MP_DIGIT(b,0);
+ }
+
+ MP_ADD_CARRY(a0, r0, r0, 0, carry);
+ MP_ADD_CARRY(a1, r1, r1, carry, carry);
+ MP_ADD_CARRY(a2, r2, r2, carry, carry);
+ MP_ADD_CARRY(a3, r3, r3, carry, carry);
+ MP_ADD_CARRY(a4, r4, r4, carry, carry);
+ MP_ADD_CARRY(a5, r5, r5, carry, carry);
+
+ MP_CHECKOK(s_mp_pad(r, 6));
+ MP_DIGIT(r, 5) = r5;
+ MP_DIGIT(r, 4) = r4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 6;
+
+ /* Do quick 'subract' if we've gone over
+ * (add the 2's complement of the curve field) */
+ a5 = MP_DIGIT(&meth->irr,5);
+ if (carry || r5 > a5 ||
+ ((r5 == a5) && mp_cmp(r,&meth->irr) != MP_LT)) {
+ a4 = MP_DIGIT(&meth->irr,4);
+ a3 = MP_DIGIT(&meth->irr,3);
+ a2 = MP_DIGIT(&meth->irr,2);
+ a1 = MP_DIGIT(&meth->irr,1);
+ a0 = MP_DIGIT(&meth->irr,0);
+ MP_SUB_BORROW(r0, a0, r0, 0, carry);
+ MP_SUB_BORROW(r1, a1, r1, carry, carry);
+ MP_SUB_BORROW(r2, a2, r2, carry, carry);
+ MP_SUB_BORROW(r3, a3, r3, carry, carry);
+ MP_SUB_BORROW(r4, a4, r4, carry, carry);
+ MP_SUB_BORROW(r5, a5, r5, carry, carry);
+ MP_DIGIT(r, 5) = r5;
+ MP_DIGIT(r, 4) = r4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ }
+
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/*
+ * The following subraction functions do in-line subractions based
+ * on our curve size.
+ *
+ * ... 3 words
+ */
+mp_err
+ec_GFp_sub_3(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit b0 = 0, b1 = 0, b2 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0;
+ mp_digit borrow;
+
+ switch(MP_USED(a)) {
+ case 3:
+ r2 = MP_DIGIT(a,2);
+ case 2:
+ r1 = MP_DIGIT(a,1);
+ case 1:
+ r0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 3:
+ b2 = MP_DIGIT(b,2);
+ case 2:
+ b1 = MP_DIGIT(b,1);
+ case 1:
+ b0 = MP_DIGIT(b,0);
+ }
+
+#ifndef MPI_AMD64_ADD
+ MP_SUB_BORROW(r0, b0, r0, 0, borrow);
+ MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
+ MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
+#else
+ __asm__ (
+ "xorq %3,%3 \n\t"
+ "subq %4,%0 \n\t"
+ "sbbq %5,%1 \n\t"
+ "sbbq %6,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r" (borrow)
+ : "r" (b0), "r" (b1), "r" (b2),
+ "0" (r0), "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+
+ /* Do quick 'add' if we've gone under 0
+ * (subtract the 2's complement of the curve field) */
+ if (borrow) {
+ b2 = MP_DIGIT(&meth->irr,2);
+ b1 = MP_DIGIT(&meth->irr,1);
+ b0 = MP_DIGIT(&meth->irr,0);
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(b0, r0, r0, 0, borrow);
+ MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
+ MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
+#else
+ __asm__ (
+ "addq %3,%0 \n\t"
+ "adcq %4,%1 \n\t"
+ "adcq %5,%2 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2)
+ : "r" (b0), "r" (b1), "r" (b2),
+ "0" (r0), "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+ }
+
+#ifdef MPI_AMD64_ADD
+ /* compiler fakeout? */
+ if ((r2 == b0) && (r1 == b0) && (r0 == b0)) {
+ MP_CHECKOK(s_mp_pad(r, 4));
+ }
+#endif
+ MP_CHECKOK(s_mp_pad(r, 3));
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 3;
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/* 4 words */
+mp_err
+ec_GFp_sub_4(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0;
+ mp_digit borrow;
+
+ switch(MP_USED(a)) {
+ case 4:
+ r3 = MP_DIGIT(a,3);
+ case 3:
+ r2 = MP_DIGIT(a,2);
+ case 2:
+ r1 = MP_DIGIT(a,1);
+ case 1:
+ r0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 4:
+ b3 = MP_DIGIT(b,3);
+ case 3:
+ b2 = MP_DIGIT(b,2);
+ case 2:
+ b1 = MP_DIGIT(b,1);
+ case 1:
+ b0 = MP_DIGIT(b,0);
+ }
+
+#ifndef MPI_AMD64_ADD
+ MP_SUB_BORROW(r0, b0, r0, 0, borrow);
+ MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
+ MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
+ MP_SUB_BORROW(r3, b3, r3, borrow, borrow);
+#else
+ __asm__ (
+ "xorq %4,%4 \n\t"
+ "subq %5,%0 \n\t"
+ "sbbq %6,%1 \n\t"
+ "sbbq %7,%2 \n\t"
+ "sbbq %8,%3 \n\t"
+ "adcq $0,%4 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r" (borrow)
+ : "r" (b0), "r" (b1), "r" (b2), "r" (b3),
+ "0" (r0), "1" (r1), "2" (r2), "3" (r3)
+ : "%cc" );
+#endif
+
+ /* Do quick 'add' if we've gone under 0
+ * (subtract the 2's complement of the curve field) */
+ if (borrow) {
+ b3 = MP_DIGIT(&meth->irr,3);
+ b2 = MP_DIGIT(&meth->irr,2);
+ b1 = MP_DIGIT(&meth->irr,1);
+ b0 = MP_DIGIT(&meth->irr,0);
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(b0, r0, r0, 0, borrow);
+ MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
+ MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
+ MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
+#else
+ __asm__ (
+ "addq %4,%0 \n\t"
+ "adcq %5,%1 \n\t"
+ "adcq %6,%2 \n\t"
+ "adcq %7,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3)
+ : "r" (b0), "r" (b1), "r" (b2), "r" (b3),
+ "0" (r0), "1" (r1), "2" (r2), "3" (r3)
+ : "%cc" );
+#endif
+ }
+#ifdef MPI_AMD64_ADD
+ /* compiler fakeout? */
+ if ((r3 == b0) && (r1 == b0) && (r0 == b0)) {
+ MP_CHECKOK(s_mp_pad(r, 4));
+ }
+#endif
+ MP_CHECKOK(s_mp_pad(r, 4));
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 4;
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/* 5 words */
+mp_err
+ec_GFp_sub_5(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0;
+ mp_digit borrow;
+
+ switch(MP_USED(a)) {
+ case 5:
+ r4 = MP_DIGIT(a,4);
+ case 4:
+ r3 = MP_DIGIT(a,3);
+ case 3:
+ r2 = MP_DIGIT(a,2);
+ case 2:
+ r1 = MP_DIGIT(a,1);
+ case 1:
+ r0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 5:
+ b4 = MP_DIGIT(b,4);
+ case 4:
+ b3 = MP_DIGIT(b,3);
+ case 3:
+ b2 = MP_DIGIT(b,2);
+ case 2:
+ b1 = MP_DIGIT(b,1);
+ case 1:
+ b0 = MP_DIGIT(b,0);
+ }
+
+ MP_SUB_BORROW(r0, b0, r0, 0, borrow);
+ MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
+ MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
+ MP_SUB_BORROW(r3, b3, r3, borrow, borrow);
+ MP_SUB_BORROW(r4, b4, r4, borrow, borrow);
+
+ /* Do quick 'add' if we've gone under 0
+ * (subtract the 2's complement of the curve field) */
+ if (borrow) {
+ b4 = MP_DIGIT(&meth->irr,4);
+ b3 = MP_DIGIT(&meth->irr,3);
+ b2 = MP_DIGIT(&meth->irr,2);
+ b1 = MP_DIGIT(&meth->irr,1);
+ b0 = MP_DIGIT(&meth->irr,0);
+ MP_ADD_CARRY(b0, r0, r0, 0, borrow);
+ MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
+ MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
+ MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
+ }
+ MP_CHECKOK(s_mp_pad(r, 5));
+ MP_DIGIT(r, 4) = r4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 5;
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+/* 6 words */
+mp_err
+ec_GFp_sub_6(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0, r3 = 0, r4 = 0, r5 = 0;
+ mp_digit borrow;
+
+ switch(MP_USED(a)) {
+ case 6:
+ r5 = MP_DIGIT(a,5);
+ case 5:
+ r4 = MP_DIGIT(a,4);
+ case 4:
+ r3 = MP_DIGIT(a,3);
+ case 3:
+ r2 = MP_DIGIT(a,2);
+ case 2:
+ r1 = MP_DIGIT(a,1);
+ case 1:
+ r0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 6:
+ b5 = MP_DIGIT(b,5);
+ case 5:
+ b4 = MP_DIGIT(b,4);
+ case 4:
+ b3 = MP_DIGIT(b,3);
+ case 3:
+ b2 = MP_DIGIT(b,2);
+ case 2:
+ b1 = MP_DIGIT(b,1);
+ case 1:
+ b0 = MP_DIGIT(b,0);
+ }
+
+ MP_SUB_BORROW(r0, b0, r0, 0, borrow);
+ MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
+ MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
+ MP_SUB_BORROW(r3, b3, r3, borrow, borrow);
+ MP_SUB_BORROW(r4, b4, r4, borrow, borrow);
+ MP_SUB_BORROW(r5, b5, r5, borrow, borrow);
+
+ /* Do quick 'add' if we've gone under 0
+ * (subtract the 2's complement of the curve field) */
+ if (borrow) {
+ b5 = MP_DIGIT(&meth->irr,5);
+ b4 = MP_DIGIT(&meth->irr,4);
+ b3 = MP_DIGIT(&meth->irr,3);
+ b2 = MP_DIGIT(&meth->irr,2);
+ b1 = MP_DIGIT(&meth->irr,1);
+ b0 = MP_DIGIT(&meth->irr,0);
+ MP_ADD_CARRY(b0, r0, r0, 0, borrow);
+ MP_ADD_CARRY(b1, r1, r1, borrow, borrow);
+ MP_ADD_CARRY(b2, r2, r2, borrow, borrow);
+ MP_ADD_CARRY(b3, r3, r3, borrow, borrow);
+ MP_ADD_CARRY(b4, r4, r4, borrow, borrow);
+ }
+
+ MP_CHECKOK(s_mp_pad(r, 6));
+ MP_DIGIT(r, 5) = r5;
+ MP_DIGIT(r, 4) = r4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 6;
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+
+/* Reduces an integer to a field element. */
+mp_err
+ec_GFp_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
+{
+ return mp_mod(a, &meth->irr, r);
+}
+
+/* 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, FLAG(b)));
+ 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, FLAG(b)));
+ 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);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecl_mult.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,378 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "mpi.h"
+#include "mplogic.h"
+#include "ecl.h"
+#include "ecl-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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, FLAG(k)));
+ 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, FLAG(k1)));
+ MP_CHECKOK(mp_init(&sy, FLAG(k1)));
+
+ 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];
+ 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 */
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ MP_DIGITS(&precomp[i][j][0]) = 0;
+ MP_DIGITS(&precomp[i][j][1]) = 0;
+ }
+ }
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ MP_CHECKOK( mp_init_size(&precomp[i][j][0],
+ ECL_MAX_FIELD_SIZE_DIGITS, FLAG(k1)) );
+ MP_CHECKOK( mp_init_size(&precomp[i][j][1],
+ ECL_MAX_FIELD_SIZE_DIGITS, FLAG(k1)) );
+ }
+ }
+
+ /* 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:
+ for (i = 0; i < 4; i++) {
+ for (j = 0; j < 4; j++) {
+ mp_clear(&precomp[i][j][0]);
+ mp_clear(&precomp[i][j][1]);
+ }
+ }
+ return res;
+}
+
+/* Elliptic curve scalar-point multiplication. Computes R(x, y) = k1 * G +
+ * 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, FLAG(k1)));
+ 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, FLAG(k2)));
+ MP_CHECKOK(mp_mod(k2, &group->order, &k2t));
+ k2p = &k2t;
+ } else {
+ k2p = k2;
+ }
+ } else {
+ k2p = k2;
+ }
+
+ /* if points_mul is defined, then use it */
+ if (group->points_mul) {
+ res = group->points_mul(k1p, k2p, px, py, rx, ry, group);
+ } else {
+ res = ec_pts_mul_simul_w2(k1p, k2p, px, py, rx, ry, group);
+ }
+
+ CLEANUP:
+ mp_clear(&k1t);
+ mp_clear(&k2t);
+ return res;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,160 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _ECP_H
+#define _ECP_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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);
+
+/* Validates a point on a GFp curve. */
+mp_err ec_GFp_validate_point(const mp_int *px, const mp_int *py, 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 */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_192.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,538 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+#define ECP192_DIGITS ECL_CURVE_DIGITS(192)
+
+/* Fast modular reduction for p192 = 2^192 - 2^64 - 1. a can be r. Uses
+ * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
+ * Implementation of the NIST Elliptic Curves over Prime Fields. */
+mp_err
+ec_GFp_nistp192_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_size a_used = MP_USED(a);
+ mp_digit r3;
+#ifndef MPI_AMD64_ADD
+ mp_digit carry;
+#endif
+#ifdef ECL_THIRTY_TWO_BIT
+ mp_digit a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
+ mp_digit r0a, r0b, r1a, r1b, r2a, r2b;
+#else
+ mp_digit a5 = 0, a4 = 0, a3 = 0;
+ mp_digit r0, r1, r2;
+#endif
+
+ /* reduction not needed if a is not larger than field size */
+ if (a_used < ECP192_DIGITS) {
+ if (a == r) {
+ return MP_OKAY;
+ }
+ return mp_copy(a, r);
+ }
+
+ /* for polynomials larger than twice the field size, use regular
+ * reduction */
+ if (a_used > ECP192_DIGITS*2) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+ /* copy out upper words of a */
+
+#ifdef ECL_THIRTY_TWO_BIT
+
+ /* in all the math below,
+ * nXb is most signifiant, nXa is least significant */
+ switch (a_used) {
+ case 12:
+ a5b = MP_DIGIT(a, 11);
+ case 11:
+ a5a = MP_DIGIT(a, 10);
+ case 10:
+ a4b = MP_DIGIT(a, 9);
+ case 9:
+ a4a = MP_DIGIT(a, 8);
+ case 8:
+ a3b = MP_DIGIT(a, 7);
+ case 7:
+ a3a = MP_DIGIT(a, 6);
+ }
+
+
+ r2b= MP_DIGIT(a, 5);
+ r2a= MP_DIGIT(a, 4);
+ r1b = MP_DIGIT(a, 3);
+ r1a = MP_DIGIT(a, 2);
+ r0b = MP_DIGIT(a, 1);
+ r0a = MP_DIGIT(a, 0);
+
+ /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
+ MP_ADD_CARRY(r0a, a3a, r0a, 0, carry);
+ MP_ADD_CARRY(r0b, a3b, r0b, carry, carry);
+ MP_ADD_CARRY(r1a, a3a, r1a, carry, carry);
+ MP_ADD_CARRY(r1b, a3b, r1b, carry, carry);
+ MP_ADD_CARRY(r2a, a4a, r2a, carry, carry);
+ MP_ADD_CARRY(r2b, a4b, r2b, carry, carry);
+ r3 = carry; carry = 0;
+ MP_ADD_CARRY(r0a, a5a, r0a, 0, carry);
+ MP_ADD_CARRY(r0b, a5b, r0b, carry, carry);
+ MP_ADD_CARRY(r1a, a5a, r1a, carry, carry);
+ MP_ADD_CARRY(r1b, a5b, r1b, carry, carry);
+ MP_ADD_CARRY(r2a, a5a, r2a, carry, carry);
+ MP_ADD_CARRY(r2b, a5b, r2b, carry, carry);
+ r3 += carry;
+ MP_ADD_CARRY(r1a, a4a, r1a, 0, carry);
+ MP_ADD_CARRY(r1b, a4b, r1b, carry, carry);
+ MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
+ MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
+ r3 += carry;
+
+ /* reduce out the carry */
+ while (r3) {
+ MP_ADD_CARRY(r0a, r3, r0a, 0, carry);
+ MP_ADD_CARRY(r0b, 0, r0b, carry, carry);
+ MP_ADD_CARRY(r1a, r3, r1a, carry, carry);
+ MP_ADD_CARRY(r1b, 0, r1b, carry, carry);
+ MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
+ MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
+ r3 = carry;
+ }
+
+ /* check for final reduction */
+ /*
+ * our field is 0xffffffffffffffff, 0xfffffffffffffffe,
+ * 0xffffffffffffffff. That means we can only be over and need
+ * one more reduction
+ * if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
+ * and
+ * r1 == 0xffffffffffffffffff or
+ * r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
+ * In all cases, we subtract the field (or add the 2's
+ * complement value (1,1,0)). (r0, r1, r2)
+ */
+ if (((r2b == 0xffffffff) && (r2a == 0xffffffff)
+ && (r1b == 0xffffffff) ) &&
+ ((r1a == 0xffffffff) ||
+ (r1a == 0xfffffffe) && (r0a == 0xffffffff) &&
+ (r0b == 0xffffffff)) ) {
+ /* do a quick subtract */
+ MP_ADD_CARRY(r0a, 1, r0a, 0, carry);
+ r0b += carry;
+ r1a = r1b = r2a = r2b = 0;
+ }
+
+ /* set the lower words of r */
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r, 6));
+ }
+ MP_DIGIT(r, 5) = r2b;
+ MP_DIGIT(r, 4) = r2a;
+ MP_DIGIT(r, 3) = r1b;
+ MP_DIGIT(r, 2) = r1a;
+ MP_DIGIT(r, 1) = r0b;
+ MP_DIGIT(r, 0) = r0a;
+ MP_USED(r) = 6;
+#else
+ switch (a_used) {
+ case 6:
+ a5 = MP_DIGIT(a, 5);
+ case 5:
+ a4 = MP_DIGIT(a, 4);
+ case 4:
+ a3 = MP_DIGIT(a, 3);
+ }
+
+ r2 = MP_DIGIT(a, 2);
+ r1 = MP_DIGIT(a, 1);
+ r0 = MP_DIGIT(a, 0);
+
+ /* implement r = (a2,a1,a0)+(a5,a5,a5)+(a4,a4,0)+(0,a3,a3) */
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(r0, a3, r0, 0, carry);
+ MP_ADD_CARRY(r1, a3, r1, carry, carry);
+ MP_ADD_CARRY(r2, a4, r2, carry, carry);
+ r3 = carry;
+ MP_ADD_CARRY(r0, a5, r0, 0, carry);
+ MP_ADD_CARRY(r1, a5, r1, carry, carry);
+ MP_ADD_CARRY(r2, a5, r2, carry, carry);
+ r3 += carry;
+ MP_ADD_CARRY(r1, a4, r1, 0, carry);
+ MP_ADD_CARRY(r2, 0, r2, carry, carry);
+ r3 += carry;
+
+#else
+ r2 = MP_DIGIT(a, 2);
+ r1 = MP_DIGIT(a, 1);
+ r0 = MP_DIGIT(a, 0);
+
+ /* set the lower words of r */
+ __asm__ (
+ "xorq %3,%3 \n\t"
+ "addq %4,%0 \n\t"
+ "adcq %4,%1 \n\t"
+ "adcq %5,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ "addq %6,%0 \n\t"
+ "adcq %6,%1 \n\t"
+ "adcq %6,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ "addq %5,%1 \n\t"
+ "adcq $0,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3),
+ "=r"(a4), "=r"(a5)
+ : "0" (r0), "1" (r1), "2" (r2), "3" (r3),
+ "4" (a3), "5" (a4), "6"(a5)
+ : "%cc" );
+#endif
+
+ /* reduce out the carry */
+ while (r3) {
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(r0, r3, r0, 0, carry);
+ MP_ADD_CARRY(r1, r3, r1, carry, carry);
+ MP_ADD_CARRY(r2, 0, r2, carry, carry);
+ r3 = carry;
+#else
+ a3=r3;
+ __asm__ (
+ "xorq %3,%3 \n\t"
+ "addq %4,%0 \n\t"
+ "adcq %4,%1 \n\t"
+ "adcq $0,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(r3), "=r"(a3)
+ : "0" (r0), "1" (r1), "2" (r2), "3" (r3), "4"(a3)
+ : "%cc" );
+#endif
+ }
+
+ /* check for final reduction */
+ /*
+ * our field is 0xffffffffffffffff, 0xfffffffffffffffe,
+ * 0xffffffffffffffff. That means we can only be over and need
+ * one more reduction
+ * if r2 == 0xffffffffffffffffff (same as r2+1 == 0)
+ * and
+ * r1 == 0xffffffffffffffffff or
+ * r1 == 0xfffffffffffffffffe and r0 = 0xfffffffffffffffff
+ * In all cases, we subtract the field (or add the 2's
+ * complement value (1,1,0)). (r0, r1, r2)
+ */
+ if (r3 || ((r2 == MP_DIGIT_MAX) &&
+ ((r1 == MP_DIGIT_MAX) ||
+ ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
+ /* do a quick subtract */
+ r0++;
+ r1 = r2 = 0;
+ }
+ /* set the lower words of r */
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r, 3));
+ }
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_USED(r) = 3;
+#endif
+ }
+
+ CLEANUP:
+ return res;
+}
+
+#ifndef ECL_THIRTY_TWO_BIT
+/* Compute the sum of 192 bit curves. Do the work in-line since the
+ * number of words are so small, we don't want to overhead of mp function
+ * calls. Uses optimized modular reduction for p192.
+ */
+mp_err
+ec_GFp_nistp192_add(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit a0 = 0, a1 = 0, a2 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0;
+ mp_digit carry;
+
+ switch(MP_USED(a)) {
+ case 3:
+ a2 = MP_DIGIT(a,2);
+ case 2:
+ a1 = MP_DIGIT(a,1);
+ case 1:
+ a0 = MP_DIGIT(a,0);
+ }
+ switch(MP_USED(b)) {
+ case 3:
+ r2 = MP_DIGIT(b,2);
+ case 2:
+ r1 = MP_DIGIT(b,1);
+ case 1:
+ r0 = MP_DIGIT(b,0);
+ }
+
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(a0, r0, r0, 0, carry);
+ MP_ADD_CARRY(a1, r1, r1, carry, carry);
+ MP_ADD_CARRY(a2, r2, r2, carry, carry);
+#else
+ __asm__ (
+ "xorq %3,%3 \n\t"
+ "addq %4,%0 \n\t"
+ "adcq %5,%1 \n\t"
+ "adcq %6,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(carry)
+ : "r" (a0), "r" (a1), "r" (a2), "0" (r0),
+ "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+
+ /* Do quick 'subract' if we've gone over
+ * (add the 2's complement of the curve field) */
+ if (carry || ((r2 == MP_DIGIT_MAX) &&
+ ((r1 == MP_DIGIT_MAX) ||
+ ((r1 == (MP_DIGIT_MAX-1)) && (r0 == MP_DIGIT_MAX))))) {
+#ifndef MPI_AMD64_ADD
+ MP_ADD_CARRY(r0, 1, r0, 0, carry);
+ MP_ADD_CARRY(r1, 1, r1, carry, carry);
+ MP_ADD_CARRY(r2, 0, r2, carry, carry);
+#else
+ __asm__ (
+ "addq $1,%0 \n\t"
+ "adcq $1,%1 \n\t"
+ "adcq $0,%2 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2)
+ : "0" (r0), "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+ }
+
+
+ MP_CHECKOK(s_mp_pad(r, 3));
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 3;
+ s_mp_clamp(r);
+
+
+ CLEANUP:
+ return res;
+}
+
+/* Compute the diff of 192 bit curves. Do the work in-line since the
+ * number of words are so small, we don't want to overhead of mp function
+ * calls. Uses optimized modular reduction for p192.
+ */
+mp_err
+ec_GFp_nistp192_sub(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_digit b0 = 0, b1 = 0, b2 = 0;
+ mp_digit r0 = 0, r1 = 0, r2 = 0;
+ mp_digit borrow;
+
+ switch(MP_USED(a)) {
+ case 3:
+ r2 = MP_DIGIT(a,2);
+ case 2:
+ r1 = MP_DIGIT(a,1);
+ case 1:
+ r0 = MP_DIGIT(a,0);
+ }
+
+ switch(MP_USED(b)) {
+ case 3:
+ b2 = MP_DIGIT(b,2);
+ case 2:
+ b1 = MP_DIGIT(b,1);
+ case 1:
+ b0 = MP_DIGIT(b,0);
+ }
+
+#ifndef MPI_AMD64_ADD
+ MP_SUB_BORROW(r0, b0, r0, 0, borrow);
+ MP_SUB_BORROW(r1, b1, r1, borrow, borrow);
+ MP_SUB_BORROW(r2, b2, r2, borrow, borrow);
+#else
+ __asm__ (
+ "xorq %3,%3 \n\t"
+ "subq %4,%0 \n\t"
+ "sbbq %5,%1 \n\t"
+ "sbbq %6,%2 \n\t"
+ "adcq $0,%3 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2), "=r"(borrow)
+ : "r" (b0), "r" (b1), "r" (b2), "0" (r0),
+ "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+
+ /* Do quick 'add' if we've gone under 0
+ * (subtract the 2's complement of the curve field) */
+ if (borrow) {
+#ifndef MPI_AMD64_ADD
+ MP_SUB_BORROW(r0, 1, r0, 0, borrow);
+ MP_SUB_BORROW(r1, 1, r1, borrow, borrow);
+ MP_SUB_BORROW(r2, 0, r2, borrow, borrow);
+#else
+ __asm__ (
+ "subq $1,%0 \n\t"
+ "sbbq $1,%1 \n\t"
+ "sbbq $0,%2 \n\t"
+ : "=r"(r0), "=r"(r1), "=r"(r2)
+ : "0" (r0), "1" (r1), "2" (r2)
+ : "%cc" );
+#endif
+ }
+
+ MP_CHECKOK(s_mp_pad(r, 3));
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 3;
+ s_mp_clamp(r);
+
+ CLEANUP:
+ return res;
+}
+
+#endif
+
+/* Compute the square of polynomial a, reduce modulo p192. Store the
+ * result in r. r could be a. Uses optimized modular reduction for p192.
+ */
+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;
+}
+
+/* Divides two field elements. If a is NULL, then returns the inverse of
+ * b. */
+mp_err
+ec_GFp_nistp192_div(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_int t;
+
+ /* If a is NULL, then return the inverse of b, otherwise return a/b. */
+ if (a == NULL) {
+ return mp_invmod(b, &meth->irr, r);
+ } else {
+ /* MPI doesn't support divmod, so we implement it using invmod and
+ * mulmod. */
+ MP_CHECKOK(mp_init(&t, FLAG(b)));
+ MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
+ MP_CHECKOK(mp_mul(a, &t, r));
+ MP_CHECKOK(ec_GFp_nistp192_mod(r, r, meth));
+ CLEANUP:
+ mp_clear(&t);
+ return res;
+ }
+}
+
+/* Wire in fast field arithmetic and precomputation of base point for
+ * named curves. */
+mp_err
+ec_group_set_gfp192(ECGroup *group, ECCurveName name)
+{
+ if (name == ECCurve_NIST_P192) {
+ group->meth->field_mod = &ec_GFp_nistp192_mod;
+ group->meth->field_mul = &ec_GFp_nistp192_mul;
+ group->meth->field_sqr = &ec_GFp_nistp192_sqr;
+ group->meth->field_div = &ec_GFp_nistp192_div;
+#ifndef ECL_THIRTY_TWO_BIT
+ group->meth->field_add = &ec_GFp_nistp192_add;
+ group->meth->field_sub = &ec_GFp_nistp192_sub;
+#endif
+ }
+ return MP_OKAY;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_224.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,394 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+#define ECP224_DIGITS ECL_CURVE_DIGITS(224)
+
+/* Fast modular reduction for p224 = 2^224 - 2^96 + 1. a can be r. Uses
+ * algorithm 7 from Brown, Hankerson, Lopez, Menezes. Software
+ * Implementation of the NIST Elliptic Curves over Prime Fields. */
+mp_err
+ec_GFp_nistp224_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_size a_used = MP_USED(a);
+
+ int r3b;
+ mp_digit carry;
+#ifdef ECL_THIRTY_TWO_BIT
+ mp_digit a6a = 0, a6b = 0,
+ a5a = 0, a5b = 0, a4a = 0, a4b = 0, a3a = 0, a3b = 0;
+ mp_digit r0a, r0b, r1a, r1b, r2a, r2b, r3a;
+#else
+ mp_digit a6 = 0, a5 = 0, a4 = 0, a3b = 0, a5a = 0;
+ mp_digit a6b = 0, a6a_a5b = 0, a5b = 0, a5a_a4b = 0, a4a_a3b = 0;
+ mp_digit r0, r1, r2, r3;
+#endif
+
+ /* reduction not needed if a is not larger than field size */
+ if (a_used < ECP224_DIGITS) {
+ if (a == r) return MP_OKAY;
+ return mp_copy(a, r);
+ }
+ /* for polynomials larger than twice the field size, use regular
+ * reduction */
+ if (a_used > ECL_CURVE_DIGITS(224*2)) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+#ifdef ECL_THIRTY_TWO_BIT
+ /* copy out upper words of a */
+ switch (a_used) {
+ case 14:
+ a6b = MP_DIGIT(a, 13);
+ case 13:
+ a6a = MP_DIGIT(a, 12);
+ case 12:
+ a5b = MP_DIGIT(a, 11);
+ case 11:
+ a5a = MP_DIGIT(a, 10);
+ case 10:
+ a4b = MP_DIGIT(a, 9);
+ case 9:
+ a4a = MP_DIGIT(a, 8);
+ case 8:
+ a3b = MP_DIGIT(a, 7);
+ }
+ r3a = MP_DIGIT(a, 6);
+ r2b= MP_DIGIT(a, 5);
+ r2a= MP_DIGIT(a, 4);
+ r1b = MP_DIGIT(a, 3);
+ r1a = MP_DIGIT(a, 2);
+ r0b = MP_DIGIT(a, 1);
+ r0a = MP_DIGIT(a, 0);
+
+
+ /* implement r = (a3a,a2,a1,a0)
+ +(a5a, a4,a3b, 0)
+ +( 0, a6,a5b, 0)
+ -( 0 0, 0|a6b, a6a|a5b )
+ -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
+ MP_ADD_CARRY (r1b, a3b, r1b, 0, carry);
+ MP_ADD_CARRY (r2a, a4a, r2a, carry, carry);
+ MP_ADD_CARRY (r2b, a4b, r2b, carry, carry);
+ MP_ADD_CARRY (r3a, a5a, r3a, carry, carry);
+ r3b = carry;
+ MP_ADD_CARRY (r1b, a5b, r1b, 0, carry);
+ MP_ADD_CARRY (r2a, a6a, r2a, carry, carry);
+ MP_ADD_CARRY (r2b, a6b, r2b, carry, carry);
+ MP_ADD_CARRY (r3a, 0, r3a, carry, carry);
+ r3b += carry;
+ MP_SUB_BORROW(r0a, a3b, r0a, 0, carry);
+ MP_SUB_BORROW(r0b, a4a, r0b, carry, carry);
+ MP_SUB_BORROW(r1a, a4b, r1a, carry, carry);
+ MP_SUB_BORROW(r1b, a5a, r1b, carry, carry);
+ MP_SUB_BORROW(r2a, a5b, r2a, carry, carry);
+ MP_SUB_BORROW(r2b, a6a, r2b, carry, carry);
+ MP_SUB_BORROW(r3a, a6b, r3a, carry, carry);
+ r3b -= carry;
+ MP_SUB_BORROW(r0a, a5b, r0a, 0, carry);
+ MP_SUB_BORROW(r0b, a6a, r0b, carry, carry);
+ MP_SUB_BORROW(r1a, a6b, r1a, carry, carry);
+ if (carry) {
+ MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
+ MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
+ MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
+ MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
+ r3b -= carry;
+ }
+
+ while (r3b > 0) {
+ int tmp;
+ MP_ADD_CARRY(r1b, r3b, r1b, 0, carry);
+ if (carry) {
+ MP_ADD_CARRY(r2a, 0, r2a, carry, carry);
+ MP_ADD_CARRY(r2b, 0, r2b, carry, carry);
+ MP_ADD_CARRY(r3a, 0, r3a, carry, carry);
+ }
+ tmp = carry;
+ MP_SUB_BORROW(r0a, r3b, r0a, 0, carry);
+ if (carry) {
+ MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
+ MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
+ MP_SUB_BORROW(r1b, 0, r1b, carry, carry);
+ MP_SUB_BORROW(r2a, 0, r2a, carry, carry);
+ MP_SUB_BORROW(r2b, 0, r2b, carry, carry);
+ MP_SUB_BORROW(r3a, 0, r3a, carry, carry);
+ tmp -= carry;
+ }
+ r3b = tmp;
+ }
+
+ while (r3b < 0) {
+ mp_digit maxInt = MP_DIGIT_MAX;
+ MP_ADD_CARRY (r0a, 1, r0a, 0, carry);
+ MP_ADD_CARRY (r0b, 0, r0b, carry, carry);
+ MP_ADD_CARRY (r1a, 0, r1a, carry, carry);
+ MP_ADD_CARRY (r1b, maxInt, r1b, carry, carry);
+ MP_ADD_CARRY (r2a, maxInt, r2a, carry, carry);
+ MP_ADD_CARRY (r2b, maxInt, r2b, carry, carry);
+ MP_ADD_CARRY (r3a, maxInt, r3a, carry, carry);
+ r3b += carry;
+ }
+ /* check for final reduction */
+ /* now the only way we are over is if the top 4 words are all ones */
+ if ((r3a == MP_DIGIT_MAX) && (r2b == MP_DIGIT_MAX)
+ && (r2a == MP_DIGIT_MAX) && (r1b == MP_DIGIT_MAX) &&
+ ((r1a != 0) || (r0b != 0) || (r0a != 0)) ) {
+ /* one last subraction */
+ MP_SUB_BORROW(r0a, 1, r0a, 0, carry);
+ MP_SUB_BORROW(r0b, 0, r0b, carry, carry);
+ MP_SUB_BORROW(r1a, 0, r1a, carry, carry);
+ r1b = r2a = r2b = r3a = 0;
+ }
+
+
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r, 7));
+ }
+ /* set the lower words of r */
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 7;
+ MP_DIGIT(r, 6) = r3a;
+ MP_DIGIT(r, 5) = r2b;
+ MP_DIGIT(r, 4) = r2a;
+ MP_DIGIT(r, 3) = r1b;
+ MP_DIGIT(r, 2) = r1a;
+ MP_DIGIT(r, 1) = r0b;
+ MP_DIGIT(r, 0) = r0a;
+#else
+ /* copy out upper words of a */
+ switch (a_used) {
+ case 7:
+ a6 = MP_DIGIT(a, 6);
+ a6b = a6 >> 32;
+ a6a_a5b = a6 << 32;
+ case 6:
+ a5 = MP_DIGIT(a, 5);
+ a5b = a5 >> 32;
+ a6a_a5b |= a5b;
+ a5b = a5b << 32;
+ a5a_a4b = a5 << 32;
+ a5a = a5 & 0xffffffff;
+ case 5:
+ a4 = MP_DIGIT(a, 4);
+ a5a_a4b |= a4 >> 32;
+ a4a_a3b = a4 << 32;
+ case 4:
+ a3b = MP_DIGIT(a, 3) >> 32;
+ a4a_a3b |= a3b;
+ a3b = a3b << 32;
+ }
+
+ r3 = MP_DIGIT(a, 3) & 0xffffffff;
+ r2 = MP_DIGIT(a, 2);
+ r1 = MP_DIGIT(a, 1);
+ r0 = MP_DIGIT(a, 0);
+
+ /* implement r = (a3a,a2,a1,a0)
+ +(a5a, a4,a3b, 0)
+ +( 0, a6,a5b, 0)
+ -( 0 0, 0|a6b, a6a|a5b )
+ -( a6b, a6a|a5b, a5a|a4b, a4a|a3b ) */
+ MP_ADD_CARRY (r1, a3b, r1, 0, carry);
+ MP_ADD_CARRY (r2, a4 , r2, carry, carry);
+ MP_ADD_CARRY (r3, a5a, r3, carry, carry);
+ MP_ADD_CARRY (r1, a5b, r1, 0, carry);
+ MP_ADD_CARRY (r2, a6 , r2, carry, carry);
+ MP_ADD_CARRY (r3, 0, r3, carry, carry);
+
+ MP_SUB_BORROW(r0, a4a_a3b, r0, 0, carry);
+ MP_SUB_BORROW(r1, a5a_a4b, r1, carry, carry);
+ MP_SUB_BORROW(r2, a6a_a5b, r2, carry, carry);
+ MP_SUB_BORROW(r3, a6b , r3, carry, carry);
+ MP_SUB_BORROW(r0, a6a_a5b, r0, 0, carry);
+ MP_SUB_BORROW(r1, a6b , r1, carry, carry);
+ if (carry) {
+ MP_SUB_BORROW(r2, 0, r2, carry, carry);
+ MP_SUB_BORROW(r3, 0, r3, carry, carry);
+ }
+
+
+ /* if the value is negative, r3 has a 2's complement
+ * high value */
+ r3b = (int)(r3 >>32);
+ while (r3b > 0) {
+ r3 &= 0xffffffff;
+ MP_ADD_CARRY(r1,((mp_digit)r3b) << 32, r1, 0, carry);
+ if (carry) {
+ MP_ADD_CARRY(r2, 0, r2, carry, carry);
+ MP_ADD_CARRY(r3, 0, r3, carry, carry);
+ }
+ MP_SUB_BORROW(r0, r3b, r0, 0, carry);
+ if (carry) {
+ MP_SUB_BORROW(r1, 0, r1, carry, carry);
+ MP_SUB_BORROW(r2, 0, r2, carry, carry);
+ MP_SUB_BORROW(r3, 0, r3, carry, carry);
+ }
+ r3b = (int)(r3 >>32);
+ }
+
+ while (r3b < 0) {
+ MP_ADD_CARRY (r0, 1, r0, 0, carry);
+ MP_ADD_CARRY (r1, MP_DIGIT_MAX <<32, r1, carry, carry);
+ MP_ADD_CARRY (r2, MP_DIGIT_MAX, r2, carry, carry);
+ MP_ADD_CARRY (r3, MP_DIGIT_MAX >> 32, r3, carry, carry);
+ r3b = (int)(r3 >>32);
+ }
+ /* check for final reduction */
+ /* now the only way we are over is if the top 4 words are all ones */
+ if ((r3 == (MP_DIGIT_MAX >> 32)) && (r2 == MP_DIGIT_MAX)
+ && ((r1 & MP_DIGIT_MAX << 32)== MP_DIGIT_MAX << 32) &&
+ ((r1 != MP_DIGIT_MAX << 32 ) || (r0 != 0)) ) {
+ /* one last subraction */
+ MP_SUB_BORROW(r0, 1, r0, 0, carry);
+ MP_SUB_BORROW(r1, 0, r1, carry, carry);
+ r2 = r3 = 0;
+ }
+
+
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r, 4));
+ }
+ /* set the lower words of r */
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 4;
+ MP_DIGIT(r, 3) = r3;
+ MP_DIGIT(r, 2) = r2;
+ MP_DIGIT(r, 1) = r1;
+ MP_DIGIT(r, 0) = r0;
+#endif
+ }
+
+ 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;
+}
+
+/* Divides two field elements. If a is NULL, then returns the inverse of
+ * b. */
+mp_err
+ec_GFp_nistp224_div(const mp_int *a, const mp_int *b, mp_int *r,
+ const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_int t;
+
+ /* If a is NULL, then return the inverse of b, otherwise return a/b. */
+ if (a == NULL) {
+ return mp_invmod(b, &meth->irr, r);
+ } else {
+ /* MPI doesn't support divmod, so we implement it using invmod and
+ * mulmod. */
+ MP_CHECKOK(mp_init(&t, FLAG(b)));
+ MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
+ MP_CHECKOK(mp_mul(a, &t, r));
+ MP_CHECKOK(ec_GFp_nistp224_mod(r, r, meth));
+ CLEANUP:
+ mp_clear(&t);
+ return res;
+ }
+}
+
+/* Wire in fast field arithmetic and precomputation of base point for
+ * named curves. */
+mp_err
+ec_group_set_gfp224(ECGroup *group, ECCurveName name)
+{
+ if (name == ECCurve_NIST_P224) {
+ group->meth->field_mod = &ec_GFp_nistp224_mod;
+ group->meth->field_mul = &ec_GFp_nistp224_mul;
+ group->meth->field_sqr = &ec_GFp_nistp224_sqr;
+ group->meth->field_div = &ec_GFp_nistp224_div;
+ }
+ return MP_OKAY;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_256.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,451 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>
+ *
+ * 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* Fast modular reduction for p256 = 2^256 - 2^224 + 2^192+ 2^96 - 1. a can be r.
+ * Uses algorithm 2.29 from Hankerson, Menezes, Vanstone. Guide to
+ * Elliptic Curve Cryptography. */
+mp_err
+ec_GFp_nistp256_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ mp_size a_used = MP_USED(a);
+ int a_bits = mpl_significant_bits(a);
+ mp_digit carry;
+
+#ifdef ECL_THIRTY_TWO_BIT
+ mp_digit a8=0, a9=0, a10=0, a11=0, a12=0, a13=0, a14=0, a15=0;
+ mp_digit r0, r1, r2, r3, r4, r5, r6, r7;
+ int r8; /* must be a signed value ! */
+#else
+ mp_digit a4=0, a5=0, a6=0, a7=0;
+ mp_digit a4h, a4l, a5h, a5l, a6h, a6l, a7h, a7l;
+ mp_digit r0, r1, r2, r3;
+ int r4; /* must be a signed value ! */
+#endif
+ /* for polynomials larger than twice the field size
+ * use regular reduction */
+ if (a_bits < 256) {
+ if (a == r) return MP_OKAY;
+ return mp_copy(a,r);
+ }
+ if (a_bits > 512) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+
+#ifdef ECL_THIRTY_TWO_BIT
+ switch (a_used) {
+ case 16:
+ a15 = MP_DIGIT(a,15);
+ case 15:
+ a14 = MP_DIGIT(a,14);
+ case 14:
+ a13 = MP_DIGIT(a,13);
+ case 13:
+ a12 = MP_DIGIT(a,12);
+ case 12:
+ a11 = MP_DIGIT(a,11);
+ case 11:
+ a10 = MP_DIGIT(a,10);
+ case 10:
+ a9 = MP_DIGIT(a,9);
+ case 9:
+ a8 = MP_DIGIT(a,8);
+ }
+
+ r0 = MP_DIGIT(a,0);
+ r1 = MP_DIGIT(a,1);
+ r2 = MP_DIGIT(a,2);
+ r3 = MP_DIGIT(a,3);
+ r4 = MP_DIGIT(a,4);
+ r5 = MP_DIGIT(a,5);
+ r6 = MP_DIGIT(a,6);
+ r7 = MP_DIGIT(a,7);
+
+ /* sum 1 */
+ MP_ADD_CARRY(r3, a11, r3, 0, carry);
+ MP_ADD_CARRY(r4, a12, r4, carry, carry);
+ MP_ADD_CARRY(r5, a13, r5, carry, carry);
+ MP_ADD_CARRY(r6, a14, r6, carry, carry);
+ MP_ADD_CARRY(r7, a15, r7, carry, carry);
+ r8 = carry;
+ MP_ADD_CARRY(r3, a11, r3, 0, carry);
+ MP_ADD_CARRY(r4, a12, r4, carry, carry);
+ MP_ADD_CARRY(r5, a13, r5, carry, carry);
+ MP_ADD_CARRY(r6, a14, r6, carry, carry);
+ MP_ADD_CARRY(r7, a15, r7, carry, carry);
+ r8 += carry;
+ /* sum 2 */
+ MP_ADD_CARRY(r3, a12, r3, 0, carry);
+ MP_ADD_CARRY(r4, a13, r4, carry, carry);
+ MP_ADD_CARRY(r5, a14, r5, carry, carry);
+ MP_ADD_CARRY(r6, a15, r6, carry, carry);
+ MP_ADD_CARRY(r7, 0, r7, carry, carry);
+ r8 += carry;
+ /* combine last bottom of sum 3 with second sum 2 */
+ MP_ADD_CARRY(r0, a8, r0, 0, carry);
+ MP_ADD_CARRY(r1, a9, r1, carry, carry);
+ MP_ADD_CARRY(r2, a10, r2, carry, carry);
+ MP_ADD_CARRY(r3, a12, r3, carry, carry);
+ MP_ADD_CARRY(r4, a13, r4, carry, carry);
+ MP_ADD_CARRY(r5, a14, r5, carry, carry);
+ MP_ADD_CARRY(r6, a15, r6, carry, carry);
+ MP_ADD_CARRY(r7, a15, r7, carry, carry); /* from sum 3 */
+ r8 += carry;
+ /* sum 3 (rest of it)*/
+ MP_ADD_CARRY(r6, a14, r6, 0, carry);
+ MP_ADD_CARRY(r7, 0, r7, carry, carry);
+ r8 += carry;
+ /* sum 4 (rest of it)*/
+ MP_ADD_CARRY(r0, a9, r0, 0, carry);
+ MP_ADD_CARRY(r1, a10, r1, carry, carry);
+ MP_ADD_CARRY(r2, a11, r2, carry, carry);
+ MP_ADD_CARRY(r3, a13, r3, carry, carry);
+ MP_ADD_CARRY(r4, a14, r4, carry, carry);
+ MP_ADD_CARRY(r5, a15, r5, carry, carry);
+ MP_ADD_CARRY(r6, a13, r6, carry, carry);
+ MP_ADD_CARRY(r7, a8, r7, carry, carry);
+ r8 += carry;
+ /* diff 5 */
+ MP_SUB_BORROW(r0, a11, r0, 0, carry);
+ MP_SUB_BORROW(r1, a12, r1, carry, carry);
+ MP_SUB_BORROW(r2, a13, r2, carry, carry);
+ MP_SUB_BORROW(r3, 0, r3, carry, carry);
+ MP_SUB_BORROW(r4, 0, r4, carry, carry);
+ MP_SUB_BORROW(r5, 0, r5, carry, carry);
+ MP_SUB_BORROW(r6, a8, r6, carry, carry);
+ MP_SUB_BORROW(r7, a10, r7, carry, carry);
+ r8 -= carry;
+ /* diff 6 */
+ MP_SUB_BORROW(r0, a12, r0, 0, carry);
+ MP_SUB_BORROW(r1, a13, r1, carry, carry);
+ MP_SUB_BORROW(r2, a14, r2, carry, carry);
+ MP_SUB_BORROW(r3, a15, r3, carry, carry);
+ MP_SUB_BORROW(r4, 0, r4, carry, carry);
+ MP_SUB_BORROW(r5, 0, r5, carry, carry);
+ MP_SUB_BORROW(r6, a9, r6, carry, carry);
+ MP_SUB_BORROW(r7, a11, r7, carry, carry);
+ r8 -= carry;
+ /* diff 7 */
+ MP_SUB_BORROW(r0, a13, r0, 0, carry);
+ MP_SUB_BORROW(r1, a14, r1, carry, carry);
+ MP_SUB_BORROW(r2, a15, r2, carry, carry);
+ MP_SUB_BORROW(r3, a8, r3, carry, carry);
+ MP_SUB_BORROW(r4, a9, r4, carry, carry);
+ MP_SUB_BORROW(r5, a10, r5, carry, carry);
+ MP_SUB_BORROW(r6, 0, r6, carry, carry);
+ MP_SUB_BORROW(r7, a12, r7, carry, carry);
+ r8 -= carry;
+ /* diff 8 */
+ MP_SUB_BORROW(r0, a14, r0, 0, carry);
+ MP_SUB_BORROW(r1, a15, r1, carry, carry);
+ MP_SUB_BORROW(r2, 0, r2, carry, carry);
+ MP_SUB_BORROW(r3, a9, r3, carry, carry);
+ MP_SUB_BORROW(r4, a10, r4, carry, carry);
+ MP_SUB_BORROW(r5, a11, r5, carry, carry);
+ MP_SUB_BORROW(r6, 0, r6, carry, carry);
+ MP_SUB_BORROW(r7, a13, r7, carry, carry);
+ r8 -= carry;
+
+ /* reduce the overflows */
+ while (r8 > 0) {
+ mp_digit r8_d = r8;
+ MP_ADD_CARRY(r0, r8_d, r0, 0, carry);
+ MP_ADD_CARRY(r1, 0, r1, carry, carry);
+ MP_ADD_CARRY(r2, 0, r2, carry, carry);
+ MP_ADD_CARRY(r3, -r8_d, r3, carry, carry);
+ MP_ADD_CARRY(r4, MP_DIGIT_MAX, r4, carry, carry);
+ MP_ADD_CARRY(r5, MP_DIGIT_MAX, r5, carry, carry);
+ MP_ADD_CARRY(r6, -(r8_d+1), r6, carry, carry);
+ MP_ADD_CARRY(r7, (r8_d-1), r7, carry, carry);
+ r8 = carry;
+ }
+
+ /* reduce the underflows */
+ while (r8 < 0) {
+ mp_digit r8_d = -r8;
+ MP_SUB_BORROW(r0, r8_d, r0, 0, carry);
+ MP_SUB_BORROW(r1, 0, r1, carry, carry);
+ MP_SUB_BORROW(r2, 0, r2, carry, carry);
+ MP_SUB_BORROW(r3, -r8_d, r3, carry, carry);
+ MP_SUB_BORROW(r4, MP_DIGIT_MAX, r4, carry, carry);
+ MP_SUB_BORROW(r5, MP_DIGIT_MAX, r5, carry, carry);
+ MP_SUB_BORROW(r6, -(r8_d+1), r6, carry, carry);
+ MP_SUB_BORROW(r7, (r8_d-1), r7, carry, carry);
+ r8 = -carry;
+ }
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r,8));
+ }
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 8;
+
+ MP_DIGIT(r,7) = r7;
+ MP_DIGIT(r,6) = r6;
+ MP_DIGIT(r,5) = r5;
+ MP_DIGIT(r,4) = r4;
+ MP_DIGIT(r,3) = r3;
+ MP_DIGIT(r,2) = r2;
+ MP_DIGIT(r,1) = r1;
+ MP_DIGIT(r,0) = r0;
+
+ /* final reduction if necessary */
+ if ((r7 == MP_DIGIT_MAX) &&
+ ((r6 > 1) || ((r6 == 1) &&
+ (r5 || r4 || r3 ||
+ ((r2 == MP_DIGIT_MAX) && (r1 == MP_DIGIT_MAX)
+ && (r0 == MP_DIGIT_MAX)))))) {
+ MP_CHECKOK(mp_sub(r, &meth->irr, r));
+ }
+#ifdef notdef
+
+
+ /* smooth the negatives */
+ while (MP_SIGN(r) != MP_ZPOS) {
+ MP_CHECKOK(mp_add(r, &meth->irr, r));
+ }
+ while (MP_USED(r) > 8) {
+ MP_CHECKOK(mp_sub(r, &meth->irr, r));
+ }
+
+ /* final reduction if necessary */
+ if (MP_DIGIT(r,7) >= MP_DIGIT(&meth->irr,7)) {
+ if (mp_cmp(r,&meth->irr) != MP_LT) {
+ MP_CHECKOK(mp_sub(r, &meth->irr, r));
+ }
+ }
+#endif
+ s_mp_clamp(r);
+#else
+ switch (a_used) {
+ case 8:
+ a7 = MP_DIGIT(a,7);
+ case 7:
+ a6 = MP_DIGIT(a,6);
+ case 6:
+ a5 = MP_DIGIT(a,5);
+ case 5:
+ a4 = MP_DIGIT(a,4);
+ }
+ a7l = a7 << 32;
+ a7h = a7 >> 32;
+ a6l = a6 << 32;
+ a6h = a6 >> 32;
+ a5l = a5 << 32;
+ a5h = a5 >> 32;
+ a4l = a4 << 32;
+ a4h = a4 >> 32;
+ r3 = MP_DIGIT(a,3);
+ r2 = MP_DIGIT(a,2);
+ r1 = MP_DIGIT(a,1);
+ r0 = MP_DIGIT(a,0);
+
+ /* sum 1 */
+ MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
+ MP_ADD_CARRY(r2, a6, r2, carry, carry);
+ MP_ADD_CARRY(r3, a7, r3, carry, carry);
+ r4 = carry;
+ MP_ADD_CARRY(r1, a5h << 32, r1, 0, carry);
+ MP_ADD_CARRY(r2, a6, r2, carry, carry);
+ MP_ADD_CARRY(r3, a7, r3, carry, carry);
+ r4 += carry;
+ /* sum 2 */
+ MP_ADD_CARRY(r1, a6l, r1, 0, carry);
+ MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
+ MP_ADD_CARRY(r3, a7h, r3, carry, carry);
+ r4 += carry;
+ MP_ADD_CARRY(r1, a6l, r1, 0, carry);
+ MP_ADD_CARRY(r2, a6h | a7l, r2, carry, carry);
+ MP_ADD_CARRY(r3, a7h, r3, carry, carry);
+ r4 += carry;
+
+ /* sum 3 */
+ MP_ADD_CARRY(r0, a4, r0, 0, carry);
+ MP_ADD_CARRY(r1, a5l >> 32, r1, carry, carry);
+ MP_ADD_CARRY(r2, 0, r2, carry, carry);
+ MP_ADD_CARRY(r3, a7, r3, carry, carry);
+ r4 += carry;
+ /* sum 4 */
+ MP_ADD_CARRY(r0, a4h | a5l, r0, 0, carry);
+ MP_ADD_CARRY(r1, a5h|(a6h<<32), r1, carry, carry);
+ MP_ADD_CARRY(r2, a7, r2, carry, carry);
+ MP_ADD_CARRY(r3, a6h | a4l, r3, carry, carry);
+ r4 += carry;
+ /* diff 5 */
+ MP_SUB_BORROW(r0, a5h | a6l, r0, 0, carry);
+ MP_SUB_BORROW(r1, a6h, r1, carry, carry);
+ MP_SUB_BORROW(r2, 0, r2, carry, carry);
+ MP_SUB_BORROW(r3, (a4l>>32)|a5l,r3, carry, carry);
+ r4 -= carry;
+ /* diff 6 */
+ MP_SUB_BORROW(r0, a6, r0, 0, carry);
+ MP_SUB_BORROW(r1, a7, r1, carry, carry);
+ MP_SUB_BORROW(r2, 0, r2, carry, carry);
+ MP_SUB_BORROW(r3, a4h|(a5h<<32),r3, carry, carry);
+ r4 -= carry;
+ /* diff 7 */
+ MP_SUB_BORROW(r0, a6h|a7l, r0, 0, carry);
+ MP_SUB_BORROW(r1, a7h|a4l, r1, carry, carry);
+ MP_SUB_BORROW(r2, a4h|a5l, r2, carry, carry);
+ MP_SUB_BORROW(r3, a6l, r3, carry, carry);
+ r4 -= carry;
+ /* diff 8 */
+ MP_SUB_BORROW(r0, a7, r0, 0, carry);
+ MP_SUB_BORROW(r1, a4h<<32, r1, carry, carry);
+ MP_SUB_BORROW(r2, a5, r2, carry, carry);
+ MP_SUB_BORROW(r3, a6h<<32, r3, carry, carry);
+ r4 -= carry;
+
+ /* reduce the overflows */
+ while (r4 > 0) {
+ mp_digit r4_long = r4;
+ mp_digit r4l = (r4_long << 32);
+ MP_ADD_CARRY(r0, r4_long, r0, 0, carry);
+ MP_ADD_CARRY(r1, -r4l, r1, carry, carry);
+ MP_ADD_CARRY(r2, MP_DIGIT_MAX, r2, carry, carry);
+ MP_ADD_CARRY(r3, r4l-r4_long-1,r3, carry, carry);
+ r4 = carry;
+ }
+
+ /* reduce the underflows */
+ while (r4 < 0) {
+ mp_digit r4_long = -r4;
+ mp_digit r4l = (r4_long << 32);
+ MP_SUB_BORROW(r0, r4_long, r0, 0, carry);
+ MP_SUB_BORROW(r1, -r4l, r1, carry, carry);
+ MP_SUB_BORROW(r2, MP_DIGIT_MAX, r2, carry, carry);
+ MP_SUB_BORROW(r3, r4l-r4_long-1,r3, carry, carry);
+ r4 = -carry;
+ }
+
+ if (a != r) {
+ MP_CHECKOK(s_mp_pad(r,4));
+ }
+ MP_SIGN(r) = MP_ZPOS;
+ MP_USED(r) = 4;
+
+ MP_DIGIT(r,3) = r3;
+ MP_DIGIT(r,2) = r2;
+ MP_DIGIT(r,1) = r1;
+ MP_DIGIT(r,0) = r0;
+
+ /* final reduction if necessary */
+ if ((r3 > 0xFFFFFFFF00000001ULL) ||
+ ((r3 == 0xFFFFFFFF00000001ULL) &&
+ (r2 || (r1 >> 32)||
+ (r1 == 0xFFFFFFFFULL && r0 == MP_DIGIT_MAX)))) {
+ /* very rare, just use mp_sub */
+ MP_CHECKOK(mp_sub(r, &meth->irr, r));
+ }
+
+ s_mp_clamp(r);
+#endif
+ }
+
+ CLEANUP:
+ return res;
+}
+
+/* Compute the square of polynomial a, reduce modulo p256. Store the
+ * result in r. r could be a. Uses optimized modular reduction for p256.
+ */
+mp_err
+ec_GFp_nistp256_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_nistp256_mod(r, r, meth));
+ CLEANUP:
+ return res;
+}
+
+/* Compute the product of two polynomials a and b, reduce modulo p256.
+ * Store the result in r. r could be a or b; a could be b. Uses
+ * optimized modular reduction for p256. */
+mp_err
+ec_GFp_nistp256_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_nistp256_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_gfp256(ECGroup *group, ECCurveName name)
+{
+ if (name == ECCurve_NIST_P256) {
+ group->meth->field_mod = &ec_GFp_nistp256_mod;
+ group->meth->field_mul = &ec_GFp_nistp256_mul;
+ group->meth->field_sqr = &ec_GFp_nistp256_sqr;
+ }
+ return MP_OKAY;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_384.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,315 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>
+ *
+ * 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* Fast modular reduction for p384 = 2^384 - 2^128 - 2^96 + 2^32 - 1. a can be r.
+ * Uses algorithm 2.30 from Hankerson, Menezes, Vanstone. Guide to
+ * Elliptic Curve Cryptography. */
+mp_err
+ec_GFp_nistp384_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ int a_bits = mpl_significant_bits(a);
+ int i;
+
+ /* m1, m2 are statically-allocated mp_int of exactly the size we need */
+ mp_int m[10];
+
+#ifdef ECL_THIRTY_TWO_BIT
+ mp_digit s[10][12];
+ for (i = 0; i < 10; i++) {
+ MP_SIGN(&m[i]) = MP_ZPOS;
+ MP_ALLOC(&m[i]) = 12;
+ MP_USED(&m[i]) = 12;
+ MP_DIGITS(&m[i]) = s[i];
+ }
+#else
+ mp_digit s[10][6];
+ for (i = 0; i < 10; i++) {
+ MP_SIGN(&m[i]) = MP_ZPOS;
+ MP_ALLOC(&m[i]) = 6;
+ MP_USED(&m[i]) = 6;
+ MP_DIGITS(&m[i]) = s[i];
+ }
+#endif
+
+#ifdef ECL_THIRTY_TWO_BIT
+ /* for polynomials larger than twice the field size or polynomials
+ * not using all words, use regular reduction */
+ if ((a_bits > 768) || (a_bits <= 736)) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+ for (i = 0; i < 12; i++) {
+ s[0][i] = MP_DIGIT(a, i);
+ }
+ s[1][0] = 0;
+ s[1][1] = 0;
+ s[1][2] = 0;
+ s[1][3] = 0;
+ s[1][4] = MP_DIGIT(a, 21);
+ s[1][5] = MP_DIGIT(a, 22);
+ s[1][6] = MP_DIGIT(a, 23);
+ s[1][7] = 0;
+ s[1][8] = 0;
+ s[1][9] = 0;
+ s[1][10] = 0;
+ s[1][11] = 0;
+ for (i = 0; i < 12; i++) {
+ s[2][i] = MP_DIGIT(a, i+12);
+ }
+ s[3][0] = MP_DIGIT(a, 21);
+ s[3][1] = MP_DIGIT(a, 22);
+ s[3][2] = MP_DIGIT(a, 23);
+ for (i = 3; i < 12; i++) {
+ s[3][i] = MP_DIGIT(a, i+9);
+ }
+ s[4][0] = 0;
+ s[4][1] = MP_DIGIT(a, 23);
+ s[4][2] = 0;
+ s[4][3] = MP_DIGIT(a, 20);
+ for (i = 4; i < 12; i++) {
+ s[4][i] = MP_DIGIT(a, i+8);
+ }
+ s[5][0] = 0;
+ s[5][1] = 0;
+ s[5][2] = 0;
+ s[5][3] = 0;
+ s[5][4] = MP_DIGIT(a, 20);
+ s[5][5] = MP_DIGIT(a, 21);
+ s[5][6] = MP_DIGIT(a, 22);
+ s[5][7] = MP_DIGIT(a, 23);
+ s[5][8] = 0;
+ s[5][9] = 0;
+ s[5][10] = 0;
+ s[5][11] = 0;
+ s[6][0] = MP_DIGIT(a, 20);
+ s[6][1] = 0;
+ s[6][2] = 0;
+ s[6][3] = MP_DIGIT(a, 21);
+ s[6][4] = MP_DIGIT(a, 22);
+ s[6][5] = MP_DIGIT(a, 23);
+ s[6][6] = 0;
+ s[6][7] = 0;
+ s[6][8] = 0;
+ s[6][9] = 0;
+ s[6][10] = 0;
+ s[6][11] = 0;
+ s[7][0] = MP_DIGIT(a, 23);
+ for (i = 1; i < 12; i++) {
+ s[7][i] = MP_DIGIT(a, i+11);
+ }
+ s[8][0] = 0;
+ s[8][1] = MP_DIGIT(a, 20);
+ s[8][2] = MP_DIGIT(a, 21);
+ s[8][3] = MP_DIGIT(a, 22);
+ s[8][4] = MP_DIGIT(a, 23);
+ s[8][5] = 0;
+ s[8][6] = 0;
+ s[8][7] = 0;
+ s[8][8] = 0;
+ s[8][9] = 0;
+ s[8][10] = 0;
+ s[8][11] = 0;
+ s[9][0] = 0;
+ s[9][1] = 0;
+ s[9][2] = 0;
+ s[9][3] = MP_DIGIT(a, 23);
+ s[9][4] = MP_DIGIT(a, 23);
+ s[9][5] = 0;
+ s[9][6] = 0;
+ s[9][7] = 0;
+ s[9][8] = 0;
+ s[9][9] = 0;
+ s[9][10] = 0;
+ s[9][11] = 0;
+
+ MP_CHECKOK(mp_add(&m[0], &m[1], r));
+ MP_CHECKOK(mp_add(r, &m[1], r));
+ MP_CHECKOK(mp_add(r, &m[2], r));
+ MP_CHECKOK(mp_add(r, &m[3], r));
+ MP_CHECKOK(mp_add(r, &m[4], r));
+ MP_CHECKOK(mp_add(r, &m[5], r));
+ MP_CHECKOK(mp_add(r, &m[6], r));
+ MP_CHECKOK(mp_sub(r, &m[7], r));
+ MP_CHECKOK(mp_sub(r, &m[8], r));
+ MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
+ s_mp_clamp(r);
+ }
+#else
+ /* for polynomials larger than twice the field size or polynomials
+ * not using all words, use regular reduction */
+ if ((a_bits > 768) || (a_bits <= 736)) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+ for (i = 0; i < 6; i++) {
+ s[0][i] = MP_DIGIT(a, i);
+ }
+ s[1][0] = 0;
+ s[1][1] = 0;
+ s[1][2] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
+ s[1][3] = MP_DIGIT(a, 11) >> 32;
+ s[1][4] = 0;
+ s[1][5] = 0;
+ for (i = 0; i < 6; i++) {
+ s[2][i] = MP_DIGIT(a, i+6);
+ }
+ s[3][0] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
+ s[3][1] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
+ for (i = 2; i < 6; i++) {
+ s[3][i] = (MP_DIGIT(a, i+4) >> 32) | (MP_DIGIT(a, i+5) << 32);
+ }
+ s[4][0] = (MP_DIGIT(a, 11) >> 32) << 32;
+ s[4][1] = MP_DIGIT(a, 10) << 32;
+ for (i = 2; i < 6; i++) {
+ s[4][i] = MP_DIGIT(a, i+4);
+ }
+ s[5][0] = 0;
+ s[5][1] = 0;
+ s[5][2] = MP_DIGIT(a, 10);
+ s[5][3] = MP_DIGIT(a, 11);
+ s[5][4] = 0;
+ s[5][5] = 0;
+ s[6][0] = (MP_DIGIT(a, 10) << 32) >> 32;
+ s[6][1] = (MP_DIGIT(a, 10) >> 32) << 32;
+ s[6][2] = MP_DIGIT(a, 11);
+ s[6][3] = 0;
+ s[6][4] = 0;
+ s[6][5] = 0;
+ s[7][0] = (MP_DIGIT(a, 11) >> 32) | (MP_DIGIT(a, 6) << 32);
+ for (i = 1; i < 6; i++) {
+ s[7][i] = (MP_DIGIT(a, i+5) >> 32) | (MP_DIGIT(a, i+6) << 32);
+ }
+ s[8][0] = MP_DIGIT(a, 10) << 32;
+ s[8][1] = (MP_DIGIT(a, 10) >> 32) | (MP_DIGIT(a, 11) << 32);
+ s[8][2] = MP_DIGIT(a, 11) >> 32;
+ s[8][3] = 0;
+ s[8][4] = 0;
+ s[8][5] = 0;
+ s[9][0] = 0;
+ s[9][1] = (MP_DIGIT(a, 11) >> 32) << 32;
+ s[9][2] = MP_DIGIT(a, 11) >> 32;
+ s[9][3] = 0;
+ s[9][4] = 0;
+ s[9][5] = 0;
+
+ MP_CHECKOK(mp_add(&m[0], &m[1], r));
+ MP_CHECKOK(mp_add(r, &m[1], r));
+ MP_CHECKOK(mp_add(r, &m[2], r));
+ MP_CHECKOK(mp_add(r, &m[3], r));
+ MP_CHECKOK(mp_add(r, &m[4], r));
+ MP_CHECKOK(mp_add(r, &m[5], r));
+ MP_CHECKOK(mp_add(r, &m[6], r));
+ MP_CHECKOK(mp_sub(r, &m[7], r));
+ MP_CHECKOK(mp_sub(r, &m[8], r));
+ MP_CHECKOK(mp_submod(r, &m[9], &meth->irr, r));
+ s_mp_clamp(r);
+ }
+#endif
+
+ CLEANUP:
+ return res;
+}
+
+/* Compute the square of polynomial a, reduce modulo p384. Store the
+ * result in r. r could be a. Uses optimized modular reduction for p384.
+ */
+mp_err
+ec_GFp_nistp384_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_nistp384_mod(r, r, meth));
+ CLEANUP:
+ return res;
+}
+
+/* Compute the product of two polynomials a and b, reduce modulo p384.
+ * Store the result in r. r could be a or b; a could be b. Uses
+ * optimized modular reduction for p384. */
+mp_err
+ec_GFp_nistp384_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_nistp384_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_gfp384(ECGroup *group, ECCurveName name)
+{
+ if (name == ECCurve_NIST_P384) {
+ group->meth->field_mod = &ec_GFp_nistp384_mod;
+ group->meth->field_mul = &ec_GFp_nistp384_mul;
+ group->meth->field_sqr = &ec_GFp_nistp384_sqr;
+ }
+ return MP_OKAY;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_521.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,192 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>
+ *
+ * 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mpi.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+#define ECP521_DIGITS ECL_CURVE_DIGITS(521)
+
+/* Fast modular reduction for p521 = 2^521 - 1. a can be r. Uses
+ * algorithm 2.31 from Hankerson, Menezes, Vanstone. Guide to
+ * Elliptic Curve Cryptography. */
+mp_err
+ec_GFp_nistp521_mod(const mp_int *a, mp_int *r, const GFMethod *meth)
+{
+ mp_err res = MP_OKAY;
+ int a_bits = mpl_significant_bits(a);
+ int i;
+
+ /* m1, m2 are statically-allocated mp_int of exactly the size we need */
+ mp_int m1;
+
+ mp_digit s1[ECP521_DIGITS] = { 0 };
+
+ MP_SIGN(&m1) = MP_ZPOS;
+ MP_ALLOC(&m1) = ECP521_DIGITS;
+ MP_USED(&m1) = ECP521_DIGITS;
+ MP_DIGITS(&m1) = s1;
+
+ if (a_bits < 521) {
+ if (a==r) return MP_OKAY;
+ return mp_copy(a, r);
+ }
+ /* for polynomials larger than twice the field size or polynomials
+ * not using all words, use regular reduction */
+ if (a_bits > (521*2)) {
+ MP_CHECKOK(mp_mod(a, &meth->irr, r));
+ } else {
+#define FIRST_DIGIT (ECP521_DIGITS-1)
+ for (i = FIRST_DIGIT; i < MP_USED(a)-1; i++) {
+ s1[i-FIRST_DIGIT] = (MP_DIGIT(a, i) >> 9)
+ | (MP_DIGIT(a, 1+i) << (MP_DIGIT_BIT-9));
+ }
+ s1[i-FIRST_DIGIT] = MP_DIGIT(a, i) >> 9;
+
+ if ( a != r ) {
+ MP_CHECKOK(s_mp_pad(r,ECP521_DIGITS));
+ for (i = 0; i < ECP521_DIGITS; i++) {
+ MP_DIGIT(r,i) = MP_DIGIT(a, i);
+ }
+ }
+ MP_USED(r) = ECP521_DIGITS;
+ MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
+
+ MP_CHECKOK(s_mp_add(r, &m1));
+ if (MP_DIGIT(r, FIRST_DIGIT) & 0x200) {
+ MP_CHECKOK(s_mp_add_d(r,1));
+ MP_DIGIT(r,FIRST_DIGIT) &= 0x1FF;
+ }
+ s_mp_clamp(r);
+ }
+
+ CLEANUP:
+ return res;
+}
+
+/* Compute the square of polynomial a, reduce modulo p521. Store the
+ * result in r. r could be a. Uses optimized modular reduction for p521.
+ */
+mp_err
+ec_GFp_nistp521_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_nistp521_mod(r, r, meth));
+ CLEANUP:
+ return res;
+}
+
+/* Compute the product of two polynomials a and b, reduce modulo p521.
+ * Store the result in r. r could be a or b; a could be b. Uses
+ * optimized modular reduction for p521. */
+mp_err
+ec_GFp_nistp521_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_nistp521_mod(r, r, meth));
+ CLEANUP:
+ return res;
+}
+
+/* Divides two field elements. If a is NULL, then returns the inverse of
+ * b. */
+mp_err
+ec_GFp_nistp521_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, FLAG(b)));
+ MP_CHECKOK(mp_invmod(b, &meth->irr, &t));
+ MP_CHECKOK(mp_mul(a, &t, r));
+ MP_CHECKOK(ec_GFp_nistp521_mod(r, r, meth));
+ CLEANUP:
+ mp_clear(&t);
+ return res;
+ }
+}
+
+/* Wire in fast field arithmetic and precomputation of base point for
+ * named curves. */
+mp_err
+ec_group_set_gfp521(ECGroup *group, ECCurveName name)
+{
+ if (name == ECCurve_NIST_P521) {
+ group->meth->field_mod = &ec_GFp_nistp521_mod;
+ group->meth->field_mul = &ec_GFp_nistp521_mul;
+ group->meth->field_sqr = &ec_GFp_nistp521_sqr;
+ group->meth->field_div = &ec_GFp_nistp521_div;
+ }
+ return MP_OKAY;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_aff.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,379 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang-Shantz <sheueling.chang@sun.com>,
+ * Stephen Fung <fungstep@hotmail.com>, and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
+ * Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
+ * Nils Larsch <nla@trustcenter.de>, and
+ * Lenka Fibikova <fibikova@exp-math.uni-essen.de>, 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mplogic.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+/* 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, FLAG(px)));
+ MP_CHECKOK(mp_init(&temp, FLAG(px)));
+ MP_CHECKOK(mp_init(&tempx, FLAG(px)));
+ MP_CHECKOK(mp_init(&tempy, FLAG(px)));
+ /* 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, FLAG(px)));
+ /* 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
+
+/* Validates a point on a GFp curve. */
+mp_err
+ec_GFp_validate_point(const mp_int *px, const mp_int *py, const ECGroup *group)
+{
+ mp_err res = MP_NO;
+ mp_int accl, accr, tmp, pxt, pyt;
+
+ MP_DIGITS(&accl) = 0;
+ MP_DIGITS(&accr) = 0;
+ MP_DIGITS(&tmp) = 0;
+ MP_DIGITS(&pxt) = 0;
+ MP_DIGITS(&pyt) = 0;
+ MP_CHECKOK(mp_init(&accl, FLAG(px)));
+ MP_CHECKOK(mp_init(&accr, FLAG(px)));
+ MP_CHECKOK(mp_init(&tmp, FLAG(px)));
+ MP_CHECKOK(mp_init(&pxt, FLAG(px)));
+ MP_CHECKOK(mp_init(&pyt, FLAG(px)));
+
+ /* 1: Verify that publicValue is not the point at infinity */
+ if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+ /* 2: Verify that the coordinates of publicValue are elements
+ * of the field.
+ */
+ if ((MP_SIGN(px) == MP_NEG) || (mp_cmp(px, &group->meth->irr) >= 0) ||
+ (MP_SIGN(py) == MP_NEG) || (mp_cmp(py, &group->meth->irr) >= 0)) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+ /* 3: Verify that publicValue is on the curve. */
+ if (group->meth->field_enc) {
+ group->meth->field_enc(px, &pxt, group->meth);
+ group->meth->field_enc(py, &pyt, group->meth);
+ } else {
+ mp_copy(px, &pxt);
+ mp_copy(py, &pyt);
+ }
+ /* left-hand side: y^2 */
+ MP_CHECKOK( group->meth->field_sqr(&pyt, &accl, group->meth) );
+ /* right-hand side: x^3 + a*x + b */
+ MP_CHECKOK( group->meth->field_sqr(&pxt, &tmp, group->meth) );
+ MP_CHECKOK( group->meth->field_mul(&pxt, &tmp, &accr, group->meth) );
+ MP_CHECKOK( group->meth->field_mul(&group->curvea, &pxt, &tmp, group->meth) );
+ MP_CHECKOK( group->meth->field_add(&tmp, &accr, &accr, group->meth) );
+ MP_CHECKOK( group->meth->field_add(&accr, &group->curveb, &accr, group->meth) );
+ /* check LHS - RHS == 0 */
+ MP_CHECKOK( group->meth->field_sub(&accl, &accr, &accr, group->meth) );
+ if (mp_cmp_z(&accr) != 0) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+ /* 4: Verify that the order of the curve times the publicValue
+ * is the point at infinity.
+ */
+ MP_CHECKOK( ECPoint_mul(group, &group->order, px, py, &pxt, &pyt) );
+ if (ec_GFp_pt_is_inf_aff(&pxt, &pyt) != MP_YES) {
+ res = MP_NO;
+ goto CLEANUP;
+ }
+
+ res = MP_YES;
+
+CLEANUP:
+ mp_clear(&accl);
+ mp_clear(&accr);
+ mp_clear(&tmp);
+ mp_clear(&pxt);
+ mp_clear(&pyt);
+ return res;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_jac.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,575 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang-Shantz <sheueling.chang@sun.com>,
+ * Stephen Fung <fungstep@hotmail.com>, and
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories.
+ * Bodo Moeller <moeller@cdc.informatik.tu-darmstadt.de>,
+ * Nils Larsch <nla@trustcenter.de>, and
+ * Lenka Fibikova <fibikova@exp-math.uni-essen.de>, 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "mplogic.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+#ifdef ECL_DEBUG
+#include <assert.h>
+#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, FLAG(px)));
+ MP_CHECKOK(mp_init(&z2, FLAG(px)));
+ MP_CHECKOK(mp_init(&z3, FLAG(px)));
+
+ /* 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, FLAG(px)));
+ MP_CHECKOK(mp_init(&B, FLAG(px)));
+ MP_CHECKOK(mp_init(&C, FLAG(px)));
+ MP_CHECKOK(mp_init(&D, FLAG(px)));
+ MP_CHECKOK(mp_init(&C2, FLAG(px)));
+ MP_CHECKOK(mp_init(&C3, FLAG(px)));
+
+ /* 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, FLAG(px)));
+ MP_CHECKOK(mp_init(&t1, FLAG(px)));
+ MP_CHECKOK(mp_init(&M, FLAG(px)));
+ MP_CHECKOK(mp_init(&S, FLAG(px)));
+
+ 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, FLAG(px)) == 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], FLAG(k1)));
+ MP_CHECKOK(mp_init(&precomp[i][j][1], FLAG(k1)));
+ }
+ }
+
+ /* 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, FLAG(k1)));
+ 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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_jm.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,353 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Stephen Fung <fungstep@hotmail.com>, 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "ecp.h"
+#include "ecl-priv.h"
+#include "mplogic.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#endif
+
+#define MAX_SCRATCH 6
+
+/* 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, mp_int scratch[], const ECGroup *group)
+{
+ mp_err res = MP_OKAY;
+ mp_int *t0, *t1, *M, *S;
+
+ t0 = &scratch[0];
+ t1 = &scratch[1];
+ M = &scratch[2];
+ S = &scratch[3];
+
+#if MAX_SCRATCH < 4
+#error "Scratch array defined too small "
+#endif
+
+ /* Check for point at infinity */
+ if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
+ /* Set r = pt at infinity by setting rz = 0 */
+
+ 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, S, group->meth));
+ MP_CHECKOK(group->meth->field_add(S, S, rz, group->meth));
+
+ /* t0 = 2y^2 , t1 = 8y^4 */
+ MP_CHECKOK(group->meth->field_sqr(py, t0, group->meth));
+ MP_CHECKOK(group->meth->field_add(t0, t0, t0, group->meth));
+ MP_CHECKOK(group->meth->field_sqr(t0, t1, group->meth));
+ MP_CHECKOK(group->meth->field_add(t1, t1, t1, group->meth));
+
+ /* 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, S, group->meth));
+ MP_CHECKOK(group->meth->field_mul(S, M, ry, group->meth));
+ MP_CHECKOK(group->meth->field_sub(ry, t1, ry, group->meth));
+
+ /* ra*z^4 = 2*t1*(apz4) */
+ MP_CHECKOK(group->meth->field_mul(paz4, t1, raz4, group->meth));
+ MP_CHECKOK(group->meth->field_add(raz4, raz4, raz4, group->meth));
+
+
+ CLEANUP:
+ 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, mp_int scratch[], const ECGroup *group)
+{
+ mp_err res = MP_OKAY;
+ mp_int *A, *B, *C, *D, *C2, *C3;
+
+ A = &scratch[0];
+ B = &scratch[1];
+ C = &scratch[2];
+ D = &scratch[3];
+ C2 = &scratch[4];
+ C3 = &scratch[5];
+
+#if MAX_SCRATCH < 6
+#error "Scratch array defined too small "
+#endif
+
+ /* If either P or Q is the point at infinity, then return the other
+ * point */
+ if (ec_GFp_pt_is_inf_jac(px, py, pz) == MP_YES) {
+ MP_CHECKOK(ec_GFp_pt_aff2jac(qx, qy, rx, ry, rz, group));
+ MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
+ MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
+ MP_CHECKOK(group->meth->
+ field_mul(raz4, &group->curvea, raz4, group->meth));
+ goto CLEANUP;
+ }
+ if (ec_GFp_pt_is_inf_aff(qx, qy) == MP_YES) {
+ MP_CHECKOK(mp_copy(px, rx));
+ MP_CHECKOK(mp_copy(py, ry));
+ MP_CHECKOK(mp_copy(pz, rz));
+ MP_CHECKOK(mp_copy(paz4, raz4));
+ goto CLEANUP;
+ }
+
+ /* A = qx * pz^2, B = qy * pz^3 */
+ MP_CHECKOK(group->meth->field_sqr(pz, A, group->meth));
+ MP_CHECKOK(group->meth->field_mul(A, pz, B, group->meth));
+ MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
+ MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
+
+ /* C = A - px, D = B - py */
+ MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
+ MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
+
+ /* C2 = C^2, C3 = C^3 */
+ MP_CHECKOK(group->meth->field_sqr(C, C2, group->meth));
+ MP_CHECKOK(group->meth->field_mul(C, C2, C3, group->meth));
+
+ /* rz = pz * C */
+ MP_CHECKOK(group->meth->field_mul(pz, C, rz, group->meth));
+
+ /* C = px * C^2 */
+ MP_CHECKOK(group->meth->field_mul(px, C2, C, group->meth));
+ /* A = D^2 */
+ MP_CHECKOK(group->meth->field_sqr(D, A, group->meth));
+
+ /* rx = D^2 - (C^3 + 2 * (px * C^2)) */
+ MP_CHECKOK(group->meth->field_add(C, C, rx, group->meth));
+ MP_CHECKOK(group->meth->field_add(C3, rx, rx, group->meth));
+ MP_CHECKOK(group->meth->field_sub(A, rx, rx, group->meth));
+
+ /* C3 = py * C^3 */
+ MP_CHECKOK(group->meth->field_mul(py, C3, C3, group->meth));
+
+ /* ry = D * (px * C^2 - rx) - py * C^3 */
+ MP_CHECKOK(group->meth->field_sub(C, rx, ry, group->meth));
+ MP_CHECKOK(group->meth->field_mul(D, ry, ry, group->meth));
+ MP_CHECKOK(group->meth->field_sub(ry, C3, ry, group->meth));
+
+ /* raz4 = a * rz^4 */
+ MP_CHECKOK(group->meth->field_sqr(rz, raz4, group->meth));
+ MP_CHECKOK(group->meth->field_sqr(raz4, raz4, group->meth));
+ MP_CHECKOK(group->meth->
+ field_mul(raz4, &group->curvea, raz4, group->meth));
+CLEANUP:
+ 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;
+ mp_int scratch[MAX_SCRATCH];
+ signed char *naf = NULL;
+ int i, orderBitSize;
+
+ MP_DIGITS(&rz) = 0;
+ MP_DIGITS(&raz4) = 0;
+ MP_DIGITS(&tpx) = 0;
+ MP_DIGITS(&tpy) = 0;
+ for (i = 0; i < 16; i++) {
+ MP_DIGITS(&precomp[i][0]) = 0;
+ MP_DIGITS(&precomp[i][1]) = 0;
+ }
+ for (i = 0; i < MAX_SCRATCH; i++) {
+ MP_DIGITS(&scratch[i]) = 0;
+ }
+
+ ARGCHK(group != NULL, MP_BADARG);
+ ARGCHK((n != NULL) && (px != NULL) && (py != NULL), MP_BADARG);
+
+ /* initialize precomputation table */
+ MP_CHECKOK(mp_init(&tpx, FLAG(n)));
+ MP_CHECKOK(mp_init(&tpy, FLAG(n)));;
+ MP_CHECKOK(mp_init(&rz, FLAG(n)));
+ MP_CHECKOK(mp_init(&raz4, FLAG(n)));
+
+ for (i = 0; i < 16; i++) {
+ MP_CHECKOK(mp_init(&precomp[i][0], FLAG(n)));
+ MP_CHECKOK(mp_init(&precomp[i][1], FLAG(n)));
+ }
+ for (i = 0; i < MAX_SCRATCH; i++) {
+ MP_CHECKOK(mp_init(&scratch[i], FLAG(n)));
+ }
+
+ /* 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 */
+#ifdef _KERNEL
+ naf = (signed char *) kmem_alloc((orderBitSize + 1), FLAG(n));
+#else
+ naf = (signed char *) malloc(sizeof(signed char) * (orderBitSize + 1));
+ if (naf == NULL) {
+ res = MP_MEM;
+ goto CLEANUP;
+ }
+#endif
+
+ /* Compute 5NAF */
+ ec_compute_wNAF(naf, orderBitSize, n, 5);
+
+ /* wNAF method */
+ for (i = orderBitSize; i >= 0; i--) {
+ /* R = 2R */
+ ec_GFp_pt_dbl_jm(rx, ry, &rz, &raz4, rx, ry, &rz,
+ &raz4, scratch, group);
+ if (naf[i] != 0) {
+ ec_GFp_pt_add_jm_aff(rx, ry, &rz, &raz4,
+ &precomp[(naf[i] + 15) / 2][0],
+ &precomp[(naf[i] + 15) / 2][1], rx, ry,
+ &rz, &raz4, scratch, group);
+ }
+ }
+
+ /* convert result S to affine coordinates */
+ MP_CHECKOK(ec_GFp_pt_jac2aff(rx, ry, &rz, rx, ry, group));
+
+ CLEANUP:
+ for (i = 0; i < MAX_SCRATCH; i++) {
+ mp_clear(&scratch[i]);
+ }
+ for (i = 0; i < 16; i++) {
+ mp_clear(&precomp[i][0]);
+ mp_clear(&precomp[i][1]);
+ }
+ mp_clear(&tpx);
+ mp_clear(&tpy);
+ mp_clear(&rz);
+ mp_clear(&raz4);
+#ifdef _KERNEL
+ kmem_free(naf, (orderBitSize + 1));
+#else
+ free(naf);
+#endif
+ return res;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/ecp_mont.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,223 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Douglas Stebila <douglas@stebila.ca>, Sun Microsystems Laboratories
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* 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"
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+
+/* 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;
+
+#ifdef _KERNEL
+ mmm = (mp_mont_modulus *) kmem_alloc(sizeof(mp_mont_modulus),
+ FLAG(irr));
+#else
+ mmm = (mp_mont_modulus *) malloc(sizeof(mp_mont_modulus));
+#endif
+ 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, FLAG(a)));
+ 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) {
+#ifdef _KERNEL
+ kmem_free(meth->extra1, sizeof(mp_mont_modulus));
+#else
+ free(meth->extra1);
+#endif
+ meth->extra1 = NULL;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/logtab.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,82 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 Netscape security libraries.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1994-2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Dr Vipul Gupta <vipul.gupta@sun.com>, 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _LOGTAB_H
+#define _LOGTAB_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+const float s_logv_2[] = {
+ 0.000000000f, 0.000000000f, 1.000000000f, 0.630929754f, /* 0 1 2 3 */
+ 0.500000000f, 0.430676558f, 0.386852807f, 0.356207187f, /* 4 5 6 7 */
+ 0.333333333f, 0.315464877f, 0.301029996f, 0.289064826f, /* 8 9 10 11 */
+ 0.278942946f, 0.270238154f, 0.262649535f, 0.255958025f, /* 12 13 14 15 */
+ 0.250000000f, 0.244650542f, 0.239812467f, 0.235408913f, /* 16 17 18 19 */
+ 0.231378213f, 0.227670249f, 0.224243824f, 0.221064729f, /* 20 21 22 23 */
+ 0.218104292f, 0.215338279f, 0.212746054f, 0.210309918f, /* 24 25 26 27 */
+ 0.208014598f, 0.205846832f, 0.203795047f, 0.201849087f, /* 28 29 30 31 */
+ 0.200000000f, 0.198239863f, 0.196561632f, 0.194959022f, /* 32 33 34 35 */
+ 0.193426404f, 0.191958720f, 0.190551412f, 0.189200360f, /* 36 37 38 39 */
+ 0.187901825f, 0.186652411f, 0.185449023f, 0.184288833f, /* 40 41 42 43 */
+ 0.183169251f, 0.182087900f, 0.181042597f, 0.180031327f, /* 44 45 46 47 */
+ 0.179052232f, 0.178103594f, 0.177183820f, 0.176291434f, /* 48 49 50 51 */
+ 0.175425064f, 0.174583430f, 0.173765343f, 0.172969690f, /* 52 53 54 55 */
+ 0.172195434f, 0.171441601f, 0.170707280f, 0.169991616f, /* 56 57 58 59 */
+ 0.169293808f, 0.168613099f, 0.167948779f, 0.167300179f, /* 60 61 62 63 */
+ 0.166666667f
+};
+
+#endif /* _LOGTAB_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/mp_gf2m-priv.h Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,122 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang Shantz <sheueling.chang@sun.com> and
+ * Douglas Stebila <douglas@stebila.ca> 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _MP_GF2M_PRIV_H_
+#define _MP_GF2M_PRIV_H_
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#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_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/native/sun/security/ec/mp_gf2m.c Tue Aug 11 16:52:26 2009 +0100
@@ -0,0 +1,624 @@
+/* *********************************************************************
+ *
+ * Sun elects to have this file available under and governed by the
+ * Mozilla Public License Version 1.1 ("MPL") (see
+ * http://www.mozilla.org/MPL/ for full license text). For the avoidance
+ * of doubt and subject to the following, Sun also elects to allow
+ * licensees to use this file under the MPL, the GNU General Public
+ * License version 2 only or the Lesser General Public License version
+ * 2.1 only. Any references to the "GNU General Public License version 2
+ * or later" or "GPL" in the following shall be construed to mean the
+ * GNU General Public License version 2 only. Any references to the "GNU
+ * Lesser General Public License version 2.1 or later" or "LGPL" in the
+ * following shall be construed to mean the GNU Lesser General Public
+ * License version 2.1 only. However, the following notice accompanied
+ * the original version of this file:
+ *
+ * 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 the Initial Developer are Copyright (C) 2003
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Sheueling Chang Shantz <sheueling.chang@sun.com> and
+ * Douglas Stebila <douglas@stebila.ca> 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.
+ *
+ *********************************************************************** */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include "mp_gf2m.h"
+#include "mp_gf2m-priv.h"
+#include "mplogic.h"
+#include "mpi-priv.h"
+
+const mp_digit mp_gf2m_sqr_tb[16] =
+{
+ 0, 1, 4, 5, 16, 17, 20, 21,
+ 64, 65, 68, 69, 80, 81, 84, 85
+};
+
+/* 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.
+ */
+#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;
+ mp_digit tab[8], top2b = a >> 30;
+ register mp_digit a1, a2, a4;
+
+ a1 = a & (0x3FFFFFFF); a2 = a1 << 1; a4 = a2 << 1;
+
+ tab[0] = 0; tab[1] = a1; tab[2] = a2; tab[3] = a1^a2;
+ tab[4] = a4; tab[5] = a1^a4; tab[6] = a2^a4; tab[7] = a1^a2^a4;
+
+ s = tab[b & 0x7]; l = s;
+ s = tab[b >> 3 & 0x7]; l ^= s << 3; h = s >> 29;
+ s = tab[b >> 6 & 0x7]; l ^= s << 6; h ^= s >> 26;
+ s = tab[b >> 9 & 0x7]; l ^= s << 9; h ^= s >> 23;
+ s = tab[b >> 12 & 0x7]; l ^= s << 12; h ^= s >> 20;
+ s = tab[b >> 15 & 0x7]; l ^= s << 15; h ^= s >> 17;
+ s = tab[b >> 18 & 0x7]; l ^= s << 18; h ^= s >> 14;
+ s = tab[b >> 21 & 0x7]; l ^= s << 21; h ^= s >> 11;
+ s = tab[b >> 24 & 0x7]; l ^= s << 24; h ^= s >> 8;
+ s = tab[b >> 27 & 0x7]; l ^= s << 27; h ^= s >> 5;
+ s = tab[b >> 30 ]; l ^= s << 30; h ^= s >> 2;
+
+ /* compensate for the top two bits of a */
+
+ if (top2b & 01) { l ^= b << 30; h ^= b >> 2; }
+ if (top2b & 02) { l ^= b << 31; h ^= b >> 1; }
+
+ *rh = h; *rl = l;
+}
+#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;
+ mp_digit tab[16], top3b = a >> 61;
+ register mp_digit a1, a2, a4, a8;
+
+ a1 = a & (0x1FFFFFFFFFFFFFFFULL); a2 = a1 << 1;
+ a4 = a2 << 1; a8 = a4 << 1;
+ tab[ 0] = 0; tab[ 1] = a1; tab[ 2] = a2; tab[ 3] = a1^a2;
+ tab[ 4] = a4; tab[ 5] = a1^a4; tab[ 6] = a2^a4; tab[ 7] = a1^a2^a4;
+ tab[ 8] = a8; tab[ 9] = a1^a8; tab[10] = a2^a8; tab[11] = a1^a2^a8;
+ tab[12] = a4^a8; tab[13] = a1^a4^a8; tab[14] = a2^a4^a8; tab[15] = a1^a2^a4^a8;
+
+ s = tab[b & 0xF]; l = s;
+ s = tab[b >> 4 & 0xF]; l ^= s << 4; h = s >> 60;
+ s = tab[b >> 8 & 0xF]; l ^= s << 8; h ^= s >> 56;
+ s = tab[b >> 12 & 0xF]; l ^= s << 12; h ^= s >> 52;
+ s = tab[b >> 16 & 0xF]; l ^= s << 16; h ^= s >> 48;
+ s = tab[b >> 20 & 0xF]; l ^= s << 20; h ^= s >> 44;
+ s = tab[b >> 24 & 0xF]; l ^= s << 24; h ^= s >> 40;
+ s = tab[b >> 28 & 0xF]; l ^= s << 28; h ^= s >> 36;
+ s = tab[b >> 32 & 0xF]; l ^= s << 32; h ^= s >> 32;
+ s = tab[b >> 36 & 0xF]; l ^= s << 36; h ^= s >> 28;
+ s = tab[b >> 40 & 0xF]; l ^= s << 40; h ^= s >> 24;
+ s = tab[b >> 44 & 0xF]; l ^= s << 44; h ^= s >> 20;
+ s = tab[b >> 48 & 0xF]; l ^= s << 48; h ^= s >> 16;
+ s = tab[b >> 52 & 0xF]; l ^= s << 52; h ^= s >> 12;
+ s = tab[b >> 56 & 0xF]; l ^= s << 56; h ^= s >> 8;
+ s = tab[b >> 60 ]; l ^= s << 60; h ^= s >> 4;
+
+ /* compensate for the top three bits of a */
+
+ if (top3b & 01) { l ^= b << 61; h ^= b >> 3; }
+ if (top3b & 02) { l ^= b << 62; h ^= b >> 2; }
+ if (top3b & 04) { l ^= b << 63; h ^= b >> 1; }
+
+ *rh = h; *rl = l;
+}
+#endif
+
+/* 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)
+{
+ mp_digit m1, m0;
+ /* r[3] = h1, r[2] = h0; r[1] = l1; r[0] = l0 */
+ s_bmul_1x1(r+3, r+2, a1, b1);
+ s_bmul_1x1(r+1, r, a0, b0);
+ 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; */
+}
+
+/* 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];