Merge
authorxdono
Tue, 18 Aug 2009 19:53:43 -0700
changeset 3639 fbc385f763cd
parent 3638 fbd0a9baa7d4 (current diff)
parent 3497 6306a67647e6 (diff)
child 3640 fd536f8d24a6
Merge
jdk/test/java/util/concurrent/ConcurrentLinkedQueue/ConcurrentQueueLoops.java
jdk/test/java/util/concurrent/ConcurrentLinkedQueue/LoopHelpers.java
--- a/jdk/.hgtags	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/.hgtags	Tue Aug 18 19:53:43 2009 -0700
@@ -43,3 +43,4 @@
 bd31b30a5b21f20e42965b1633f18a5c7946d398 jdk7-b66
 a952aafd5181af953b0ef3010dbd2fcc28460e8a jdk7-b67
 b23d905cb5d3b382295240d28ab0bfb266b4503c jdk7-b68
+226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69
--- a/jdk/THIRD_PARTY_README	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/THIRD_PARTY_README	Tue Aug 18 19:53:43 2009 -0700
@@ -32,7 +32,7 @@
 
 --- end of LICENSE file ---
 %% This notice is provided with respect to ASM, which may be included with this software: 
-Copyright (c) 2000-2005 INRIA, France Telecom
+Copyright (c) 2000-2007 INRIA, France Telecom
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
--- a/jdk/make/java/java/FILES_java.gmk	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/java/java/FILES_java.gmk	Tue Aug 18 19:53:43 2009 -0700
@@ -77,6 +77,7 @@
     java/lang/Compiler.java \
     java/lang/Throwable.java \
         java/lang/Exception.java \
+	    java/lang/ReflectiveOperationException.java \
 	    java/lang/IllegalAccessException.java \
 	    java/lang/InstantiationException.java \
 	    java/lang/ClassNotFoundException.java \
@@ -250,6 +251,8 @@
 	java/util/IdentityHashMap.java \
 	java/util/EnumMap.java \
     java/util/Arrays.java \
+    java/util/TimSort.java \
+    java/util/ComparableTimSort.java \
     java/util/ConcurrentModificationException.java \
     java/util/ServiceLoader.java \
     java/util/ServiceConfigurationError.java \
--- a/jdk/make/sun/net/FILES_java.gmk	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/sun/net/FILES_java.gmk	Tue Aug 18 19:53:43 2009 -0700
@@ -41,6 +41,7 @@
 	sun/net/NetProperties.java \
 	sun/net/NetHooks.java \
 	sun/net/util/IPAddressUtil.java \
+	sun/net/util/URLUtil.java \
 	sun/net/dns/ResolverConfiguration.java \
 	sun/net/dns/ResolverConfigurationImpl.java \
 	sun/net/ftp/FtpClient.java \
--- a/jdk/make/sun/security/Makefile	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/sun/security/Makefile	Tue Aug 18 19:53:43 2009 -0700
@@ -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 @@
   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::
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/sun/security/ec/FILES_c.gmk	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/make/sun/security/ec/Makefile	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/make/sun/security/ec/mapfile-vers	Tue Aug 18 19:53:43 2009 -0700
@@ -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:
+                *;
+};
--- a/jdk/make/sun/security/other/Makefile	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/sun/security/other/Makefile	Tue Aug 18 19:53:43 2009 -0700
@@ -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 @@
 #
 AUTO_FILES_JAVA_DIRS = \
     sun/security/acl \
-    sun/security/ec \
     sun/security/jca \
     sun/security/pkcs \
     sun/security/pkcs12 \
--- a/jdk/make/tools/CharsetMapping/IBM420.c2b	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/tools/CharsetMapping/IBM420.c2b	Tue Aug 18 19:53:43 2009 -0700
@@ -1,1 +1,187 @@
-0x15	U+0085
+#
+#  The diff of 01A434B0.TXMAP110 and 34B001A4.RXMAP110
+#
+#  Added: 0x15    U+0085
+#
+0x15    U+0085
+0x42    U+FE7C
+0x46    U+FE80
+0x47    U+FE81
+0x49    U+FE83
+0x4B    U+066C
+0x4B    U+FF0E
+0x4C    U+FF1C
+0x4D    U+FF08
+0x4E    U+FF0B
+0x4F    U+FF5C
+0x50    U+FF06
+0x52    U+FE85
+0x52    U+FE86
+0x55    U+FE89
+0x55    U+FE8A
+0x55    U+FE8B
+0x55    U+FE8C
+0x56    U+0625
+0x56    U+FE87
+0x56    U+FE8D
+0x57    U+FE88
+0x58    U+FE8F
+0x58    U+FE90
+0x59    U+FE92
+0x5A    U+FF01
+0x5B    U+FF04
+0x5C    U+066D
+0x5C    U+FF0A
+0x5D    U+FF09
+0x5E    U+FF1B
+0x60    U+FF0D
+0x61    U+FF0F
+0x62    U+FE93
+0x62    U+FE94
+0x63    U+FE95
+0x63    U+FE96
+0x64    U+FE98
+0x65    U+FE99
+0x65    U+FE9A
+0x66    U+FE9C
+0x67    U+FE9D
+0x67    U+FE9E
+0x68    U+FEA0
+0x69    U+FEA1
+0x69    U+FEA2
+0x6B    U+066B
+0x6B    U+FF0C
+0x6C    U+066A
+0x6C    U+FF05
+0x6D    U+FF3F
+0x6E    U+FF1E
+0x6F    U+FF1F
+0x70    U+FEA4
+0x71    U+FEA5
+0x71    U+FEA6
+0x72    U+FEA8
+0x73    U+FEA9
+0x73    U+FEAA
+0x74    U+FEAB
+0x74    U+FEAC
+0x75    U+FEAD
+0x75    U+FEAE
+0x76    U+FEAF
+0x76    U+FEB0
+0x77    U+FEB1
+0x77    U+FEB2
+0x78    U+FEB4
+0x7A    U+FF1A
+0x7B    U+FF03
+0x7C    U+FF20
+0x7D    U+FF07
+0x7E    U+FF1D
+0x7F    U+FF02
+0x80    U+FEB5
+0x80    U+FEB6
+0x81    U+FF41
+0x82    U+FF42
+0x83    U+FF43
+0x84    U+FF44
+0x85    U+FF45
+0x86    U+FF46
+0x87    U+FF47
+0x88    U+FF48
+0x89    U+FF49
+0x8A    U+FEB8
+0x8B    U+FEB9
+0x8B    U+FEBA
+0x8C    U+FEBC
+0x8D    U+FEBD
+0x8D    U+FEBE
+0x8E    U+FEC0
+0x8F    U+FEC1
+0x8F    U+FEC2
+0x8F    U+FEC3
+0x8F    U+FEC4
+0x90    U+FEC5
+0x90    U+FEC6
+0x90    U+FEC7
+0x90    U+FEC8
+0x91    U+FF4A
+0x92    U+FF4B
+0x93    U+FF4C
+0x94    U+FF4D
+0x95    U+FF4E
+0x96    U+FF4F
+0x97    U+FF50
+0x98    U+FF51
+0x99    U+FF52
+0x9A    U+FEC9
+0x9E    U+FECD
+0xA2    U+FF53
+0xA3    U+FF54
+0xA4    U+FF55
+0xA5    U+FF56
+0xA6    U+FF57
+0xA7    U+FF58
+0xA8    U+FF59
+0xA9    U+FF5A
+0xAB    U+FED1
+0xAB    U+FED2
+0xAC    U+FED4
+0xAD    U+FED5
+0xAD    U+FED6
+0xAE    U+FED8
+0xAF    U+FED9
+0xAF    U+FEDA
+0xB0    U+FEDC
+0xB1    U+FEDD
+0xB1    U+FEDE
+0xB8    U+FEF9
+0xB9    U+FEFA
+0xBA    U+FEE0
+0xBB    U+FEE1
+0xBB    U+FEE2
+0xBC    U+FEE4
+0xBD    U+FEE5
+0xBD    U+FEE6
+0xBE    U+FEE8
+0xBF    U+FEE9
+0xBF    U+FEEA
+0xC1    U+FF21
+0xC2    U+FF22
+0xC3    U+FF23
+0xC4    U+FF24
+0xC5    U+FF25
+0xC6    U+FF26
+0xC7    U+FF27
+0xC8    U+FF28
+0xC9    U+FF29
+0xCF    U+FEED
+0xCF    U+FEEE
+0xD1    U+FF2A
+0xD2    U+FF2B
+0xD3    U+FF2C
+0xD4    U+FF2D
+0xD5    U+FF2E
+0xD6    U+FF2F
+0xD7    U+FF30
+0xD8    U+FF31
+0xD9    U+FF32
+0xDA    U+FEEF
+0xDC    U+FEF1
+0xDE    U+FEF4
+0xE2    U+FF33
+0xE3    U+FF34
+0xE4    U+FF35
+0xE5    U+FF36
+0xE6    U+FF37
+0xE7    U+FF38
+0xE8    U+FF39
+0xE9    U+FF3A
+0xF0    U+FF10
+0xF1    U+FF11
+0xF2    U+FF12
+0xF3    U+FF13
+0xF4    U+FF14
+0xF5    U+FF15
+0xF6    U+FF16
+0xF7    U+FF17
+0xF8    U+FF18
+0xF9    U+FF19
--- a/jdk/make/tools/CharsetMapping/IBM420.map	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/tools/CharsetMapping/IBM420.map	Tue Aug 18 19:53:43 2009 -0700
@@ -1,257 +1,253 @@
-#Generated from IBM420.java
-0x00	U+0000
-0x01	U+0001
-0x02	U+0002
-0x03	U+0003
-0x04	U+009c
-0x05	U+0009
-0x06	U+0086
-0x07	U+007f
-0x08	U+0097
-0x09	U+008d
-0x0a	U+008e
-0x0b	U+000b
-0x0c	U+000c
-0x0d	U+000d
-0x0e	U+000e
-0x0f	U+000f
-0x10	U+0010
-0x11	U+0011
-0x12	U+0012
-0x13	U+0013
-0x14	U+009d
-0x15	U+000a
-0x16	U+0008
-0x17	U+0087
-0x18	U+0018
-0x19	U+0019
-0x1a	U+0092
-0x1b	U+008f
-0x1c	U+001c
-0x1d	U+001d
-0x1e	U+001e
-0x1f	U+001f
-0x20	U+0080
-0x21	U+0081
-0x22	U+0082
-0x23	U+0083
-0x24	U+0084
-0x25	U+000a
-0x26	U+0017
-0x27	U+001b
-0x28	U+0088
-0x29	U+0089
-0x2a	U+008a
-0x2b	U+008b
-0x2c	U+008c
-0x2d	U+0005
-0x2e	U+0006
-0x2f	U+0007
-0x30	U+0090
-0x31	U+0091
-0x32	U+0016
-0x33	U+0093
-0x34	U+0094
-0x35	U+0095
-0x36	U+0096
-0x37	U+0004
-0x38	U+0098
-0x39	U+0099
-0x3a	U+009a
-0x3b	U+009b
-0x3c	U+0014
-0x3d	U+0015
-0x3e	U+009e
-0x3f	U+001a
-0x40	U+0020
-0x41	U+00a0
-0x42	U+fe7c
-0x43	U+fe7d
-0x44	U+0640
-0x45	U+f8fc
-0x46	U+fe80
-0x47	U+fe81
-0x48	U+fe82
-0x49	U+fe83
-0x4a	U+00a2
-0x4b	U+002e
-0x4c	U+003c
-0x4d	U+0028
-0x4e	U+002b
-0x4f	U+007c
-0x50	U+0026
-0x51	U+fe84
-0x52	U+fe85
-0x53	U+fffd
-0x54	U+fffd
-0x55	U+fe8b
-0x56	U+fe8d
-0x57	U+fe8e
-0x58	U+fe8f
-0x59	U+fe91
-0x5a	U+0021
-0x5b	U+0024
-0x5c	U+002a
-0x5d	U+0029
-0x5e	U+003b
-0x5f	U+00ac
-0x60	U+002d
-0x61	U+002f
-0x62	U+fe93
-0x63	U+fe95
-0x64	U+fe97
-0x65	U+fe99
-0x66	U+fe9b
-0x67	U+fe9d
-0x68	U+fe9f
-0x69	U+fea1
-0x6a	U+00a6
-0x6b	U+002c
-0x6c	U+0025
-0x6d	U+005f
-0x6e	U+003e
-0x6f	U+003f
-0x70	U+fea3
-0x71	U+fea5
-0x72	U+fea7
-0x73	U+fea9
-0x74	U+feab
-0x75	U+fead
-0x76	U+feaf
-0x77	U+f8f6
-0x78	U+feb3
-0x79	U+060c
-0x7a	U+003a
-0x7b	U+0023
-0x7c	U+0040
-0x7d	U+0027
-0x7e	U+003d
-0x7f	U+0022
-0x80	U+f8f5
-0x81	U+0061
-0x82	U+0062
-0x83	U+0063
-0x84	U+0064
-0x85	U+0065
-0x86	U+0066
-0x87	U+0067
-0x88	U+0068
-0x89	U+0069
-0x8a	U+feb7
-0x8b	U+f8f4
-0x8c	U+febb
-0x8d	U+f8f7
-0x8e	U+febf
-0x8f	U+fec3
-0x90	U+fec7
-0x91	U+006a
-0x92	U+006b
-0x93	U+006c
-0x94	U+006d
-0x95	U+006e
-0x96	U+006f
-0x97	U+0070
-0x98	U+0071
-0x99	U+0072
-0x9a	U+fec9
-0x9b	U+feca
-0x9c	U+fecb
-0x9d	U+fecc
-0x9e	U+fecd
-0x9f	U+fece
-0xa0	U+fecf
-0xa1	U+00f7
-0xa2	U+0073
-0xa3	U+0074
-0xa4	U+0075
-0xa5	U+0076
-0xa6	U+0077
-0xa7	U+0078
-0xa8	U+0079
-0xa9	U+007a
-0xaa	U+fed0
-0xab	U+fed1
-0xac	U+fed3
-0xad	U+fed5
-0xae	U+fed7
-0xaf	U+fed9
-0xb0	U+fedb
-0xb1	U+fedd
-0xb2	U+fef5
-0xb3	U+fef6
-0xb4	U+fef7
-0xb5	U+fef8
-0xb6	U+fffd
-0xb7	U+fffd
-0xb8	U+fefb
-0xb9	U+fefc
-0xba	U+fedf
-0xbb	U+fee1
-0xbc	U+fee3
-0xbd	U+fee5
-0xbe	U+fee7
-0xbf	U+fee9
-0xc0	U+061b
-0xc1	U+0041
-0xc2	U+0042
-0xc3	U+0043
-0xc4	U+0044
-0xc5	U+0045
-0xc6	U+0046
-0xc7	U+0047
-0xc8	U+0048
-0xc9	U+0049
-0xca	U+00ad
-0xcb	U+feeb
-0xcc	U+fffd
-0xcd	U+feec
-0xce	U+fffd
-0xcf	U+feed
-0xd0	U+061f
-0xd1	U+004a
-0xd2	U+004b
-0xd3	U+004c
-0xd4	U+004d
-0xd5	U+004e
-0xd6	U+004f
-0xd7	U+0050
-0xd8	U+0051
-0xd9	U+0052
-0xda	U+feef
-0xdb	U+fef0
-0xdc	U+fef1
-0xdd	U+fef2
-0xde	U+fef3
-0xdf	U+0660
-0xe0	U+00d7
-0xe1	U+2007
-0xe2	U+0053
-0xe3	U+0054
-0xe4	U+0055
-0xe5	U+0056
-0xe6	U+0057
-0xe7	U+0058
-0xe8	U+0059
-0xe9	U+005a
-0xea	U+0661
-0xeb	U+0662
-0xec	U+fffd
-0xed	U+0663
-0xee	U+0664
-0xef	U+0665
-0xf0	U+0030
-0xf1	U+0031
-0xf2	U+0032
-0xf3	U+0033
-0xf4	U+0034
-0xf5	U+0035
-0xf6	U+0036
-0xf7	U+0037
-0xf8	U+0038
-0xf9	U+0039
-0xfa	U+fffd
-0xfb	U+0666
-0xfc	U+0667
-0xfd	U+0668
-0xfe	U+0669
-0xff	U+009f
+#
+#  Frm IBMCDC datatable 01A434B0.TXMAP110
+#
+#  Changed
+#  0x15    U+0085  ->  0x15    U+000a
+#
+0x00    U+0000
+0x01    U+0001
+0x02    U+0002
+0x03    U+0003
+0x04    U+009C
+0x05    U+0009
+0x06    U+0086
+0x07    U+007F
+0x08    U+0097
+0x09    U+008D
+0x0A    U+008E
+0x0B    U+000B
+0x0C    U+000C
+0x0D    U+000D
+0x0E    U+000E
+0x0F    U+000F
+0x10    U+0010
+0x11    U+0011
+0x12    U+0012
+0x13    U+0013
+0x14    U+009D
+0x15    U+000A
+0x16    U+0008
+0x17    U+0087
+0x18    U+0018
+0x19    U+0019
+0x1A    U+0092
+0x1B    U+008F
+0x1C    U+001C
+0x1D    U+001D
+0x1E    U+001E
+0x1F    U+001F
+0x20    U+0080
+0x21    U+0081
+0x22    U+0082
+0x23    U+0083
+0x24    U+0084
+0x25    U+000A
+0x26    U+0017
+0x27    U+001B
+0x28    U+0088
+0x29    U+0089
+0x2A    U+008A
+0x2B    U+008B
+0x2C    U+008C
+0x2D    U+0005
+0x2E    U+0006
+0x2F    U+0007
+0x30    U+0090
+0x31    U+0091
+0x32    U+0016
+0x33    U+0093
+0x34    U+0094
+0x35    U+0095
+0x36    U+0096
+0x37    U+0004
+0x38    U+0098
+0x39    U+0099
+0x3A    U+009A
+0x3B    U+009B
+0x3C    U+0014
+0x3D    U+0015
+0x3E    U+009E
+0x3F    U+001A
+0x40    U+0020
+0x41    U+00A0
+0x42    U+0651
+0x43    U+FE7D
+0x44    U+0640
+0x45    U+200B
+0x46    U+0621
+0x47    U+0622
+0x48    U+FE82
+0x49    U+0623
+0x4A    U+00A2
+0x4B    U+002E
+0x4C    U+003C
+0x4D    U+0028
+0x4E    U+002B
+0x4F    U+007C
+0x50    U+0026
+0x51    U+FE84
+0x52    U+0624
+0x55    U+0626
+0x56    U+0627
+0x57    U+FE8E
+0x58    U+0628
+0x59    U+FE91
+0x5A    U+0021
+0x5B    U+0024
+0x5C    U+002A
+0x5D    U+0029
+0x5E    U+003B
+0x5F    U+00AC
+0x60    U+002D
+0x61    U+002F
+0x62    U+0629
+0x63    U+062A
+0x64    U+FE97
+0x65    U+062B
+0x66    U+FE9B
+0x67    U+062C
+0x68    U+FE9F
+0x69    U+062D
+0x6A    U+00A6
+0x6B    U+002C
+0x6C    U+0025
+0x6D    U+005F
+0x6E    U+003E
+0x6F    U+003F
+0x70    U+FEA3
+0x71    U+062E
+0x72    U+FEA7
+0x73    U+062F
+0x74    U+0630
+0x75    U+0631
+0x76    U+0632
+0x77    U+0633
+0x78    U+FEB3
+0x79    U+060C
+0x7A    U+003A
+0x7B    U+0023
+0x7C    U+0040
+0x7D    U+0027
+0x7E    U+003D
+0x7F    U+0022
+0x80    U+0634
+0x81    U+0061
+0x82    U+0062
+0x83    U+0063
+0x84    U+0064
+0x85    U+0065
+0x86    U+0066
+0x87    U+0067
+0x88    U+0068
+0x89    U+0069
+0x8A    U+FEB7
+0x8B    U+0635
+0x8C    U+FEBB
+0x8D    U+0636
+0x8E    U+FEBF
+0x8F    U+0637
+0x90    U+0638
+0x91    U+006A
+0x92    U+006B
+0x93    U+006C
+0x94    U+006D
+0x95    U+006E
+0x96    U+006F
+0x97    U+0070
+0x98    U+0071
+0x99    U+0072
+0x9A    U+0639
+0x9B    U+FECA
+0x9C    U+FECB
+0x9D    U+FECC
+0x9E    U+063A
+0x9F    U+FECE
+0xA0    U+FECF
+0xA1    U+00F7
+0xA2    U+0073
+0xA3    U+0074
+0xA4    U+0075
+0xA5    U+0076
+0xA6    U+0077
+0xA7    U+0078
+0xA8    U+0079
+0xA9    U+007A
+0xAA    U+FED0
+0xAB    U+0641
+0xAC    U+FED3
+0xAD    U+0642
+0xAE    U+FED7
+0xAF    U+0643
+0xB0    U+FEDB
+0xB1    U+0644
+0xB2    U+FEF5
+0xB3    U+FEF6
+0xB4    U+FEF7
+0xB5    U+FEF8
+0xB8    U+FEFB
+0xB9    U+FEFC
+0xBA    U+FEDF
+0xBB    U+0645
+0xBC    U+FEE3
+0xBD    U+0646
+0xBE    U+FEE7
+0xBF    U+0647
+0xC0    U+061B
+0xC1    U+0041
+0xC2    U+0042
+0xC3    U+0043
+0xC4    U+0044
+0xC5    U+0045
+0xC6    U+0046
+0xC7    U+0047
+0xC8    U+0048
+0xC9    U+0049
+0xCA    U+00AD
+0xCB    U+FEEB
+0xCD    U+FEEC
+0xCF    U+0648
+0xD0    U+061F
+0xD1    U+004A
+0xD2    U+004B
+0xD3    U+004C
+0xD4    U+004D
+0xD5    U+004E
+0xD6    U+004F
+0xD7    U+0050
+0xD8    U+0051
+0xD9    U+0052
+0xDA    U+0649
+0xDB    U+FEF0
+0xDC    U+064A
+0xDD    U+FEF2
+0xDE    U+FEF3
+0xDF    U+0660
+0xE0    U+00D7
+0xE2    U+0053
+0xE3    U+0054
+0xE4    U+0055
+0xE5    U+0056
+0xE6    U+0057
+0xE7    U+0058
+0xE8    U+0059
+0xE9    U+005A
+0xEA    U+0661
+0xEB    U+0662
+0xED    U+0663
+0xEE    U+0664
+0xEF    U+0665
+0xF0    U+0030
+0xF1    U+0031
+0xF2    U+0032
+0xF3    U+0033
+0xF4    U+0034
+0xF5    U+0035
+0xF6    U+0036
+0xF7    U+0037
+0xF8    U+0038
+0xF9    U+0039
+0xFB    U+0666
+0xFC    U+0667
+0xFD    U+0668
+0xFE    U+0669
+0xFF    U+009F
--- a/jdk/make/tools/CharsetMapping/IBM420.nr	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/tools/CharsetMapping/IBM420.nr	Tue Aug 18 19:53:43 2009 -0700
@@ -1,1 +1,1 @@
-0x25	U+000a
+0x25    U+000a
--- a/jdk/make/tools/src/build/tools/charsetmapping/GenerateSBCS.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/make/tools/src/build/tools/charsetmapping/GenerateSBCS.java	Tue Aug 18 19:53:43 2009 -0700
@@ -26,6 +26,7 @@
 package build.tools.charsetmapping;
 
 import java.io.*;
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Scanner;
 import java.util.Formatter;
@@ -54,33 +55,19 @@
             String pkgName  = fields[4];
             System.out.printf("%s,%s,%s,%b,%s%n", clzName, csName, hisName, isASCII, pkgName);
 
-            StringBuilder b2c = new StringBuilder();
-            int c2bLen = genB2C(
-                new FileInputStream(new File(args[0], clzName+".map")), b2c);
-
-            String b2cNR = null;
-            File nrF = new File(args[0], clzName+".nr");
-            if (nrF.exists()) {
-                b2cNR = genNR(new FileInputStream(nrF));
-            }
-
-            String c2bNR = null;
-            File c2bF = new File(args[0], clzName+".c2b");
-            if (c2bF.exists()) {
-                c2bNR = genC2BNR(new FileInputStream(c2bF));
-            }
-
-            genSBCSClass(args[0], args[1], "SingleByte-X.java",
-                         clzName, csName, hisName, pkgName, isASCII,
-                         b2c.toString(), b2cNR, c2bNR, c2bLen);
+            genClass(args[0], args[1], "SingleByte-X.java",
+                     clzName, csName, hisName, pkgName, isASCII);
         }
     }
 
     private static void toString(char[] sb, int off, int end,
-                                 Formatter out, String closure) {
+                                 Formatter out, String closure,
+                                 boolean comment) {
         while (off < end) {
             out.format("        \"");
             for (int j = 0; j < 8; j++) {
+                if (off == end)
+                    break;
                 char c = sb[off++];
                 switch (c) {
                 case '\b':
@@ -103,101 +90,124 @@
                     out.format("\\u%04X", c & 0xffff);
                 }
             }
-            if (off == end)
-               out.format("\" %s      // 0x%02x - 0x%02x%n", closure, off-8, off-1);
-            else
-               out.format("\" +      // 0x%02x - 0x%02x%n", off-8, off-1);
+            if (comment) {
+                if (off == end)
+                    out.format("\" %s      // 0x%02x - 0x%02x%n",
+                               closure, off-8, off-1);
+                else
+                    out.format("\" +      // 0x%02x - 0x%02x%n",
+                               off-8, off-1);
+            } else {
+                if (off == end)
+                    out.format("\"%s%n", closure);
+                else
+                    out.format("\" +%n");
+            }
         }
     }
 
     static Pattern sbmap = Pattern.compile("0x(\\p{XDigit}++)\\s++U\\+(\\p{XDigit}++)(\\s++#.*)?");
-    private static int genB2C(InputStream in, StringBuilder out)
+
+    private static void genClass(String srcDir, String dstDir,
+                                 String template,
+                                 String clzName,
+                                 String csName,
+                                 String hisName,
+                                 String pkgName,
+                                 boolean isASCII)
         throws Exception
     {
-        char[] sb = new char[0x100];
-        int[] indexC2B = new int[0x100];
+        StringBuilder b2cSB = new StringBuilder();
+        StringBuilder b2cNRSB = new StringBuilder();
+        StringBuilder c2bNRSB = new StringBuilder();
 
-        for (int i = 0; i < sb.length; i++)
-            sb[i] = UNMAPPABLE_DECODING;
+        char[] sb = new char[0x100];
+        char[] c2bIndex = new char[0x100];
+        int    c2bOff = 0;
+        Arrays.fill(sb, UNMAPPABLE_DECODING);
+        Arrays.fill(c2bIndex, UNMAPPABLE_DECODING);
 
-        // parse the b2c mapping table
+        // (1)read in .map to parse all b->c entries
+        FileInputStream in = new FileInputStream(
+                                 new File(srcDir, clzName + ".map"));
         Parser p = new Parser(in, sbmap);
         Entry  e = null;
-        int    off = 0;
+
         while ((e = p.next()) != null) {
             sb[e.bs] = (char)e.cp;
-            if (indexC2B[e.cp>>8] == 0) {
-                off += 0x100;
-                indexC2B[e.cp>>8] = 1;
+            if (c2bIndex[e.cp>>8] == UNMAPPABLE_DECODING) {
+                c2bOff += 0x100;
+                c2bIndex[e.cp>>8] = 1;
             }
         }
 
-        Formatter fm = new Formatter(out);
+        Formatter fm = new Formatter(b2cSB);
         fm.format("%n");
 
         // vm -server shows cc[byte + 128] access is much faster than
         // cc[byte&0xff] so we output the upper segment first
-        toString(sb, 0x80, 0x100, fm, "+");
-        toString(sb, 0x00, 0x80,  fm, ";");
-
+        toString(sb, 0x80, 0x100, fm, "+", true);
+        toString(sb, 0x00, 0x80,  fm, ";", true);
         fm.close();
-        return off;
-    }
 
-    // generate non-roundtrip entries from xxx.nr file
-    private static String genNR(InputStream in) throws Exception
-    {
-        StringBuilder sb = new StringBuilder();
-        Formatter fm = new Formatter(sb);
-        Parser p = new Parser(in, sbmap);
-        Entry  e = null;
-        fm.format("// remove non-roundtrip entries%n");
-        fm.format("        b2cMap = b2cTable.toCharArray();%n");
-        while ((e = p.next()) != null) {
-            fm.format("        b2cMap[%d] = UNMAPPABLE_DECODING;%n",
-                      (e.bs>=0x80)?(e.bs-0x80):(e.bs+0x80));
-        }
-        fm.close();
-        return sb.toString();
-    }
+        // (2)now the .nr file which includes "b->c" non-roundtrip entries
+        File f = new File(srcDir, clzName + ".nr");
+        if (f.exists()) {
+            in = new FileInputStream(f);
+            fm = new Formatter(b2cNRSB);
+            p = new Parser(in, sbmap);
+            e = null;
 
-    // generate c2b only entries from xxx.c2b file
-    private static String genC2BNR(InputStream in) throws Exception
-    {
-        StringBuilder sb = new StringBuilder();
-        Formatter fm = new Formatter(sb);
-        Parser p = new Parser(in, sbmap);
-        ArrayList<Entry> es = new ArrayList<Entry>();
-        Entry  e = null;
-        while ((e = p.next()) != null) {
-            es.add(e);
+            fm.format("// remove non-roundtrip entries%n");
+            fm.format("        b2cMap = b2cTable.toCharArray();%n");
+            while ((e = p.next()) != null) {
+                fm.format("        b2cMap[%d] = UNMAPPABLE_DECODING;%n",
+                          (e.bs>=0x80)?(e.bs-0x80):(e.bs+0x80));
+            }
+            fm.close();
         }
 
-        fm.format("// non-roundtrip c2b only entries%n");
-        fm.format("        c2bNR = new char[%d];%n", es.size() * 2);
-        int i = 0;
-        for (Entry entry: es) {
-            fm.format("        c2bNR[%d] = 0x%x; c2bNR[%d] = 0x%x;%n",
-                      i++, entry.bs, i++, entry.cp);
+        // (3)finally the .c2b file which includes c->b non-roundtrip entries
+        f = new File(srcDir, clzName + ".c2b");
+        if (f.exists()) {
+            in = new FileInputStream(f);
+            fm = new Formatter(c2bNRSB);
+            p = new Parser(in, sbmap);
+            e = null;
+            ArrayList<Entry> es = new ArrayList<Entry>();
+            while ((e = p.next()) != null) {
+                if (c2bIndex[e.cp>>8] == UNMAPPABLE_DECODING) {
+                    c2bOff += 0x100;
+                    c2bIndex[e.cp>>8] = 1;
+                }
+                es.add(e);
+            }
+            fm.format("// non-roundtrip c2b only entries%n");
+            if (es.size() < 100) {
+                fm.format("        c2bNR = new char[%d];%n", es.size() * 2);
+                int i = 0;
+                for (Entry entry: es) {
+                    fm.format("        c2bNR[%d] = 0x%x; c2bNR[%d] = 0x%x;%n",
+                              i++, entry.bs, i++, entry.cp);
+                }
+            } else {
+                char[] cc = new char[es.size() * 2];
+                int i = 0;
+                for (Entry entry: es) {
+                    cc[i++] = (char)entry.bs;
+                    cc[i++] = (char)entry.cp;
+                }
+                fm.format("        c2bNR = (%n");
+                toString(cc, 0, i,  fm, ").toCharArray();", false);
+            }
+            fm.close();
         }
-        fm.close();
-        return sb.toString();
-    }
 
-    private static void genSBCSClass(String srcDir,
-                                     String dstDir,
-                                     String template,
-                                     String clzName,
-                                     String csName,
-                                     String hisName,
-                                     String pkgName,
-                                     boolean isASCII,
-                                     String b2c,
-                                     String b2cNR,
-                                     String c2bNR,
-                                     int    c2blen)
-        throws Exception
-    {
+        // (4)it's time to generate the source file
+        String b2c = b2cSB.toString();
+        String b2cNR = b2cNRSB.toString();
+        String c2bNR = c2bNRSB.toString();
+
         Scanner s = new Scanner(new File(srcDir, template));
         PrintStream out = new PrintStream(new FileOutputStream(
                               new File(dstDir, clzName + ".java")));
@@ -239,16 +249,16 @@
                 line = line.replace("$B2CTABLE$", b2c);
             }
             if (line.indexOf("$C2BLENGTH$") != -1) {
-                line = line.replace("$C2BLENGTH$", "0x" + Integer.toString(c2blen, 16));
+                line = line.replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16));
             }
             if (line.indexOf("$NONROUNDTRIP_B2C$") != -1) {
-                if (b2cNR == null)
+                if (b2cNR.length() == 0)
                     continue;
                 line = line.replace("$NONROUNDTRIP_B2C$", b2cNR);
             }
 
             if (line.indexOf("$NONROUNDTRIP_C2B$") != -1) {
-                if (c2bNR == null)
+                if (c2bNR.length() == 0)
                     continue;
                 line = line.replace("$NONROUNDTRIP_C2B$", c2bNR);
             }
--- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -51,7 +51,7 @@
               entensions,
               mimeType,
               "com.sun.imageio.plugins.bmp.BMPImageReader",
-              STANDARD_INPUT_TYPE,
+              new Class[] { ImageInputStream.class },
               writerSpiNames,
               false,
               null, null, null, null,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -32,6 +32,7 @@
 import javax.imageio.spi.ImageWriterSpi;
 import javax.imageio.spi.ServiceRegistry;
 import javax.imageio.spi.IIORegistry;
+import javax.imageio.stream.ImageOutputStream;
 import javax.imageio.ImageWriter;
 import javax.imageio.ImageTypeSpecifier;
 import javax.imageio.IIOException;
@@ -55,7 +56,7 @@
               entensions,
               mimeType,
               "com.sun.imageio.plugins.bmp.BMPImageWriter",
-              STANDARD_OUTPUT_TYPE,
+              new Class[] { ImageOutputStream.class },
               readerSpiNames,
               false,
               null, null, null, null,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -60,7 +60,7 @@
               suffixes,
               MIMETypes,
               readerClassName,
-              STANDARD_INPUT_TYPE,
+              new Class[] { ImageInputStream.class },
               writerSpiNames,
               true,
               GIFStreamMetadata.nativeMetadataFormatName,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -31,6 +31,7 @@
 import javax.imageio.ImageTypeSpecifier;
 import javax.imageio.ImageWriter;
 import javax.imageio.spi.ImageWriterSpi;
+import javax.imageio.stream.ImageOutputStream;
 import com.sun.imageio.plugins.common.PaletteBuilder;
 
 public class GIFImageWriterSpi extends ImageWriterSpi {
@@ -59,7 +60,7 @@
               suffixes,
               MIMETypes,
               writerClassName,
-              STANDARD_OUTPUT_TYPE,
+              new Class[] { ImageOutputStream.class },
               readerSpiNames,
               true,
               GIFWritableStreamMetadata.NATIVE_FORMAT_NAME,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -46,7 +46,7 @@
               JPEG.suffixes,
               JPEG.MIMETypes,
               "com.sun.imageio.plugins.jpeg.JPEGImageReader",
-              STANDARD_INPUT_TYPE,
+              new Class[] { ImageInputStream.class },
               writerSpiNames,
               true,
               JPEG.nativeStreamMetadataFormatName,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -28,6 +28,7 @@
 import javax.imageio.spi.ImageWriterSpi;
 import javax.imageio.spi.ServiceRegistry;
 import javax.imageio.spi.IIORegistry;
+import javax.imageio.stream.ImageOutputStream;
 import javax.imageio.ImageWriter;
 import javax.imageio.ImageTypeSpecifier;
 import javax.imageio.IIOException;
@@ -49,7 +50,7 @@
               JPEG.suffixes,
               JPEG.MIMETypes,
               "com.sun.imageio.plugins.jpeg.JPEGImageWriter",
-              STANDARD_OUTPUT_TYPE,
+              new Class[] { ImageOutputStream.class },
               readerSpiNames,
               true,
               JPEG.nativeStreamMetadataFormatName,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -60,7 +60,7 @@
               suffixes,
               MIMETypes,
               readerClassName,
-              STANDARD_INPUT_TYPE,
+              new Class[] { ImageInputStream.class },
               writerSpiNames,
               false,
               null, null,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -34,6 +34,7 @@
 import javax.imageio.metadata.IIOMetadataFormat;
 import javax.imageio.metadata.IIOMetadataFormatImpl;
 import javax.imageio.spi.ImageWriterSpi;
+import javax.imageio.stream.ImageOutputStream;
 
 public class PNGImageWriterSpi extends ImageWriterSpi {
 
@@ -61,7 +62,7 @@
                 suffixes,
                 MIMETypes,
                 writerClassName,
-                STANDARD_OUTPUT_TYPE,
+                new Class[] { ImageOutputStream.class },
                 readerSpiNames,
                 false,
                 null, null,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -55,7 +55,7 @@
               entensions,
               mimeType,
               "com.sun.imageio.plugins.wbmp.WBMPImageReader",
-              STANDARD_INPUT_TYPE,
+              new Class[] { ImageInputStream.class },
               writerSpiNames,
               true,
               null, null, null, null,
--- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -28,6 +28,7 @@
 import javax.imageio.spi.ImageWriterSpi;
 import javax.imageio.spi.ServiceRegistry;
 import javax.imageio.spi.IIORegistry;
+import javax.imageio.stream.ImageOutputStream;
 import javax.imageio.ImageWriter;
 import javax.imageio.ImageTypeSpecifier;
 import javax.imageio.IIOException;
@@ -54,7 +55,7 @@
               entensions,
               mimeType,
               "com.sun.imageio.plugins.wbmp.WBMPImageWriter",
-              STANDARD_OUTPUT_TYPE,
+              new Class[] { ImageOutputStream.class },
               readerSpiNames,
               true,
               null, null, null, null,
--- a/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java	Tue Aug 18 19:53:43 2009 -0700
@@ -43,35 +43,35 @@
  */
 public class StreamCloser {
 
-    private static WeakHashMap<ImageInputStream, Object> toCloseQueue;
+    private static WeakHashMap<CloseAction, Object> toCloseQueue;
     private static Thread streamCloser;
 
-    public static void addToQueue(ImageInputStream iis) {
+    public static void addToQueue(CloseAction ca) {
         synchronized (StreamCloser.class) {
             if (toCloseQueue == null) {
                 toCloseQueue =
-                    new WeakHashMap<ImageInputStream, Object>();
+                    new WeakHashMap<CloseAction, Object>();
             }
 
-            toCloseQueue.put(iis, null);
+            toCloseQueue.put(ca, null);
 
             if (streamCloser == null) {
                 final Runnable streamCloserRunnable = new Runnable() {
                     public void run() {
                         if (toCloseQueue != null) {
                             synchronized (StreamCloser.class) {
-                                Set<ImageInputStream> set =
+                                Set<CloseAction> set =
                                     toCloseQueue.keySet();
                                 // Make a copy of the set in order to avoid
                                 // concurrent modification (the is.close()
                                 // will in turn call removeFromQueue())
-                                ImageInputStream[] streams =
-                                    new ImageInputStream[set.size()];
-                                streams = set.toArray(streams);
-                                for (ImageInputStream is : streams) {
-                                    if (is != null) {
+                                CloseAction[] actions =
+                                    new CloseAction[set.size()];
+                                actions = set.toArray(actions);
+                                for (CloseAction ca : actions) {
+                                    if (ca != null) {
                                         try {
-                                            is.close();
+                                            ca.performAction();
                                         } catch (IOException e) {
                                         }
                                     }
@@ -106,10 +106,28 @@
         }
     }
 
-    public static void removeFromQueue(ImageInputStream iis) {
+    public static void removeFromQueue(CloseAction ca) {
         synchronized (StreamCloser.class) {
             if (toCloseQueue != null) {
-                toCloseQueue.remove(iis);
+                toCloseQueue.remove(ca);
+            }
+        }
+    }
+
+    public static CloseAction createCloseAction(ImageInputStream iis) {
+        return new CloseAction(iis);
+    }
+
+    public static final class CloseAction {
+        private ImageInputStream iis;
+
+        private CloseAction(ImageInputStream iis) {
+            this.iis = iis;
+        }
+
+        public void performAction() throws IOException {
+            if (iis != null) {
+                iis.close();
             }
         }
     }
--- a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-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
@@ -922,7 +922,7 @@
 
     //---------- Debugging
 
-    public static boolean debug = false;
+    private static final boolean debug = false;
 
     private static final void dprint(String msg) {
         if (debug) {
@@ -972,14 +972,11 @@
     }
 
     /*
-     * ctx will be closed when no longer needed by the enumeration.
+     * ctx will be set to null when no longer needed by the enumeration.
      */
-    public void close () {
+    public void close() {
         nodes = null;
-        if (ctx != null) {
-            ctx.close();
-            ctx = null;
-        }
+        ctx = null;
     }
 
     public boolean hasMore() {
--- a/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-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
@@ -41,6 +41,15 @@
 import javax.sound.midi.spi.SoundbankReader;
 import javax.sound.midi.spi.MidiDeviceProvider;
 
+import javax.sound.midi.Receiver;
+import javax.sound.midi.Sequencer;
+import javax.sound.midi.Synthesizer;
+import javax.sound.midi.Transmitter;
+import javax.sound.sampled.Clip;
+import javax.sound.sampled.Port;
+import javax.sound.sampled.SourceDataLine;
+import javax.sound.sampled.TargetDataLine;
+
 
 /**
  * JDK13Services uses the Service class in JDK 1.3
@@ -186,6 +195,16 @@
         If the property is not set, null is returned.
      */
     private static synchronized String getDefaultProvider(Class typeClass) {
+        if (!SourceDataLine.class.equals(typeClass)
+                && !TargetDataLine.class.equals(typeClass)
+                && !Clip.class.equals(typeClass)
+                && !Port.class.equals(typeClass)
+                && !Receiver.class.equals(typeClass)
+                && !Transmitter.class.equals(typeClass)
+                && !Synthesizer.class.equals(typeClass)
+                && !Sequencer.class.equals(typeClass)) {
+            return null;
+        }
         String value;
         String propertyName = typeClass.getName();
         value = JSSecurityManager.getProperty(propertyName);
--- a/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-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
@@ -283,28 +283,37 @@
 
 
     static List getProviders(final Class providerClass) {
-        PrivilegedAction action = new PrivilegedAction() {
-                public Object run() {
-                    List p = new ArrayList();
-                    Iterator ps = Service.providers(providerClass);
-                    while (ps.hasNext()) {
-                        try {
-                            Object provider = ps.next();
-                            if (providerClass.isInstance(provider)) {
-                                // $$mp 2003-08-22
-                                // Always adding at the beginning reverses the
-                                // order of the providers. So we no longer have
-                                // to do this in AudioSystem and MidiSystem.
-                                p.add(0, provider);
-                            }
-                        } catch (Throwable t) {
-                            //$$fb 2002-11-07: do not fail on SPI not found
-                            if (Printer.err) t.printStackTrace();
-                        }                                                                  }
-                    return p;
+        List p = new ArrayList();
+        // Service.providers(Class) just creates "lazy" iterator instance,
+        // so it doesn't require do be called from privileged section
+        final Iterator ps = Service.providers(providerClass);
+
+        // the iterator's hasNext() method looks through classpath for
+        // the provider class names, so it requires read permissions
+        PrivilegedAction<Boolean> hasNextAction = new PrivilegedAction<Boolean>() {
+            public Boolean run() {
+                return ps.hasNext();
+            }
+        };
+
+        while (AccessController.doPrivileged(hasNextAction)) {
+            try {
+                // the iterator's next() method creates instances of the
+                // providers and it should be called in the current security
+                // context
+                Object provider = ps.next();
+                if (providerClass.isInstance(provider)) {
+                    // $$mp 2003-08-22
+                    // Always adding at the beginning reverses the
+                    // order of the providers. So we no longer have
+                    // to do this in AudioSystem and MidiSystem.
+                    p.add(0, provider);
                 }
-            };
-        List providers = (List) AccessController.doPrivileged(action);
-        return providers;
+            } catch (Throwable t) {
+                //$$fb 2002-11-07: do not fail on SPI not found
+                if (Printer.err) t.printStackTrace();
+            }
+        }
+        return p;
     }
 }
--- a/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileWriter.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileWriter.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1999-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
@@ -82,7 +82,7 @@
     /**
      * MIDI parser types
      */
-    public static final int types[] = {
+    private static final int types[] = {
         MIDI_TYPE_0,
         MIDI_TYPE_1
     };
--- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java	Tue Aug 18 19:53:43 2009 -0700
@@ -60,8 +60,14 @@
     */
    public abstract String engineGetURI();
 
+   /**
+    * Returns the output length of the hash/digest.
+    */
+   abstract int getDigestLength();
+
    /** Field _macAlgorithm */
    private Mac _macAlgorithm = null;
+   private boolean _HMACOutputLengthSet = false;
 
    /** Field _HMACOutputLength */
    int _HMACOutputLength = 0;
@@ -100,7 +106,9 @@
    }
 
    public void reset() {
-           _HMACOutputLength=0;
+       _HMACOutputLength=0;
+       _HMACOutputLengthSet = false;
+       _macAlgorithm.reset();
    }
 
    /**
@@ -115,14 +123,16 @@
            throws XMLSignatureException {
 
       try {
-         byte[] completeResult = this._macAlgorithm.doFinal();
-
-         if ((this._HMACOutputLength == 0) || (this._HMACOutputLength >= 160)) {
+         if (this._HMACOutputLengthSet && this._HMACOutputLength < getDigestLength()) {
+            if (log.isLoggable(java.util.logging.Level.FINE)) {
+                log.log(java.util.logging.Level.FINE,
+                    "HMACOutputLength must not be less than " + getDigestLength());
+            }
+            throw new XMLSignatureException("errorMessages.XMLSignatureException");
+         } else {
+            byte[] completeResult = this._macAlgorithm.doFinal();
             return MessageDigestAlgorithm.isEqual(completeResult, signature);
          }
-         byte[] stripped = IntegrityHmac.reduceBitLength(completeResult,
-                                 this._HMACOutputLength);
-         return MessageDigestAlgorithm.isEqual(stripped, signature);
       } catch (IllegalStateException ex) {
          throw new XMLSignatureException("empty", ex);
       }
@@ -176,14 +186,15 @@
    protected byte[] engineSign() throws XMLSignatureException {
 
       try {
-         byte[] completeResult = this._macAlgorithm.doFinal();
-
-         if ((this._HMACOutputLength == 0) || (this._HMACOutputLength >= 160)) {
-            return completeResult;
+         if (this._HMACOutputLengthSet && this._HMACOutputLength < getDigestLength()) {
+            if (log.isLoggable(java.util.logging.Level.FINE)) {
+                log.log(java.util.logging.Level.FINE,
+                    "HMACOutputLength must not be less than " + getDigestLength());
+            }
+            throw new XMLSignatureException("errorMessages.XMLSignatureException");
+         } else {
+            return this._macAlgorithm.doFinal();
          }
-          return IntegrityHmac.reduceBitLength(completeResult,
-                                                 this._HMACOutputLength);
-
       } catch (IllegalStateException ex) {
          throw new XMLSignatureException("empty", ex);
       }
@@ -361,6 +372,7 @@
     */
    protected void engineSetHMACOutputLength(int HMACOutputLength) {
       this._HMACOutputLength = HMACOutputLength;
+      this._HMACOutputLengthSet = true;
    }
 
    /**
@@ -376,12 +388,13 @@
          throw new IllegalArgumentException("element null");
       }
 
-             Text hmaclength =XMLUtils.selectDsNodeText(element.getFirstChild(),
-                    Constants._TAG_HMACOUTPUTLENGTH,0);
+      Text hmaclength =XMLUtils.selectDsNodeText(element.getFirstChild(),
+         Constants._TAG_HMACOUTPUTLENGTH,0);
 
-            if (hmaclength != null) {
-               this._HMACOutputLength = Integer.parseInt(hmaclength.getData());
-            }
+      if (hmaclength != null) {
+         this._HMACOutputLength = Integer.parseInt(hmaclength.getData());
+         this._HMACOutputLengthSet = true;
+      }
 
    }
 
@@ -390,14 +403,13 @@
     *
     * @param element
     */
-   public void engineAddContextToElement(Element element)
-           {
+   public void engineAddContextToElement(Element element) {
 
       if (element == null) {
          throw new IllegalArgumentException("null element");
       }
 
-      if (this._HMACOutputLength != 0) {
+      if (this._HMACOutputLengthSet) {
          Document doc = element.getOwnerDocument();
          Element HMElem = XMLUtils.createElementInSignatureSpace(doc,
                              Constants._TAG_HMACOUTPUTLENGTH);
@@ -436,6 +448,10 @@
       public String engineGetURI() {
          return XMLSignature.ALGO_ID_MAC_HMAC_SHA1;
       }
+
+      int getDigestLength() {
+          return 160;
+      }
    }
 
    /**
@@ -463,6 +479,10 @@
       public String engineGetURI() {
          return XMLSignature.ALGO_ID_MAC_HMAC_SHA256;
       }
+
+      int getDigestLength() {
+          return 256;
+      }
    }
 
    /**
@@ -490,6 +510,10 @@
       public String engineGetURI() {
          return XMLSignature.ALGO_ID_MAC_HMAC_SHA384;
       }
+
+      int getDigestLength() {
+          return 384;
+      }
    }
 
    /**
@@ -517,6 +541,10 @@
       public String engineGetURI() {
          return XMLSignature.ALGO_ID_MAC_HMAC_SHA512;
       }
+
+      int getDigestLength() {
+          return 512;
+      }
    }
 
    /**
@@ -544,6 +572,10 @@
       public String engineGetURI() {
          return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160;
       }
+
+      int getDigestLength() {
+          return 160;
+      }
    }
 
    /**
@@ -571,5 +603,9 @@
       public String engineGetURI() {
          return XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5;
       }
+
+      int getDigestLength() {
+          return 128;
+      }
    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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 com.sun.security.jgss;
+
+/**
+ * Kerberos 5 AuthorizationData entry.
+ */
+final public class AuthorizationDataEntry {
+
+    private final int type;
+    private final byte[] data;
+
+    /**
+     * Create an AuthorizationDataEntry object.
+     * @param type the ad-type
+     * @param data the ad-data, a copy of the data will be saved
+     * inside the object.
+     */
+    public AuthorizationDataEntry(int type, byte[] data) {
+        this.type = type;
+        this.data = data.clone();
+    }
+
+    /**
+     * Get the ad-type field.
+     * @return ad-type
+     */
+    public int getType() {
+        return type;
+    }
+
+    /**
+     * Get a copy of the ad-data field.
+     * @return ad-data
+     */
+    public byte[] getData() {
+        return data.clone();
+    }
+
+    public String toString() {
+        return "AuthorizationDataEntry: type="+type+", data=" +
+                data.length + " bytes:\n" +
+                new sun.misc.HexDumpEncoder().encode(data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,102 @@
+/*
+ * 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 com.sun.security.jgss;
+
+import org.ietf.jgss.*;
+
+/**
+ * The extended GSSContext interface for supporting additional
+ * functionalities not defined by {@code org.ietf.jgss.GSSContext},
+ * such as querying context-specific attributes.
+ */
+public interface ExtendedGSSContext extends GSSContext {
+    /**
+     * Return the mechanism-specific attribute associated with {@code type}.
+     * <br><br>
+     * For each supported attribute type, the type for the output are
+     * defined below.
+     * <ol>
+     * <li>{@code KRB5_GET_TKT_FLAGS}:
+     * the returned object is a boolean array for the service ticket flags,
+     * which is long enough to contain all true bits. This means if
+     * the user wants to get the <em>n</em>'th bit but the length of the
+     * returned array is less than <em>n</em>, it is regarded as false.
+     * <li>{@code KRB5_GET_SESSION_KEY}:
+     * the returned object is an instance of {@link java.security.Key},
+     * which has the following properties:
+     *    <ul>
+     *    <li>Algorithm: enctype as a string, where
+     *        enctype is defined in RFC 3961, section 8.
+     *    <li>Format: "RAW"
+     *    <li>Encoded form: the raw key bytes, not in any ASN.1 encoding
+     *    </ul>
+     * <li>{@code KRB5_GET_AUTHZ_DATA}:
+     * the returned object is an array of
+     * {@link com.sun.security.jgss.AuthorizationDataEntry}, or null if the
+     * optional field is missing in the service ticket.
+     * <li>{@code KRB5_GET_AUTHTIME}:
+     * the returned object is a String object in the standard KerberosTime
+     * format defined in RFC 4120 5.2.3
+     * </ol>
+     *
+     * If there is a security manager, an {@link InquireSecContextPermission}
+     * with the name {@code type.mech} must be granted. Otherwise, this could
+     * result in a {@link SecurityException}.<p>
+     *
+     * Example:
+     * <pre>
+     *      GSSContext ctxt = m.createContext(...)
+     *      // Establishing the context
+     *      if (ctxt instanceof ExtendedGSSContext) {
+     *          ExtendedGSSContext ex = (ExtendedGSSContext)ctxt;
+     *          try {
+     *              Key key = (key)ex.inquireSecContext(
+     *                      InquireType.KRB5_GET_SESSION_KEY);
+     *              // read key info
+     *          } catch (GSSException gsse) {
+     *              // deal with exception
+     *          }
+     *      }
+     * </pre>
+     * @param type the type of the attribute requested
+     * @return the attribute, see the method documentation for details.
+     * @throws GSSException containing  the following
+     * major error codes:
+     *   {@link GSSException#BAD_MECH GSSException.BAD_MECH} if the mechanism
+     *   does not support this method,
+     *   {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE} if the
+     *   type specified is not supported,
+     *   {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT} if the
+     *   security context is invalid,
+     *   {@link GSSException#FAILURE GSSException.FAILURE} for other
+     *   unspecified failures.
+     * @throws SecurityException if a security manager exists and a proper
+     *   {@link InquireSecContextPermission} is not granted.
+     * @see InquireSecContextPermission
+     */
+    public Object inquireSecContext(InquireType type)
+            throws GSSException;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/security/jgss/InquireSecContextPermission.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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.
+ */
+
+package com.sun.security.jgss;
+
+import java.security.BasicPermission;
+
+/**
+ * This class is used to protect various attributes of an established
+ * GSS security context that can be accessed using the
+ * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext}
+ * method.
+ *
+ * <p>The target name is the {@link InquireType} allowed.
+ */
+public final class InquireSecContextPermission extends BasicPermission {
+
+    /**
+     * Constructs a new {@code InquireSecContextPermission} object with
+     * the specified name. The name is the symbolic name of the
+     * {@link InquireType} allowed.
+     *
+     * @param name the {@link InquireType} allowed by this
+     * permission. "*" means all {@link InquireType}s are allowed.
+     *
+     * @throws NullPointerException if <code>name</code> is <code>null</code>.
+     * @throws IllegalArgumentException if <code>name</code> is empty.
+     */
+    public InquireSecContextPermission(String name) {
+        super(name);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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.
+ */
+
+package com.sun.security.jgss;
+
+/**
+ * Attribute types that can be specified as an argument of
+ * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext}
+ */
+public enum InquireType {
+    /**
+     * Attribute type for retrieving the session key of an
+     * established Kerberos 5 security context.
+     */
+    KRB5_GET_SESSION_KEY,
+    /**
+     * Attribute type for retrieving the service ticket flags of an
+     * established Kerberos 5 security context.
+     */
+    KRB5_GET_TKT_FLAGS,
+    /**
+     * Attribute type for retrieving the authorization data in the
+     * service ticket of an established Kerberos 5 security context.
+     * Only supported on the acceptor side.
+     */
+    KRB5_GET_AUTHZ_DATA,
+    /**
+     * Attribute type for retrieving the authtime in the service ticket
+     * of an established Kerberos 5 security context.
+     */
+    KRB5_GET_AUTHTIME
+}
--- a/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2003 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-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
@@ -48,10 +48,6 @@
  * @author Rosanna Lee
  */
 public abstract class AbstractSaslImpl {
-    /**
-     * Logger for debug messages
-     */
-    protected static Logger logger;  // set in initLogger(); lazily loads logger
 
     protected boolean completed = false;
     protected boolean privacy = false;
@@ -68,7 +64,6 @@
     protected String myClassName;
 
     protected AbstractSaslImpl(Map props, String className) throws SaslException {
-        initLogger();
         myClassName = className;
 
         // Parse properties  to set desired context options
@@ -325,19 +320,15 @@
         }
     }
 
-    /**
-     * Sets logger field.
-     */
-    private static synchronized void initLogger() {
-        if (logger == null) {
-            logger = Logger.getLogger(SASL_LOGGER_NAME);
-        }
-    }
-
     // ---------------- Constants  -----------------
     private static final String SASL_LOGGER_NAME = "javax.security.sasl";
     protected static final String MAX_SEND_BUF = "javax.security.sasl.sendmaxbuffer";
 
+    /**
+     * Logger for debug messages
+     */
+    protected static final Logger logger = Logger.getLogger(SASL_LOGGER_NAME);
+
     // default 0 (no protection); 1 (integrity only)
     protected static final byte NO_PROTECTION = (byte)1;
     protected static final byte INTEGRITY_ONLY_PROTECTION = (byte)2;
--- a/jdk/src/share/classes/java/awt/Cursor.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/awt/Cursor.java	Tue Aug 18 19:53:43 2009 -0700
@@ -118,8 +118,18 @@
      */
     public static final int     MOVE_CURSOR                     = 13;
 
+    /**
+      * @deprecated As of JDK version 1.7, the {@link #getPredefinedCursor()}
+      * method should be used instead.
+      */
+    @Deprecated
     protected static Cursor predefined[] = new Cursor[14];
 
+    /**
+     * This field is a private replacement for 'predefined' array.
+     */
+    private final static Cursor[] predefinedPrivate = new Cursor[14];
+
     /* Localization names and default values */
     static final String[][] cursorProperties = {
         { "AWT.DefaultCursor", "Default Cursor" },
@@ -253,10 +263,15 @@
         if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
             throw new IllegalArgumentException("illegal cursor type");
         }
+        Cursor c = predefinedPrivate[type];
+        if (c == null) {
+            predefinedPrivate[type] = c = new Cursor(type);
+        }
+        // fill 'predefined' array for backwards compatibility.
         if (predefined[type] == null) {
-            predefined[type] = new Cursor(type);
+            predefined[type] = c;
         }
-        return predefined[type];
+        return c;
     }
 
     /**
--- a/jdk/src/share/classes/java/awt/Window.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/awt/Window.java	Tue Aug 18 19:53:43 2009 -0700
@@ -3743,16 +3743,58 @@
 
     // ****************** END OF MIXING CODE ********************************
 
-    // This method gets the window location/size as reported by the native
-    // system since the locally cached values may represent outdated data.
-    // NOTE: this method is invoked on the toolkit thread, and therefore
-    // is not supposed to become public/user-overridable.
+    /**
+     * Limit the given double value with the given range.
+     */
+    private static double limit(double value, double min, double max) {
+        value = Math.max(value, min);
+        value = Math.min(value, max);
+        return value;
+    }
+
+    /**
+     * Calculate the position of the security warning.
+     *
+     * This method gets the window location/size as reported by the native
+     * system since the locally cached values may represent outdated data.
+     *
+     * The method is used from the native code, or via AWTAccessor.
+     *
+     * NOTE: this method is invoked on the toolkit thread, and therefore is not
+     * supposed to become public/user-overridable.
+     */
     private Point2D calculateSecurityWarningPosition(double x, double y,
             double w, double h)
     {
-        return new Point2D.Double(
-                x + w * securityWarningAlignmentX + securityWarningPointX,
-                y + h * securityWarningAlignmentY + securityWarningPointY);
+        // The position according to the spec of SecurityWarning.setPosition()
+        double wx = x + w * securityWarningAlignmentX + securityWarningPointX;
+        double wy = y + h * securityWarningAlignmentY + securityWarningPointY;
+
+        // First, make sure the warning is not too far from the window bounds
+        wx = Window.limit(wx,
+                x - securityWarningWidth - 2,
+                x + w + 2);
+        wy = Window.limit(wy,
+                y - securityWarningHeight - 2,
+                y + h + 2);
+
+        // Now make sure the warning window is visible on the screen
+        GraphicsConfiguration graphicsConfig =
+            getGraphicsConfiguration_NoClientCode();
+        Rectangle screenBounds = graphicsConfig.getBounds();
+        Insets screenInsets =
+            Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfig);
+
+        wx = Window.limit(wx,
+                screenBounds.x + screenInsets.left,
+                screenBounds.x + screenBounds.width - screenInsets.right
+                - securityWarningWidth);
+        wy = Window.limit(wy,
+                screenBounds.y + screenInsets.top,
+                screenBounds.y + screenBounds.height - screenInsets.bottom
+                - securityWarningHeight);
+
+        return new Point2D.Double(wx, wy);
     }
 
     static {
--- a/jdk/src/share/classes/java/beans/Introspector.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/beans/Introspector.java	Tue Aug 18 19:53:43 2009 -0700
@@ -114,8 +114,8 @@
     // Static Caches to speed up introspection.
     private static Map declaredMethodCache =
         Collections.synchronizedMap(new WeakHashMap());
-    private static Map beanInfoCache =
-        Collections.synchronizedMap(new WeakHashMap());
+
+    private static final Object BEANINFO_CACHE = new Object();
 
     private Class beanClass;
     private BeanInfo explicitBeanInfo;
@@ -174,10 +174,18 @@
         if (!ReflectUtil.isPackageAccessible(beanClass)) {
             return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
         }
-        BeanInfo bi = (BeanInfo)beanInfoCache.get(beanClass);
+        Map<Class<?>, BeanInfo> map;
+        synchronized (BEANINFO_CACHE) {
+            map = (Map<Class<?>, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE);
+            if (map == null) {
+                map = Collections.synchronizedMap(new WeakHashMap<Class<?>, BeanInfo>());
+                AppContext.getAppContext().put(BEANINFO_CACHE, map);
+            }
+        }
+        BeanInfo bi = map.get(beanClass);
         if (bi == null) {
             bi = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
-            beanInfoCache.put(beanClass, bi);
+            map.put(beanClass, bi);
         }
         return bi;
     }
@@ -351,7 +359,10 @@
      */
 
     public static void flushCaches() {
-        beanInfoCache.clear();
+        Map map = (Map) AppContext.getAppContext().get(BEANINFO_CACHE);
+        if (map != null) {
+            map.clear();
+        }
         declaredMethodCache.clear();
     }
 
@@ -374,7 +385,10 @@
         if (clz == null) {
             throw new NullPointerException();
         }
-        beanInfoCache.remove(clz);
+        Map map = (Map) AppContext.getAppContext().get(BEANINFO_CACHE);
+        if (map != null) {
+            map.remove(clz);
+        }
         declaredMethodCache.remove(clz);
     }
 
--- a/jdk/src/share/classes/java/beans/MetaData.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/beans/MetaData.java	Tue Aug 18 19:53:43 2009 -0700
@@ -335,31 +335,6 @@
         return (oldC.size() == newC.size()) && oldC.containsAll(newC);
     }
 
-    static Object getPrivateField(final Object instance, final String name) {
-        return AccessController.doPrivileged(
-                new PrivilegedAction() {
-                    public Object run() {
-                        Class type = instance.getClass();
-                        while ( true ) {
-                            try {
-                                Field field = type.getDeclaredField(name);
-                                field.setAccessible(true);
-                                return field.get( instance );
-                            }
-                            catch (NoSuchFieldException exception) {
-                                type = type.getSuperclass();
-                                if (type == null) {
-                                    throw new IllegalStateException("Could not find field " + name, exception);
-                                }
-                            }
-                            catch (Exception exception) {
-                                throw new IllegalStateException("Could not get value " + type.getName() + '.' + name, exception);
-                            }
-                        }
-                    }
-                } );
-    }
-
     static final class EmptyList_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
             return new Expression(oldInstance, Collections.class, "emptyList", null);
@@ -500,7 +475,7 @@
 
     static final class CheckedCollection_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object type = getPrivateField(oldInstance, "type");
+            Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
             List list = new ArrayList((Collection) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedCollection", new Object[]{list, type});
         }
@@ -508,7 +483,7 @@
 
     static final class CheckedList_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object type = getPrivateField(oldInstance, "type");
+            Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
             List list = new LinkedList((Collection) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
         }
@@ -516,7 +491,7 @@
 
     static final class CheckedRandomAccessList_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object type = getPrivateField(oldInstance, "type");
+            Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
             List list = new ArrayList((Collection) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type});
         }
@@ -524,7 +499,7 @@
 
     static final class CheckedSet_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object type = getPrivateField(oldInstance, "type");
+            Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
             Set set = new HashSet((Set) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedSet", new Object[]{set, type});
         }
@@ -532,7 +507,7 @@
 
     static final class CheckedSortedSet_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object type = getPrivateField(oldInstance, "type");
+            Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type");
             SortedSet set = new TreeSet((SortedSet) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedSortedSet", new Object[]{set, type});
         }
@@ -540,8 +515,8 @@
 
     static final class CheckedMap_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object keyType = getPrivateField(oldInstance, "keyType");
-            Object valueType = getPrivateField(oldInstance, "valueType");
+            Object keyType   = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
+            Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
             Map map = new HashMap((Map) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedMap", new Object[]{map, keyType, valueType});
         }
@@ -549,8 +524,8 @@
 
     static final class CheckedSortedMap_PersistenceDelegate extends java_util_Collections {
         protected Expression instantiate(Object oldInstance, Encoder out) {
-            Object keyType = getPrivateField(oldInstance, "keyType");
-            Object valueType = getPrivateField(oldInstance, "valueType");
+            Object keyType   = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType");
+            Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType");
             SortedMap map = new TreeMap((SortedMap) oldInstance);
             return new Expression(oldInstance, Collections.class, "checkedSortedMap", new Object[]{map, keyType, valueType});
         }
@@ -572,7 +547,7 @@
     }
 
     private static Object getType(Object instance) {
-        return java_util_Collections.getPrivateField(instance, "keyType");
+        return MetaData.getPrivateFieldValue(instance, "java.util.EnumMap.keyType");
     }
 }
 
@@ -591,7 +566,7 @@
     }
 
     private static Object getType(Object instance) {
-        return java_util_Collections.getPrivateField(instance, "elementType");
+        return MetaData.getPrivateFieldValue(instance, "java.util.EnumSet.elementType");
     }
 }
 
@@ -1282,7 +1257,7 @@
 
     private Integer getAxis(Object object) {
         Box box = (Box) object;
-        return (Integer) java_util_Collections.getPrivateField(box.getLayout(), "axis");
+        return (Integer) MetaData.getPrivateFieldValue(box.getLayout(), "javax.swing.BoxLayout.axis");
     }
 }
 
@@ -1365,6 +1340,7 @@
 }
 
 class MetaData {
+    private static final Map<String,Field> fields = Collections.synchronizedMap(new WeakHashMap<String, Field>());
     private static Hashtable internalPersistenceDelegates = new Hashtable();
 
     private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate();
@@ -1503,4 +1479,35 @@
             return null;
         }
     }
+
+    static Object getPrivateFieldValue(Object instance, String name) {
+        Field field = fields.get(name);
+        if (field == null) {
+            int index = name.lastIndexOf('.');
+            final String className = name.substring(0, index);
+            final String fieldName = name.substring(1 + index);
+            field = AccessController.doPrivileged(new PrivilegedAction<Field>() {
+                public Field run() {
+                    try {
+                        Field field = Class.forName(className).getDeclaredField(fieldName);
+                        field.setAccessible(true);
+                        return field;
+                    }
+                    catch (ClassNotFoundException exception) {
+                        throw new IllegalStateException("Could not find class", exception);
+                    }
+                    catch (NoSuchFieldException exception) {
+                        throw new IllegalStateException("Could not find field", exception);
+                    }
+                }
+            });
+            fields.put(name, field);
+        }
+        try {
+            return field.get(instance);
+        }
+        catch (IllegalAccessException exception) {
+            throw new IllegalStateException("Could not get value of the field", exception);
+        }
+    }
 }
--- a/jdk/src/share/classes/java/lang/instrument/Instrumentation.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/lang/instrument/Instrumentation.java	Tue Aug 18 19:53:43 2009 -0700
@@ -81,7 +81,7 @@
      * an exception during execution, the JVM will still call the other registered
      * transformers in order. The same transformer may be added more than once,
      * but it is strongly discouraged -- avoid this by creating a new instance of
-     * tranformer class.
+     * transformer class.
      * <P>
      * This method is intended for use in instrumentation, as described in the
      * {@linkplain Instrumentation class specification}.
@@ -183,7 +183,7 @@
      * <P>
      *
      * The order of transformation is described in the
-     * ({@link java.lang.instrument.ClassFileTransformer#transform transform} method.
+     * {@link java.lang.instrument.ClassFileTransformer#transform transform} method.
      * This same order is used in the automatic reapplication of retransformation
      * incapable transforms.
      * <P>
@@ -424,7 +424,7 @@
      * classes or resources other than those to be defined by the bootstrap
      * class loader for the purpose of instrumentation.
      * Failure to observe this warning could result in unexpected
-     * behaviour that is difficult to diagnose. For example, suppose there is a
+     * behavior that is difficult to diagnose. For example, suppose there is a
      * loader L, and L's parent for delegation is the bootstrap class loader.
      * Furthermore, a method in class C, a class defined by L, makes reference to
      * a non-public accessor class C$1. If the JAR file contains a class C$1 then
@@ -475,9 +475,9 @@
      * classes or resources other than those to be defined by the system class
      * loader for the purpose of instrumentation.
      * Failure to observe this warning could result in unexpected
-     * behaviour that is difficult to diagnose (see
+     * behavior that is difficult to diagnose (see
      * {@link #appendToBootstrapClassLoaderSearch
-     * appendToBootstrapClassLoaderSearch}.
+     * appendToBootstrapClassLoaderSearch}).
      *
      * <p> The system class loader supports adding a JAR file to be searched if
      * it implements a method named <code>appendToClassPathForInstrumentation</code>
@@ -485,7 +485,7 @@
      * method is not required to have <code>public</code> access. The name of
      * the JAR file is obtained by invoking the {@link java.util.zip.ZipFile#getName
      * getName()} method on the <code>jarfile</code> and this is provided as the
-     * parameter to the <code>appendtoClassPathForInstrumentation</code> method.
+     * parameter to the <code>appendToClassPathForInstrumentation</code> method.
      *
      * <p> The <a href="http://java.sun.com/docs/books/vmspec/">Java Virtual Machine
      * Specification</a> specifies that a subsequent attempt to resolve a symbolic
--- a/jdk/src/share/classes/java/net/Socket.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/net/Socket.java	Tue Aug 18 19:53:43 2009 -0700
@@ -114,9 +114,14 @@
      * @since   1.5
      */
     public Socket(Proxy proxy) {
-        if (proxy != null && proxy.type() == Proxy.Type.SOCKS) {
+        // Create a copy of Proxy as a security measure
+        if (proxy == null) {
+            throw new IllegalArgumentException("Invalid Proxy");
+        }
+        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy);
+        if (p.type() == Proxy.Type.SOCKS) {
             SecurityManager security = System.getSecurityManager();
-            InetSocketAddress epoint = (InetSocketAddress) proxy.address();
+            InetSocketAddress epoint = (InetSocketAddress) p.address();
             if (security != null) {
                 if (epoint.isUnresolved())
                     security.checkConnect(epoint.getHostName(),
@@ -125,10 +130,10 @@
                     security.checkConnect(epoint.getAddress().getHostAddress(),
                                           epoint.getPort());
             }
-            impl = new SocksSocketImpl(proxy);
+            impl = new SocksSocketImpl(p);
             impl.setSocket(this);
         } else {
-            if (proxy == Proxy.NO_PROXY) {
+            if (p == Proxy.NO_PROXY) {
                 if (factory == null) {
                     impl = new PlainSocketImpl();
                     impl.setSocket(this);
--- a/jdk/src/share/classes/java/net/SocksSocketImpl.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java	Tue Aug 18 19:53:43 2009 -0700
@@ -46,6 +46,9 @@
     private Socket cmdsock = null;
     private InputStream cmdIn = null;
     private OutputStream cmdOut = null;
+    /* true if the Proxy has been set programatically */
+    private boolean applicationSetProxy;  /* false */
+
 
     SocksSocketImpl() {
         // Nothing needed
@@ -237,8 +240,7 @@
         out.write((endpoint.getPort() >> 8) & 0xff);
         out.write((endpoint.getPort() >> 0) & 0xff);
         out.write(endpoint.getAddress().getAddress());
-        String userName = java.security.AccessController.doPrivileged(
-               new sun.security.action.GetPropertyAction("user.name"));
+        String userName = getUserName();
         try {
             out.write(userName.getBytes("ISO-8859-1"));
         } catch (java.io.UnsupportedEncodingException uee) {
@@ -554,8 +556,7 @@
         out.write((super.getLocalPort() >> 8) & 0xff);
         out.write((super.getLocalPort() >> 0) & 0xff);
         out.write(addr1);
-        String userName = java.security.AccessController.doPrivileged(
-               new sun.security.action.GetPropertyAction("user.name"));
+        String userName = getUserName();
         try {
             out.write(userName.getBytes("ISO-8859-1"));
         } catch (java.io.UnsupportedEncodingException uee) {
@@ -1022,4 +1023,16 @@
         super.close();
     }
 
+    private String getUserName() {
+        String userName = "";
+        if (applicationSetProxy) {
+            try {
+                userName = System.getProperty("user.name");
+            } catch (SecurityException se) { /* swallow Exception */ }
+        } else {
+            userName = java.security.AccessController.doPrivileged(
+                new sun.security.action.GetPropertyAction("user.name"));
+        }
+        return userName;
+    }
 }
--- a/jdk/src/share/classes/java/net/URL.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/net/URL.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1004,16 +1004,18 @@
             throw new IllegalArgumentException("proxy can not be null");
         }
 
+        // Create a copy of Proxy as a security measure
+        Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy);
         SecurityManager sm = System.getSecurityManager();
-        if (proxy.type() != Proxy.Type.DIRECT && sm != null) {
-            InetSocketAddress epoint = (InetSocketAddress) proxy.address();
+        if (p.type() != Proxy.Type.DIRECT && sm != null) {
+            InetSocketAddress epoint = (InetSocketAddress) p.address();
             if (epoint.isUnresolved())
                 sm.checkConnect(epoint.getHostName(), epoint.getPort());
             else
                 sm.checkConnect(epoint.getAddress().getHostAddress(),
                                 epoint.getPort());
         }
-        return handler.openConnection(this, proxy);
+        return handler.openConnection(this, p);
     }
 
     /**
--- a/jdk/src/share/classes/java/nio/channels/DatagramChannel.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/channels/DatagramChannel.java	Tue Aug 18 19:53:43 2009 -0700
@@ -421,7 +421,7 @@
      * invocation of this method will block until the first operation is
      * complete. If this channel's socket is not bound then this method will
      * first cause the socket to be bound to an address that is assigned
-     * automatically, as if by invoking the {@link #bind bind) method with a
+     * automatically, as if by invoking the {@link #bind bind} method with a
      * parameter of {@code null}. </p>
      *
      * @param  src
--- a/jdk/src/share/classes/java/nio/channels/package-info.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/channels/package-info.java	Tue Aug 18 19:53:43 2009 -0700
@@ -115,8 +115,8 @@
  *     <td>Reads, writes, maps, and manipulates files</td></tr>
  * <tr><td valign=top><tt>{@link java.nio.channels.FileLock}</tt></td>
  *     <td>A lock on a (region of a) file</td></tr>
- * <tr><td valign=top><tt>{@link java.nio.MappedByteBuffer}/{@link java.nio.MappedBigByteBuffer}&nbsp;&nbsp;</tt></td>
- *     <td>A direct byte buffer or big byte buffer mapped to a region of a&nbsp;file</td></tr>
+ * <tr><td valign=top><tt>{@link java.nio.MappedByteBuffer}&nbsp;&nbsp;</tt></td>
+ *     <td>A direct byte buffer mapped to a region of a&nbsp;file</td></tr>
  * </table></blockquote>
  *
  * <p> The {@link java.nio.channels.FileChannel} class supports the usual
--- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java	Tue Aug 18 19:53:43 2009 -0700
@@ -53,7 +53,7 @@
  * invoking the {@link #close close} method. Closing the directory stream
  * releases any resources associated with the stream. Once a directory stream
  * is closed, all further method invocations on the iterator throw {@link
- * java.util.concurrent.ConcurrentModificationException} with cause {@link
+ * java.util.ConcurrentModificationException} with cause {@link
  * ClosedDirectoryStreamException}.
  *
  * <p> A directory stream is not required to be <i>asynchronously closeable</i>.
--- a/jdk/src/share/classes/java/nio/file/Path.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/file/Path.java	Tue Aug 18 19:53:43 2009 -0700
@@ -987,7 +987,7 @@
      * exception then it is propogated to the iterator's {@link Iterator#hasNext()
      * hasNext} or {@link Iterator#next() next} method. Where an {@code
      * IOException} is thrown, it is propogated as a {@link
-     * java.util.concurrent.ConcurrentModificationException} with the {@code
+     * java.util.ConcurrentModificationException} with the {@code
      * IOException} as the cause.
      *
      * <p> When an implementation supports operations on entries in the
--- a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java	Tue Aug 18 19:53:43 2009 -0700
@@ -48,6 +48,14 @@
     }
 
     /**
+     * Throws NullPointerException if obj is null.
+     */
+    private static void checkNotNull(Object obj) {
+        if (obj == null)
+            throw new NullPointerException();
+    }
+
+    /**
      * Invoked for a directory before entries in the directory are visited.
      *
      * <p> Unless overridden, this method returns {@link FileVisitResult#CONTINUE
@@ -55,6 +63,7 @@
      */
     @Override
     public FileVisitResult preVisitDirectory(T dir) {
+        checkNotNull(dir);
         return FileVisitResult.CONTINUE;
     }
 
@@ -70,6 +79,8 @@
      */
     @Override
     public FileVisitResult preVisitDirectoryFailed(T dir, IOException exc) {
+        checkNotNull(dir);
+        checkNotNull(exc);
         throw new IOError(exc);
     }
 
@@ -81,6 +92,8 @@
      */
     @Override
     public FileVisitResult visitFile(T file, BasicFileAttributes attrs) {
+        checkNotNull(file);
+        checkNotNull(attrs);
         return FileVisitResult.CONTINUE;
     }
 
@@ -96,6 +109,8 @@
      */
     @Override
     public FileVisitResult visitFileFailed(T file, IOException exc) {
+        checkNotNull(file);
+        checkNotNull(exc);
         throw new IOError(exc);
     }
 
@@ -114,6 +129,7 @@
      */
     @Override
     public FileVisitResult postVisitDirectory(T dir, IOException exc) {
+        checkNotNull(dir);
         if (exc != null)
             throw new IOError(exc);
         return FileVisitResult.CONTINUE;
--- a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java	Tue Aug 18 19:53:43 2009 -0700
@@ -75,7 +75,7 @@
  *         .lookupPrincipalByName("joe");
  *
  *     // get view
- *     AclFileAttributeView view = file.newFileAttributeView(AclFileAttributeView.class);
+ *     AclFileAttributeView view = file.getFileAttributeView(AclFileAttributeView.class);
  *
  *     // create ACE to give "joe" read access
  *     AclEntry entry = AclEntry.newBuilder()
--- a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java	Tue Aug 18 19:53:43 2009 -0700
@@ -61,7 +61,7 @@
  * Suppose we need to print out the owner and access permissions of a file:
  * <pre>
  *     FileRef file = ...
- *     PosixFileAttributes attrs = file.newFileAttributeView(PosixFileAttributeView.class)
+ *     PosixFileAttributes attrs = file.getFileAttributeView(PosixFileAttributeView.class)
  *         .readAttributes();
  *     System.out.format("%s %s%n",
  *         attrs.owner().getName(),
--- a/jdk/src/share/classes/java/nio/file/attribute/package-info.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/nio/file/attribute/package-info.java	Tue Aug 18 19:53:43 2009 -0700
@@ -102,9 +102,9 @@
  *   <p><li> The {@link java.nio.file.attribute.UserPrincipalLookupService}
  *   interface defines methods to lookup user or group principals. </li>
  *
- *   <p><li> The {@link java.nio.file.attribute.Attribute} interface
+ *   <p><li> The {@link java.nio.file.attribute.FileAttribute} interface
  *   represents the value of an attribute for cases where the attribute value is
- *   require to be set atomically when creating an object in the file system. </li>
+ *   required to be set atomically when creating an object in the file system. </li>
  *
  * </ul>
  *
--- a/jdk/src/share/classes/java/util/Arrays.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/util/Arrays.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1065,29 +1065,103 @@
                 (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
     }
 
+    /**
+     * Old merge sort implementation can be selected (for
+     * compatibility with broken comparators) using a system property.
+     * Cannot be a static boolean in the enclosing class due to
+     * circular dependencies.  To be removed in a future release.
+     */
+    static final class LegacyMergeSort {
+        private static final boolean userRequested =
+            java.security.AccessController.doPrivileged(
+                new sun.security.action.GetBooleanAction(
+                    "java.util.Arrays.useLegacyMergeSort")).booleanValue();
+    }
+
+    /*
+     * If this platform has an optimizing VM, check whether ComparableTimSort
+     * offers any performance benefit over TimSort in conjunction with a
+     * comparator that returns:
+     *    {@code ((Comparable)first).compareTo(Second)}.
+     * If not, you are better off deleting ComparableTimSort to
+     * eliminate the code duplication.  In other words, the commented
+     * out code below is the preferable implementation for sorting
+     * arrays of Comparables if it offers sufficient performance.
+     */
+
+//    /**
+//     * A comparator that implements the natural ordering of a group of
+//     * mutually comparable elements.  Using this comparator saves us
+//     * from duplicating most of the code in this file (one version for
+//     * Comparables, one for explicit Comparators).
+//     */
+//    private static final Comparator<Object> NATURAL_ORDER =
+//            new Comparator<Object>() {
+//        @SuppressWarnings("unchecked")
+//        public int compare(Object first, Object second) {
+//            return ((Comparable<Object>)first).compareTo(second);
+//        }
+//    };
+//
+//    public static void sort(Object[] a) {
+//        sort(a, 0, a.length, NATURAL_ORDER);
+//    }
+//
+//    public static void sort(Object[] a, int fromIndex, int toIndex) {
+//        sort(a, fromIndex, toIndex, NATURAL_ORDER);
+//    }
 
     /**
-     * Sorts the specified array of objects into ascending order, according to
-     * the {@linkplain Comparable natural ordering}
-     * of its elements.  All elements in the array
-     * must implement the {@link Comparable} interface.  Furthermore, all
-     * elements in the array must be <i>mutually comparable</i> (that is,
-     * <tt>e1.compareTo(e2)</tt> must not throw a <tt>ClassCastException</tt>
-     * for any elements <tt>e1</tt> and <tt>e2</tt> in the array).<p>
+     * Sorts the specified array of objects into ascending order, according
+     * to the {@linkplain Comparable natural ordering} of its elements.
+     * All elements in the array must implement the {@link Comparable}
+     * interface.  Furthermore, all elements in the array must be
+     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)} must
+     * not throw a {@code ClassCastException} for any elements {@code e1}
+     * and {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
      *
-     * This sort is guaranteed to be <i>stable</i>:  equal elements will
-     * not be reordered as a result of the sort.<p>
+     * <p>Implementation note: This implementation is a stable, adaptive,
+     * iterative mergesort that requires far fewer than n lg(n) comparisons
+     * when the input array is partially sorted, while offering the
+     * performance of a traditional mergesort when the input array is
+     * randomly ordered.  If the input array is nearly sorted, the
+     * implementation requires approximately n comparisons.  Temporary
+     * storage requirements vary from a small constant for nearly sorted
+     * input arrays to n/2 object references for randomly ordered input
+     * arrays.
      *
-     * The sorting algorithm is a modified mergesort (in which the merge is
-     * omitted if the highest element in the low sublist is less than the
-     * lowest element in the high sublist).  This algorithm offers guaranteed
-     * n*log(n) performance.
+     * <p>The implementation takes equal advantage of ascending and
+     * descending order in its input array, and can take advantage of
+     * ascending and descending order in different parts of the the same
+     * input array.  It is well-suited to merging two or more sorted arrays:
+     * simply concatenate the arrays and sort the resulting array.
+     *
+     * <p>The implementation was adapted from Tim Peters's list sort for Python
+     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
+     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * Sorting and Information Theoretic Complexity", in Proceedings of the
+     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
+     * January 1993.
      *
      * @param a the array to be sorted
-     * @throws  ClassCastException if the array contains elements that are not
-     *          <i>mutually comparable</i> (for example, strings and integers).
+     * @throws ClassCastException if the array contains elements that are not
+     *         <i>mutually comparable</i> (for example, strings and integers)
+     * @throws IllegalArgumentException (optional) if the natural
+     *         ordering of the array elements is found to violate the
+     *         {@link Comparable} contract
      */
     public static void sort(Object[] a) {
+        if (LegacyMergeSort.userRequested)
+            legacyMergeSort(a);
+        else
+            ComparableTimSort.sort(a);
+    }
+
+    /** To be removed in a future release. */
+    private static void legacyMergeSort(Object[] a) {
         Object[] aux = a.clone();
         mergeSort(aux, a, 0, a.length, 0);
     }
@@ -1097,34 +1171,63 @@
      * ascending order, according to the
      * {@linkplain Comparable natural ordering} of its
      * elements.  The range to be sorted extends from index
-     * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
-     * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)  All
+     * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive.
+     * (If {@code fromIndex==toIndex}, the range to be sorted is empty.)  All
      * elements in this range must implement the {@link Comparable}
      * interface.  Furthermore, all elements in this range must be <i>mutually
-     * comparable</i> (that is, <tt>e1.compareTo(e2)</tt> must not throw a
-     * <tt>ClassCastException</tt> for any elements <tt>e1</tt> and
-     * <tt>e2</tt> in the array).<p>
+     * comparable</i> (that is, {@code e1.compareTo(e2)} must not throw a
+     * {@code ClassCastException} for any elements {@code e1} and
+     * {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
      *
-     * This sort is guaranteed to be <i>stable</i>:  equal elements will
-     * not be reordered as a result of the sort.<p>
+     * <p>Implementation note: This implementation is a stable, adaptive,
+     * iterative mergesort that requires far fewer than n lg(n) comparisons
+     * when the input array is partially sorted, while offering the
+     * performance of a traditional mergesort when the input array is
+     * randomly ordered.  If the input array is nearly sorted, the
+     * implementation requires approximately n comparisons.  Temporary
+     * storage requirements vary from a small constant for nearly sorted
+     * input arrays to n/2 object references for randomly ordered input
+     * arrays.
      *
-     * The sorting algorithm is a modified mergesort (in which the merge is
-     * omitted if the highest element in the low sublist is less than the
-     * lowest element in the high sublist).  This algorithm offers guaranteed
-     * n*log(n) performance.
+     * <p>The implementation takes equal advantage of ascending and
+     * descending order in its input array, and can take advantage of
+     * ascending and descending order in different parts of the the same
+     * input array.  It is well-suited to merging two or more sorted arrays:
+     * simply concatenate the arrays and sort the resulting array.
+     *
+     * <p>The implementation was adapted from Tim Peters's list sort for Python
+     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
+     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * Sorting and Information Theoretic Complexity", in Proceedings of the
+     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
+     * January 1993.
      *
      * @param a the array to be sorted
      * @param fromIndex the index of the first element (inclusive) to be
      *        sorted
      * @param toIndex the index of the last element (exclusive) to be sorted
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
-     * @throws    ClassCastException if the array contains elements that are
-     *            not <i>mutually comparable</i> (for example, strings and
-     *            integers).
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+     *         (optional) if the natural ordering of the array elements is
+     *         found to violate the {@link Comparable} contract
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> (for example, strings and
+     *         integers).
      */
     public static void sort(Object[] a, int fromIndex, int toIndex) {
+        if (LegacyMergeSort.userRequested)
+            legacyMergeSort(a, fromIndex, toIndex);
+        else
+            ComparableTimSort.sort(a, fromIndex, toIndex);
+    }
+
+    /** To be removed in a future release. */
+    private static void legacyMergeSort(Object[] a,
+                                        int fromIndex, int toIndex) {
         rangeCheck(a.length, fromIndex, toIndex);
         Object[] aux = copyOfRange(a, fromIndex, toIndex);
         mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
@@ -1133,6 +1236,7 @@
     /**
      * Tuning parameter: list size at or below which insertion sort will be
      * used in preference to mergesort or quicksort.
+     * To be removed in a future release.
      */
     private static final int INSERTIONSORT_THRESHOLD = 7;
 
@@ -1142,6 +1246,7 @@
      * low is the index in dest to start sorting
      * high is the end index in dest to end sorting
      * off is the offset to generate corresponding low, high in src
+     * To be removed in a future release.
      */
     private static void mergeSort(Object[] src,
                                   Object[] dest,
@@ -1197,25 +1302,53 @@
      * Sorts the specified array of objects according to the order induced by
      * the specified comparator.  All elements in the array must be
      * <i>mutually comparable</i> by the specified comparator (that is,
-     * <tt>c.compare(e1, e2)</tt> must not throw a <tt>ClassCastException</tt>
-     * for any elements <tt>e1</tt> and <tt>e2</tt> in the array).<p>
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the array).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
      *
-     * This sort is guaranteed to be <i>stable</i>:  equal elements will
-     * not be reordered as a result of the sort.<p>
+     * <p>Implementation note: This implementation is a stable, adaptive,
+     * iterative mergesort that requires far fewer than n lg(n) comparisons
+     * when the input array is partially sorted, while offering the
+     * performance of a traditional mergesort when the input array is
+     * randomly ordered.  If the input array is nearly sorted, the
+     * implementation requires approximately n comparisons.  Temporary
+     * storage requirements vary from a small constant for nearly sorted
+     * input arrays to n/2 object references for randomly ordered input
+     * arrays.
      *
-     * The sorting algorithm is a modified mergesort (in which the merge is
-     * omitted if the highest element in the low sublist is less than the
-     * lowest element in the high sublist).  This algorithm offers guaranteed
-     * n*log(n) performance.
+     * <p>The implementation takes equal advantage of ascending and
+     * descending order in its input array, and can take advantage of
+     * ascending and descending order in different parts of the the same
+     * input array.  It is well-suited to merging two or more sorted arrays:
+     * simply concatenate the arrays and sort the resulting array.
+     *
+     * <p>The implementation was adapted from Tim Peters's list sort for Python
+     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
+     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * Sorting and Information Theoretic Complexity", in Proceedings of the
+     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
+     * January 1993.
      *
      * @param a the array to be sorted
      * @param c the comparator to determine the order of the array.  A
-     *        <tt>null</tt> value indicates that the elements'
+     *        {@code null} value indicates that the elements'
      *        {@linkplain Comparable natural ordering} should be used.
-     * @throws  ClassCastException if the array contains elements that are
-     *          not <i>mutually comparable</i> using the specified comparator.
+     * @throws ClassCastException if the array contains elements that are
+     *         not <i>mutually comparable</i> using the specified comparator
+     * @throws IllegalArgumentException (optional) if the comparator is
+     *         found to violate the {@link Comparator} contract
      */
     public static <T> void sort(T[] a, Comparator<? super T> c) {
+        if (LegacyMergeSort.userRequested)
+            legacyMergeSort(a, c);
+        else
+            TimSort.sort(a, c);
+    }
+
+    /** To be removed in a future release. */
+    private static <T> void legacyMergeSort(T[] a, Comparator<? super T> c) {
         T[] aux = a.clone();
         if (c==null)
             mergeSort(aux, a, 0, a.length, 0);
@@ -1226,36 +1359,65 @@
     /**
      * Sorts the specified range of the specified array of objects according
      * to the order induced by the specified comparator.  The range to be
-     * sorted extends from index <tt>fromIndex</tt>, inclusive, to index
-     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
+     * sorted extends from index {@code fromIndex}, inclusive, to index
+     * {@code toIndex}, exclusive.  (If {@code fromIndex==toIndex}, the
      * range to be sorted is empty.)  All elements in the range must be
      * <i>mutually comparable</i> by the specified comparator (that is,
-     * <tt>c.compare(e1, e2)</tt> must not throw a <tt>ClassCastException</tt>
-     * for any elements <tt>e1</tt> and <tt>e2</tt> in the range).<p>
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the range).
+     *
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
      *
-     * This sort is guaranteed to be <i>stable</i>:  equal elements will
-     * not be reordered as a result of the sort.<p>
+     * <p>Implementation note: This implementation is a stable, adaptive,
+     * iterative mergesort that requires far fewer than n lg(n) comparisons
+     * when the input array is partially sorted, while offering the
+     * performance of a traditional mergesort when the input array is
+     * randomly ordered.  If the input array is nearly sorted, the
+     * implementation requires approximately n comparisons.  Temporary
+     * storage requirements vary from a small constant for nearly sorted
+     * input arrays to n/2 object references for randomly ordered input
+     * arrays.
      *
-     * The sorting algorithm is a modified mergesort (in which the merge is
-     * omitted if the highest element in the low sublist is less than the
-     * lowest element in the high sublist).  This algorithm offers guaranteed
-     * n*log(n) performance.
+     * <p>The implementation takes equal advantage of ascending and
+     * descending order in its input array, and can take advantage of
+     * ascending and descending order in different parts of the the same
+     * input array.  It is well-suited to merging two or more sorted arrays:
+     * simply concatenate the arrays and sort the resulting array.
+     *
+     * <p>The implementation was adapted from Tim Peters's list sort for Python
+     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
+     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * Sorting and Information Theoretic Complexity", in Proceedings of the
+     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
+     * January 1993.
      *
      * @param a the array to be sorted
      * @param fromIndex the index of the first element (inclusive) to be
      *        sorted
      * @param toIndex the index of the last element (exclusive) to be sorted
      * @param c the comparator to determine the order of the array.  A
-     *        <tt>null</tt> value indicates that the elements'
+     *        {@code null} value indicates that the elements'
      *        {@linkplain Comparable natural ordering} should be used.
      * @throws ClassCastException if the array contains elements that are not
      *         <i>mutually comparable</i> using the specified comparator.
-     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
-     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
-     *         <tt>toIndex &gt; a.length</tt>
+     * @throws IllegalArgumentException if {@code fromIndex > toIndex} or
+     *         (optional) if the comparator is found to violate the
+     *         {@link Comparator} contract
+     * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or
+     *         {@code toIndex > a.length}
      */
     public static <T> void sort(T[] a, int fromIndex, int toIndex,
                                 Comparator<? super T> c) {
+        if (LegacyMergeSort.userRequested)
+            legacyMergeSort(a, fromIndex, toIndex, c);
+        else
+            TimSort.sort(a, fromIndex, toIndex, c);
+    }
+
+    /** To be removed in a future release. */
+    private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
+                                            Comparator<? super T> c) {
         rangeCheck(a.length, fromIndex, toIndex);
         T[] aux = copyOfRange(a, fromIndex, toIndex);
         if (c==null)
@@ -1270,6 +1432,7 @@
      * low is the index in dest to start sorting
      * high is the end index in dest to end sorting
      * off is the offset into src corresponding to low in dest
+     * To be removed in a future release.
      */
     private static void mergeSort(Object[] src,
                                   Object[] dest,
--- a/jdk/src/share/classes/java/util/Collections.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/util/Collections.java	Tue Aug 18 19:53:43 2009 -0700
@@ -100,23 +100,42 @@
 
     /**
      * Sorts the specified list into ascending order, according to the
-     * <i>natural ordering</i> of its elements.  All elements in the list must
-     * implement the <tt>Comparable</tt> interface.  Furthermore, all elements
-     * in the list must be <i>mutually comparable</i> (that is,
-     * <tt>e1.compareTo(e2)</tt> must not throw a <tt>ClassCastException</tt>
-     * for any elements <tt>e1</tt> and <tt>e2</tt> in the list).<p>
+     * {@linkplain Comparable natural ordering} of its elements.
+     * All elements in the list must implement the {@link Comparable}
+     * interface.  Furthermore, all elements in the list must be
+     * <i>mutually comparable</i> (that is, {@code e1.compareTo(e2)}
+     * must not throw a {@code ClassCastException} for any elements
+     * {@code e1} and {@code e2} in the list).
      *
-     * This sort is guaranteed to be <i>stable</i>:  equal elements will
-     * not be reordered as a result of the sort.<p>
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * <p>The specified list must be modifiable, but need not be resizable.
      *
-     * The specified list must be modifiable, but need not be resizable.<p>
+     * <p>Implementation note: This implementation is a stable, adaptive,
+     * iterative mergesort that requires far fewer than n lg(n) comparisons
+     * when the input array is partially sorted, while offering the
+     * performance of a traditional mergesort when the input array is
+     * randomly ordered.  If the input array is nearly sorted, the
+     * implementation requires approximately n comparisons.  Temporary
+     * storage requirements vary from a small constant for nearly sorted
+     * input arrays to n/2 object references for randomly ordered input
+     * arrays.
      *
-     * The sorting algorithm is a modified mergesort (in which the merge is
-     * omitted if the highest element in the low sublist is less than the
-     * lowest element in the high sublist).  This algorithm offers guaranteed
-     * n log(n) performance.
+     * <p>The implementation takes equal advantage of ascending and
+     * descending order in its input array, and can take advantage of
+     * ascending and descending order in different parts of the the same
+     * input array.  It is well-suited to merging two or more sorted arrays:
+     * simply concatenate the arrays and sort the resulting array.
      *
-     * This implementation dumps the specified list into an array, sorts
+     * <p>The implementation was adapted from Tim Peters's list sort for Python
+     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
+     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * Sorting and Information Theoretic Complexity", in Proceedings of the
+     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
+     * January 1993.
+     *
+     * <p>This implementation dumps the specified list into an array, sorts
      * the array, and iterates over the list resetting each element
      * from the corresponding position in the array.  This avoids the
      * n<sup>2</sup> log(n) performance that would result from attempting
@@ -126,8 +145,10 @@
      * @throws ClassCastException if the list contains elements that are not
      *         <i>mutually comparable</i> (for example, strings and integers).
      * @throws UnsupportedOperationException if the specified list's
-     *         list-iterator does not support the <tt>set</tt> operation.
-     * @see Comparable
+     *         list-iterator does not support the {@code set} operation.
+     * @throws IllegalArgumentException (optional) if the implementation
+     *         detects that the natural ordering of the list elements is
+     *         found to violate the {@link Comparable} contract
      */
     public static <T extends Comparable<? super T>> void sort(List<T> list) {
         Object[] a = list.toArray();
@@ -143,19 +164,38 @@
      * Sorts the specified list according to the order induced by the
      * specified comparator.  All elements in the list must be <i>mutually
      * comparable</i> using the specified comparator (that is,
-     * <tt>c.compare(e1, e2)</tt> must not throw a <tt>ClassCastException</tt>
-     * for any elements <tt>e1</tt> and <tt>e2</tt> in the list).<p>
+     * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException}
+     * for any elements {@code e1} and {@code e2} in the list).
      *
-     * This sort is guaranteed to be <i>stable</i>:  equal elements will
-     * not be reordered as a result of the sort.<p>
+     * <p>This sort is guaranteed to be <i>stable</i>:  equal elements will
+     * not be reordered as a result of the sort.
+     *
+     * <p>The specified list must be modifiable, but need not be resizable.
      *
-     * The sorting algorithm is a modified mergesort (in which the merge is
-     * omitted if the highest element in the low sublist is less than the
-     * lowest element in the high sublist).  This algorithm offers guaranteed
-     * n log(n) performance.
+     * <p>Implementation note: This implementation is a stable, adaptive,
+     * iterative mergesort that requires far fewer than n lg(n) comparisons
+     * when the input array is partially sorted, while offering the
+     * performance of a traditional mergesort when the input array is
+     * randomly ordered.  If the input array is nearly sorted, the
+     * implementation requires approximately n comparisons.  Temporary
+     * storage requirements vary from a small constant for nearly sorted
+     * input arrays to n/2 object references for randomly ordered input
+     * arrays.
      *
-     * The specified list must be modifiable, but need not be resizable.
-     * This implementation dumps the specified list into an array, sorts
+     * <p>The implementation takes equal advantage of ascending and
+     * descending order in its input array, and can take advantage of
+     * ascending and descending order in different parts of the the same
+     * input array.  It is well-suited to merging two or more sorted arrays:
+     * simply concatenate the arrays and sort the resulting array.
+     *
+     * <p>The implementation was adapted from Tim Peters's list sort for Python
+     * (<a href="http://svn.python.org/projects/python/trunk/Objects/listsort.txt">
+     * TimSort</a>).  It uses techiques from Peter McIlroy's "Optimistic
+     * Sorting and Information Theoretic Complexity", in Proceedings of the
+     * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474,
+     * January 1993.
+     *
+     * <p>This implementation dumps the specified list into an array, sorts
      * the array, and iterates over the list resetting each element
      * from the corresponding position in the array.  This avoids the
      * n<sup>2</sup> log(n) performance that would result from attempting
@@ -163,13 +203,14 @@
      *
      * @param  list the list to be sorted.
      * @param  c the comparator to determine the order of the list.  A
-     *        <tt>null</tt> value indicates that the elements' <i>natural
+     *        {@code null} value indicates that the elements' <i>natural
      *        ordering</i> should be used.
      * @throws ClassCastException if the list contains elements that are not
      *         <i>mutually comparable</i> using the specified comparator.
      * @throws UnsupportedOperationException if the specified list's
-     *         list-iterator does not support the <tt>set</tt> operation.
-     * @see Comparator
+     *         list-iterator does not support the {@code set} operation.
+     * @throws IllegalArgumentException (optional) if the comparator is
+     *         found to violate the {@link Comparator} contract
      */
     public static <T> void sort(List<T> list, Comparator<? super T> c) {
         Object[] a = list.toArray();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/ComparableTimSort.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,895 @@
+/*
+ * Copyright 2009 Google 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 java.util;
+
+/**
+ * This is a near duplicate of {@link TimSort}, modified for use with
+ * arrays of objects that implement {@link Comparable}, instead of using
+ * explicit comparators.
+ *
+ * <p>If you are using an optimizing VM, you may find that ComparableTimSort
+ * offers no performance benefit over TimSort in conjunction with a
+ * comparator that simply returns {@code ((Comparable)first).compareTo(Second)}.
+ * If this is the case, you are better off deleting ComparableTimSort to
+ * eliminate the code duplication.  (See Arrays.java for details.)
+ *
+ * @author Josh Bloch
+ */
+class ComparableTimSort {
+    /**
+     * This is the minimum sized sequence that will be merged.  Shorter
+     * sequences will be lengthened by calling binarySort.  If the entire
+     * array is less than this length, no merges will be performed.
+     *
+     * This constant should be a power of two.  It was 64 in Tim Peter's C
+     * implementation, but 32 was empirically determined to work better in
+     * this implementation.  In the unlikely event that you set this constant
+     * to be a number that's not a power of two, you'll need to change the
+     * {@link #minRunLength} computation.
+     *
+     * If you decrease this constant, you must change the stackLen
+     * computation in the TimSort constructor, or you risk an
+     * ArrayOutOfBounds exception.  See listsort.txt for a discussion
+     * of the minimum stack length required as a function of the length
+     * of the array being sorted and the minimum merge sequence length.
+     */
+    private static final int MIN_MERGE = 32;
+
+    /**
+     * The array being sorted.
+     */
+    private final Object[] a;
+
+    /**
+     * When we get into galloping mode, we stay there until both runs win less
+     * often than MIN_GALLOP consecutive times.
+     */
+    private static final int  MIN_GALLOP = 7;
+
+    /**
+     * This controls when we get *into* galloping mode.  It is initialized
+     * to MIN_GALLOP.  The mergeLo and mergeHi methods nudge it higher for
+     * random data, and lower for highly structured data.
+     */
+    private int minGallop = MIN_GALLOP;
+
+    /**
+     * Maximum initial size of tmp array, which is used for merging.  The array
+     * can grow to accommodate demand.
+     *
+     * Unlike Tim's original C version, we do not allocate this much storage
+     * when sorting smaller arrays.  This change was required for performance.
+     */
+    private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
+
+    /**
+     * Temp storage for merges.
+     */
+    private Object[] tmp;
+
+    /**
+     * A stack of pending runs yet to be merged.  Run i starts at
+     * address base[i] and extends for len[i] elements.  It's always
+     * true (so long as the indices are in bounds) that:
+     *
+     *     runBase[i] + runLen[i] == runBase[i + 1]
+     *
+     * so we could cut the storage for this, but it's a minor amount,
+     * and keeping all the info explicit simplifies the code.
+     */
+    private int stackSize = 0;  // Number of pending runs on stack
+    private final int[] runBase;
+    private final int[] runLen;
+
+    /**
+     * Creates a TimSort instance to maintain the state of an ongoing sort.
+     *
+     * @param a the array to be sorted
+     */
+    private ComparableTimSort(Object[] a) {
+        this.a = a;
+
+        // Allocate temp storage (which may be increased later if necessary)
+        int len = a.length;
+        @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+        Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
+                                       len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
+        tmp = newArray;
+
+        /*
+         * Allocate runs-to-be-merged stack (which cannot be expanded).  The
+         * stack length requirements are described in listsort.txt.  The C
+         * version always uses the same stack length (85), but this was
+         * measured to be too expensive when sorting "mid-sized" arrays (e.g.,
+         * 100 elements) in Java.  Therefore, we use smaller (but sufficiently
+         * large) stack lengths for smaller arrays.  The "magic numbers" in the
+         * computation below must be changed if MIN_MERGE is decreased.  See
+         * the MIN_MERGE declaration above for more information.
+         */
+        int stackLen = (len <    120  ?  5 :
+                        len <   1542  ? 10 :
+                        len < 119151  ? 19 : 40);
+        runBase = new int[stackLen];
+        runLen = new int[stackLen];
+    }
+
+    /*
+     * The next two methods (which are package private and static) constitute
+     * the entire API of this class.  Each of these methods obeys the contract
+     * of the public method with the same signature in java.util.Arrays.
+     */
+
+    static void sort(Object[] a) {
+          sort(a, 0, a.length);
+    }
+
+    static void sort(Object[] a, int lo, int hi) {
+        rangeCheck(a.length, lo, hi);
+        int nRemaining  = hi - lo;
+        if (nRemaining < 2)
+            return;  // Arrays of size 0 and 1 are always sorted
+
+        // If array is small, do a "mini-TimSort" with no merges
+        if (nRemaining < MIN_MERGE) {
+            int initRunLen = countRunAndMakeAscending(a, lo, hi);
+            binarySort(a, lo, hi, lo + initRunLen);
+            return;
+        }
+
+        /**
+         * March over the array once, left to right, finding natural runs,
+         * extending short natural runs to minRun elements, and merging runs
+         * to maintain stack invariant.
+         */
+        ComparableTimSort ts = new ComparableTimSort(a);
+        int minRun = minRunLength(nRemaining);
+        do {
+            // Identify next run
+            int runLen = countRunAndMakeAscending(a, lo, hi);
+
+            // If run is short, extend to min(minRun, nRemaining)
+            if (runLen < minRun) {
+                int force = nRemaining <= minRun ? nRemaining : minRun;
+                binarySort(a, lo, lo + force, lo + runLen);
+                runLen = force;
+            }
+
+            // Push run onto pending-run stack, and maybe merge
+            ts.pushRun(lo, runLen);
+            ts.mergeCollapse();
+
+            // Advance to find next run
+            lo += runLen;
+            nRemaining -= runLen;
+        } while (nRemaining != 0);
+
+        // Merge all remaining runs to complete sort
+        assert lo == hi;
+        ts.mergeForceCollapse();
+        assert ts.stackSize == 1;
+    }
+
+    /**
+     * Sorts the specified portion of the specified array using a binary
+     * insertion sort.  This is the best method for sorting small numbers
+     * of elements.  It requires O(n log n) compares, but O(n^2) data
+     * movement (worst case).
+     *
+     * If the initial part of the specified range is already sorted,
+     * this method can take advantage of it: the method assumes that the
+     * elements from index {@code lo}, inclusive, to {@code start},
+     * exclusive are already sorted.
+     *
+     * @param a the array in which a range is to be sorted
+     * @param lo the index of the first element in the range to be sorted
+     * @param hi the index after the last element in the range to be sorted
+     * @param start the index of the first element in the range that is
+     *        not already known to be sorted (@code lo <= start <= hi}
+     */
+    @SuppressWarnings("fallthrough")
+    private static void binarySort(Object[] a, int lo, int hi, int start) {
+        assert lo <= start && start <= hi;
+        if (start == lo)
+            start++;
+        for ( ; start < hi; start++) {
+            @SuppressWarnings("unchecked")
+            Comparable<Object> pivot = (Comparable) a[start];
+
+            // Set left (and right) to the index where a[start] (pivot) belongs
+            int left = lo;
+            int right = start;
+            assert left <= right;
+            /*
+             * Invariants:
+             *   pivot >= all in [lo, left).
+             *   pivot <  all in [right, start).
+             */
+            while (left < right) {
+                int mid = (left + right) >>> 1;
+                if (pivot.compareTo(a[mid]) < 0)
+                    right = mid;
+                else
+                    left = mid + 1;
+            }
+            assert left == right;
+
+            /*
+             * The invariants still hold: pivot >= all in [lo, left) and
+             * pivot < all in [left, start), so pivot belongs at left.  Note
+             * that if there are elements equal to pivot, left points to the
+             * first slot after them -- that's why this sort is stable.
+             * Slide elements over to make room to make room for pivot.
+             */
+            int n = start - left;  // The number of elements to move
+            // Switch is just an optimization for arraycopy in default case
+            switch(n) {
+                case 2:  a[left + 2] = a[left + 1];
+                case 1:  a[left + 1] = a[left];
+                         break;
+                default: System.arraycopy(a, left, a, left + 1, n);
+            }
+            a[left] = pivot;
+        }
+    }
+
+    /**
+     * Returns the length of the run beginning at the specified position in
+     * the specified array and reverses the run if it is descending (ensuring
+     * that the run will always be ascending when the method returns).
+     *
+     * A run is the longest ascending sequence with:
+     *
+     *    a[lo] <= a[lo + 1] <= a[lo + 2] <= ...
+     *
+     * or the longest descending sequence with:
+     *
+     *    a[lo] >  a[lo + 1] >  a[lo + 2] >  ...
+     *
+     * For its intended use in a stable mergesort, the strictness of the
+     * definition of "descending" is needed so that the call can safely
+     * reverse a descending sequence without violating stability.
+     *
+     * @param a the array in which a run is to be counted and possibly reversed
+     * @param lo index of the first element in the run
+     * @param hi index after the last element that may be contained in the run.
+              It is required that @code{lo < hi}.
+     * @return  the length of the run beginning at the specified position in
+     *          the specified array
+     */
+    @SuppressWarnings("unchecked")
+    private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {
+        assert lo < hi;
+        int runHi = lo + 1;
+        if (runHi == hi)
+            return 1;
+
+        // Find end of run, and reverse range if descending
+        if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending
+            while(runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0)
+                runHi++;
+            reverseRange(a, lo, runHi);
+        } else {                              // Ascending
+            while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0)
+                runHi++;
+        }
+
+        return runHi - lo;
+    }
+
+    /**
+     * Reverse the specified range of the specified array.
+     *
+     * @param a the array in which a range is to be reversed
+     * @param lo the index of the first element in the range to be reversed
+     * @param hi the index after the last element in the range to be reversed
+     */
+    private static void reverseRange(Object[] a, int lo, int hi) {
+        hi--;
+        while (lo < hi) {
+            Object t = a[lo];
+            a[lo++] = a[hi];
+            a[hi--] = t;
+        }
+    }
+
+    /**
+     * Returns the minimum acceptable run length for an array of the specified
+     * length. Natural runs shorter than this will be extended with
+     * {@link #binarySort}.
+     *
+     * Roughly speaking, the computation is:
+     *
+     *  If n < MIN_MERGE, return n (it's too small to bother with fancy stuff).
+     *  Else if n is an exact power of 2, return MIN_MERGE/2.
+     *  Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k
+     *   is close to, but strictly less than, an exact power of 2.
+     *
+     * For the rationale, see listsort.txt.
+     *
+     * @param n the length of the array to be sorted
+     * @return the length of the minimum run to be merged
+     */
+    private static int minRunLength(int n) {
+        assert n >= 0;
+        int r = 0;      // Becomes 1 if any 1 bits are shifted off
+        while (n >= MIN_MERGE) {
+            r |= (n & 1);
+            n >>= 1;
+        }
+        return n + r;
+    }
+
+    /**
+     * Pushes the specified run onto the pending-run stack.
+     *
+     * @param runBase index of the first element in the run
+     * @param runLen  the number of elements in the run
+     */
+    private void pushRun(int runBase, int runLen) {
+        this.runBase[stackSize] = runBase;
+        this.runLen[stackSize] = runLen;
+        stackSize++;
+    }
+
+    /**
+     * Examines the stack of runs waiting to be merged and merges adjacent runs
+     * until the stack invariants are reestablished:
+     *
+     *     1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1]
+     *     2. runLen[i - 2] > runLen[i - 1]
+     *
+     * This method is called each time a new run is pushed onto the stack,
+     * so the invariants are guaranteed to hold for i < stackSize upon
+     * entry to the method.
+     */
+    private void mergeCollapse() {
+        while (stackSize > 1) {
+            int n = stackSize - 2;
+            if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
+                if (runLen[n - 1] < runLen[n + 1])
+                    n--;
+                mergeAt(n);
+            } else if (runLen[n] <= runLen[n + 1]) {
+                mergeAt(n);
+            } else {
+                break; // Invariant is established
+            }
+        }
+    }
+
+    /**
+     * Merges all runs on the stack until only one remains.  This method is
+     * called once, to complete the sort.
+     */
+    private void mergeForceCollapse() {
+        while (stackSize > 1) {
+            int n = stackSize - 2;
+            if (n > 0 && runLen[n - 1] < runLen[n + 1])
+                n--;
+            mergeAt(n);
+        }
+    }
+
+    /**
+     * Merges the two runs at stack indices i and i+1.  Run i must be
+     * the penultimate or antepenultimate run on the stack.  In other words,
+     * i must be equal to stackSize-2 or stackSize-3.
+     *
+     * @param i stack index of the first of the two runs to merge
+     */
+    @SuppressWarnings("unchecked")
+    private void mergeAt(int i) {
+        assert stackSize >= 2;
+        assert i >= 0;
+        assert i == stackSize - 2 || i == stackSize - 3;
+
+        int base1 = runBase[i];
+        int len1 = runLen[i];
+        int base2 = runBase[i + 1];
+        int len2 = runLen[i + 1];
+        assert len1 > 0 && len2 > 0;
+        assert base1 + len1 == base2;
+
+        /*
+         * Record the length of the combined runs; if i is the 3rd-last
+         * run now, also slide over the last run (which isn't involved
+         * in this merge).  The current run (i+1) goes away in any case.
+         */
+        runLen[i] = len1 + len2;
+        if (i == stackSize - 3) {
+            runBase[i + 1] = runBase[i + 2];
+            runLen[i + 1] = runLen[i + 2];
+        }
+        stackSize--;
+
+        /*
+         * Find where the first element of run2 goes in run1. Prior elements
+         * in run1 can be ignored (because they're already in place).
+         */
+        int k = gallopRight((Comparable<Object>) a[base2], a, base1, len1, 0);
+        assert k >= 0;
+        base1 += k;
+        len1 -= k;
+        if (len1 == 0)
+            return;
+
+        /*
+         * Find where the last element of run1 goes in run2. Subsequent elements
+         * in run2 can be ignored (because they're already in place).
+         */
+        len2 = gallopLeft((Comparable<Object>) a[base1 + len1 - 1], a,
+                base2, len2, len2 - 1);
+        assert len2 >= 0;
+        if (len2 == 0)
+            return;
+
+        // Merge remaining runs, using tmp array with min(len1, len2) elements
+        if (len1 <= len2)
+            mergeLo(base1, len1, base2, len2);
+        else
+            mergeHi(base1, len1, base2, len2);
+    }
+
+    /**
+     * Locates the position at which to insert the specified key into the
+     * specified sorted range; if the range contains an element equal to key,
+     * returns the index of the leftmost equal element.
+     *
+     * @param key the key whose insertion point to search for
+     * @param a the array in which to search
+     * @param base the index of the first element in the range
+     * @param len the length of the range; must be > 0
+     * @param hint the index at which to begin the search, 0 <= hint < n.
+     *     The closer hint is to the result, the faster this method will run.
+     * @return the int k,  0 <= k <= n such that a[b + k - 1] < key <= a[b + k],
+     *    pretending that a[b - 1] is minus infinity and a[b + n] is infinity.
+     *    In other words, key belongs at index b + k; or in other words,
+     *    the first k elements of a should precede key, and the last n - k
+     *    should follow it.
+     */
+    private static int gallopLeft(Comparable<Object> key, Object[] a,
+            int base, int len, int hint) {
+        assert len > 0 && hint >= 0 && hint < len;
+
+        int lastOfs = 0;
+        int ofs = 1;
+        if (key.compareTo(a[base + hint]) > 0) {
+            // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs]
+            int maxOfs = len - hint;
+            while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) > 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to base
+            lastOfs += hint;
+            ofs += hint;
+        } else { // key <= a[base + hint]
+            // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs]
+            final int maxOfs = hint + 1;
+            while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) <= 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to base
+            int tmp = lastOfs;
+            lastOfs = hint - ofs;
+            ofs = hint - tmp;
+        }
+        assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
+
+        /*
+         * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere
+         * to the right of lastOfs but no farther right than ofs.  Do a binary
+         * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs].
+         */
+        lastOfs++;
+        while (lastOfs < ofs) {
+            int m = lastOfs + ((ofs - lastOfs) >>> 1);
+
+            if (key.compareTo(a[base + m]) > 0)
+                lastOfs = m + 1;  // a[base + m] < key
+            else
+                ofs = m;          // key <= a[base + m]
+        }
+        assert lastOfs == ofs;    // so a[base + ofs - 1] < key <= a[base + ofs]
+        return ofs;
+    }
+
+    /**
+     * Like gallopLeft, except that if the range contains an element equal to
+     * key, gallopRight returns the index after the rightmost equal element.
+     *
+     * @param key the key whose insertion point to search for
+     * @param a the array in which to search
+     * @param base the index of the first element in the range
+     * @param len the length of the range; must be > 0
+     * @param hint the index at which to begin the search, 0 <= hint < n.
+     *     The closer hint is to the result, the faster this method will run.
+     * @return the int k,  0 <= k <= n such that a[b + k - 1] <= key < a[b + k]
+     */
+    private static int gallopRight(Comparable<Object> key, Object[] a,
+            int base, int len, int hint) {
+        assert len > 0 && hint >= 0 && hint < len;
+
+        int ofs = 1;
+        int lastOfs = 0;
+        if (key.compareTo(a[base + hint]) < 0) {
+            // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs]
+            int maxOfs = hint + 1;
+            while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) < 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to b
+            int tmp = lastOfs;
+            lastOfs = hint - ofs;
+            ofs = hint - tmp;
+        } else { // a[b + hint] <= key
+            // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs]
+            int maxOfs = len - hint;
+            while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) >= 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to b
+            lastOfs += hint;
+            ofs += hint;
+        }
+        assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
+
+        /*
+         * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to
+         * the right of lastOfs but no farther right than ofs.  Do a binary
+         * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs].
+         */
+        lastOfs++;
+        while (lastOfs < ofs) {
+            int m = lastOfs + ((ofs - lastOfs) >>> 1);
+
+            if (key.compareTo(a[base + m]) < 0)
+                ofs = m;          // key < a[b + m]
+            else
+                lastOfs = m + 1;  // a[b + m] <= key
+        }
+        assert lastOfs == ofs;    // so a[b + ofs - 1] <= key < a[b + ofs]
+        return ofs;
+    }
+
+    /**
+     * Merges two adjacent runs in place, in a stable fashion.  The first
+     * element of the first run must be greater than the first element of the
+     * second run (a[base1] > a[base2]), and the last element of the first run
+     * (a[base1 + len1-1]) must be greater than all elements of the second run.
+     *
+     * For performance, this method should be called only when len1 <= len2;
+     * its twin, mergeHi should be called if len1 >= len2.  (Either method
+     * may be called if len1 == len2.)
+     *
+     * @param base1 index of first element in first run to be merged
+     * @param len1  length of first run to be merged (must be > 0)
+     * @param base2 index of first element in second run to be merged
+     *        (must be aBase + aLen)
+     * @param len2  length of second run to be merged (must be > 0)
+     */
+    @SuppressWarnings("unchecked")
+    private void mergeLo(int base1, int len1, int base2, int len2) {
+        assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
+
+        // Copy first run into temp array
+        Object[] a = this.a; // For performance
+        Object[] tmp = ensureCapacity(len1);
+        System.arraycopy(a, base1, tmp, 0, len1);
+
+        int cursor1 = 0;       // Indexes into tmp array
+        int cursor2 = base2;   // Indexes int a
+        int dest = base1;      // Indexes int a
+
+        // Move first element of second run and deal with degenerate cases
+        a[dest++] = a[cursor2++];
+        if (--len2 == 0) {
+            System.arraycopy(tmp, cursor1, a, dest, len1);
+            return;
+        }
+        if (len1 == 1) {
+            System.arraycopy(a, cursor2, a, dest, len2);
+            a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge
+            return;
+        }
+
+        int minGallop = this.minGallop;  // Use local variable for performance
+    outer:
+        while (true) {
+            int count1 = 0; // Number of times in a row that first run won
+            int count2 = 0; // Number of times in a row that second run won
+
+            /*
+             * Do the straightforward thing until (if ever) one run starts
+             * winning consistently.
+             */
+            do {
+                assert len1 > 1 && len2 > 0;
+                if (((Comparable) a[cursor2]).compareTo(tmp[cursor1]) < 0) {
+                    a[dest++] = a[cursor2++];
+                    count2++;
+                    count1 = 0;
+                    if (--len2 == 0)
+                        break outer;
+                } else {
+                    a[dest++] = tmp[cursor1++];
+                    count1++;
+                    count2 = 0;
+                    if (--len1 == 1)
+                        break outer;
+                }
+            } while ((count1 | count2) < minGallop);
+
+            /*
+             * One run is winning so consistently that galloping may be a
+             * huge win. So try that, and continue galloping until (if ever)
+             * neither run appears to be winning consistently anymore.
+             */
+            do {
+                assert len1 > 1 && len2 > 0;
+                count1 = gallopRight((Comparable) a[cursor2], tmp, cursor1, len1, 0);
+                if (count1 != 0) {
+                    System.arraycopy(tmp, cursor1, a, dest, count1);
+                    dest += count1;
+                    cursor1 += count1;
+                    len1 -= count1;
+                    if (len1 <= 1)  // len1 == 1 || len1 == 0
+                        break outer;
+                }
+                a[dest++] = a[cursor2++];
+                if (--len2 == 0)
+                    break outer;
+
+                count2 = gallopLeft((Comparable) tmp[cursor1], a, cursor2, len2, 0);
+                if (count2 != 0) {
+                    System.arraycopy(a, cursor2, a, dest, count2);
+                    dest += count2;
+                    cursor2 += count2;
+                    len2 -= count2;
+                    if (len2 == 0)
+                        break outer;
+                }
+                a[dest++] = tmp[cursor1++];
+                if (--len1 == 1)
+                    break outer;
+                minGallop--;
+            } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
+            if (minGallop < 0)
+                minGallop = 0;
+            minGallop += 2;  // Penalize for leaving gallop mode
+        }  // End of "outer" loop
+        this.minGallop = minGallop < 1 ? 1 : minGallop;  // Write back to field
+
+        if (len1 == 1) {
+            assert len2 > 0;
+            System.arraycopy(a, cursor2, a, dest, len2);
+            a[dest + len2] = tmp[cursor1]; //  Last elt of run 1 to end of merge
+        } else if (len1 == 0) {
+            throw new IllegalArgumentException(
+                "Comparison method violates its general contract!");
+        } else {
+            assert len2 == 0;
+            assert len1 > 1;
+            System.arraycopy(tmp, cursor1, a, dest, len1);
+        }
+    }
+
+    /**
+     * Like mergeLo, except that this method should be called only if
+     * len1 >= len2; mergeLo should be called if len1 <= len2.  (Either method
+     * may be called if len1 == len2.)
+     *
+     * @param base1 index of first element in first run to be merged
+     * @param len1  length of first run to be merged (must be > 0)
+     * @param base2 index of first element in second run to be merged
+     *        (must be aBase + aLen)
+     * @param len2  length of second run to be merged (must be > 0)
+     */
+    @SuppressWarnings("unchecked")
+    private void mergeHi(int base1, int len1, int base2, int len2) {
+        assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
+
+        // Copy second run into temp array
+        Object[] a = this.a; // For performance
+        Object[] tmp = ensureCapacity(len2);
+        System.arraycopy(a, base2, tmp, 0, len2);
+
+        int cursor1 = base1 + len1 - 1;  // Indexes into a
+        int cursor2 = len2 - 1;          // Indexes into tmp array
+        int dest = base2 + len2 - 1;     // Indexes into a
+
+        // Move last element of first run and deal with degenerate cases
+        a[dest--] = a[cursor1--];
+        if (--len1 == 0) {
+            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            return;
+        }
+        if (len2 == 1) {
+            dest -= len1;
+            cursor1 -= len1;
+            System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
+            a[dest] = tmp[cursor2];
+            return;
+        }
+
+        int minGallop = this.minGallop;  // Use local variable for performance
+    outer:
+        while (true) {
+            int count1 = 0; // Number of times in a row that first run won
+            int count2 = 0; // Number of times in a row that second run won
+
+            /*
+             * Do the straightforward thing until (if ever) one run
+             * appears to win consistently.
+             */
+            do {
+                assert len1 > 0 && len2 > 1;
+                if (((Comparable) tmp[cursor2]).compareTo(a[cursor1]) < 0) {
+                    a[dest--] = a[cursor1--];
+                    count1++;
+                    count2 = 0;
+                    if (--len1 == 0)
+                        break outer;
+                } else {
+                    a[dest--] = tmp[cursor2--];
+                    count2++;
+                    count1 = 0;
+                    if (--len2 == 1)
+                        break outer;
+                }
+            } while ((count1 | count2) < minGallop);
+
+            /*
+             * One run is winning so consistently that galloping may be a
+             * huge win. So try that, and continue galloping until (if ever)
+             * neither run appears to be winning consistently anymore.
+             */
+            do {
+                assert len1 > 0 && len2 > 1;
+                count1 = len1 - gallopRight((Comparable) tmp[cursor2], a, base1, len1, len1 - 1);
+                if (count1 != 0) {
+                    dest -= count1;
+                    cursor1 -= count1;
+                    len1 -= count1;
+                    System.arraycopy(a, cursor1 + 1, a, dest + 1, count1);
+                    if (len1 == 0)
+                        break outer;
+                }
+                a[dest--] = tmp[cursor2--];
+                if (--len2 == 1)
+                    break outer;
+
+                count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1);
+                if (count2 != 0) {
+                    dest -= count2;
+                    cursor2 -= count2;
+                    len2 -= count2;
+                    System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2);
+                    if (len2 <= 1)
+                        break outer; // len2 == 1 || len2 == 0
+                }
+                a[dest--] = a[cursor1--];
+                if (--len1 == 0)
+                    break outer;
+                minGallop--;
+            } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
+            if (minGallop < 0)
+                minGallop = 0;
+            minGallop += 2;  // Penalize for leaving gallop mode
+        }  // End of "outer" loop
+        this.minGallop = minGallop < 1 ? 1 : minGallop;  // Write back to field
+
+        if (len2 == 1) {
+            assert len1 > 0;
+            dest -= len1;
+            cursor1 -= len1;
+            System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
+            a[dest] = tmp[cursor2];  // Move first elt of run2 to front of merge
+        } else if (len2 == 0) {
+            throw new IllegalArgumentException(
+                "Comparison method violates its general contract!");
+        } else {
+            assert len1 == 0;
+            assert len2 > 0;
+            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+        }
+    }
+
+    /**
+     * Ensures that the external array tmp has at least the specified
+     * number of elements, increasing its size if necessary.  The size
+     * increases exponentially to ensure amortized linear time complexity.
+     *
+     * @param minCapacity the minimum required capacity of the tmp array
+     * @return tmp, whether or not it grew
+     */
+    private Object[]  ensureCapacity(int minCapacity) {
+        if (tmp.length < minCapacity) {
+            // Compute smallest power of 2 > minCapacity
+            int newSize = minCapacity;
+            newSize |= newSize >> 1;
+            newSize |= newSize >> 2;
+            newSize |= newSize >> 4;
+            newSize |= newSize >> 8;
+            newSize |= newSize >> 16;
+            newSize++;
+
+            if (newSize < 0) // Not bloody likely!
+                newSize = minCapacity;
+            else
+                newSize = Math.min(newSize, a.length >>> 1);
+
+            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+            Object[] newArray = new Object[newSize];
+            tmp = newArray;
+        }
+        return tmp;
+    }
+
+    /**
+     * Checks that fromIndex and toIndex are in range, and throws an
+     * appropriate exception if they aren't.
+     *
+     * @param arrayLen the length of the array
+     * @param fromIndex the index of the first element of the range
+     * @param toIndex the index after the last element of the range
+     * @throws IllegalArgumentException if fromIndex > toIndex
+     * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
+     *         or toIndex > arrayLen
+     */
+    private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
+        if (fromIndex > toIndex)
+            throw new IllegalArgumentException("fromIndex(" + fromIndex +
+                       ") > toIndex(" + toIndex+")");
+        if (fromIndex < 0)
+            throw new ArrayIndexOutOfBoundsException(fromIndex);
+        if (toIndex > arrayLen)
+            throw new ArrayIndexOutOfBoundsException(toIndex);
+    }
+}
--- a/jdk/src/share/classes/java/util/Formatter.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/util/Formatter.java	Tue Aug 18 19:53:43 2009 -0700
@@ -2818,15 +2818,18 @@
         }
 
         private void printString(Object arg, Locale l) throws IOException {
-            if (arg == null) {
-                print("null");
-            } else if (arg instanceof Formattable) {
+            if (arg instanceof Formattable) {
                 Formatter fmt = formatter;
                 if (formatter.locale() != l)
                     fmt = new Formatter(formatter.out(), l);
                 ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
             } else {
-                print(arg.toString());
+                if (f.contains(Flags.ALTERNATE))
+                    failMismatch(Flags.ALTERNATE, 's');
+                if (arg == null)
+                    print("null");
+                else
+                    print(arg.toString());
             }
         }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/util/TimSort.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,928 @@
+/*
+ * Copyright 2009 Google 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 java.util;
+
+/**
+ * A stable, adaptive, iterative mergesort that requires far fewer than
+ * n lg(n) comparisons when running on partially sorted arrays, while
+ * offering performance comparable to a traditional mergesort when run
+ * on random arrays.  Like all proper mergesorts, this sort is stable and
+ * runs O(n log n) time (worst case).  In the worst case, this sort requires
+ * temporary storage space for n/2 object references; in the best case,
+ * it requires only a small constant amount of space.
+ *
+ * This implementation was adapted from Tim Peters's list sort for
+ * Python, which is described in detail here:
+ *
+ *   http://svn.python.org/projects/python/trunk/Objects/listsort.txt
+ *
+ * Tim's C code may be found here:
+ *
+ *   http://svn.python.org/projects/python/trunk/Objects/listobject.c
+ *
+ * The underlying techniques are described in this paper (and may have
+ * even earlier origins):
+ *
+ *  "Optimistic Sorting and Information Theoretic Complexity"
+ *  Peter McIlroy
+ *  SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms),
+ *  pp 467-474, Austin, Texas, 25-27 January 1993.
+ *
+ * While the API to this class consists solely of static methods, it is
+ * (privately) instantiable; a TimSort instance holds the state of an ongoing
+ * sort, assuming the input array is large enough to warrant the full-blown
+ * TimSort. Small arrays are sorted in place, using a binary insertion sort.
+ *
+ * @author Josh Bloch
+ */
+class TimSort<T> {
+    /**
+     * This is the minimum sized sequence that will be merged.  Shorter
+     * sequences will be lengthened by calling binarySort.  If the entire
+     * array is less than this length, no merges will be performed.
+     *
+     * This constant should be a power of two.  It was 64 in Tim Peter's C
+     * implementation, but 32 was empirically determined to work better in
+     * this implementation.  In the unlikely event that you set this constant
+     * to be a number that's not a power of two, you'll need to change the
+     * {@link #minRunLength} computation.
+     *
+     * If you decrease this constant, you must change the stackLen
+     * computation in the TimSort constructor, or you risk an
+     * ArrayOutOfBounds exception.  See listsort.txt for a discussion
+     * of the minimum stack length required as a function of the length
+     * of the array being sorted and the minimum merge sequence length.
+     */
+    private static final int MIN_MERGE = 32;
+
+    /**
+     * The array being sorted.
+     */
+    private final T[] a;
+
+    /**
+     * The comparator for this sort.
+     */
+    private final Comparator<? super T> c;
+
+    /**
+     * When we get into galloping mode, we stay there until both runs win less
+     * often than MIN_GALLOP consecutive times.
+     */
+    private static final int  MIN_GALLOP = 7;
+
+    /**
+     * This controls when we get *into* galloping mode.  It is initialized
+     * to MIN_GALLOP.  The mergeLo and mergeHi methods nudge it higher for
+     * random data, and lower for highly structured data.
+     */
+    private int minGallop = MIN_GALLOP;
+
+    /**
+     * Maximum initial size of tmp array, which is used for merging.  The array
+     * can grow to accommodate demand.
+     *
+     * Unlike Tim's original C version, we do not allocate this much storage
+     * when sorting smaller arrays.  This change was required for performance.
+     */
+    private static final int INITIAL_TMP_STORAGE_LENGTH = 256;
+
+    /**
+     * Temp storage for merges.
+     */
+    private T[] tmp; // Actual runtime type will be Object[], regardless of T
+
+    /**
+     * A stack of pending runs yet to be merged.  Run i starts at
+     * address base[i] and extends for len[i] elements.  It's always
+     * true (so long as the indices are in bounds) that:
+     *
+     *     runBase[i] + runLen[i] == runBase[i + 1]
+     *
+     * so we could cut the storage for this, but it's a minor amount,
+     * and keeping all the info explicit simplifies the code.
+     */
+    private int stackSize = 0;  // Number of pending runs on stack
+    private final int[] runBase;
+    private final int[] runLen;
+
+    /**
+     * Creates a TimSort instance to maintain the state of an ongoing sort.
+     *
+     * @param a the array to be sorted
+     * @param c the comparator to determine the order of the sort
+     */
+    private TimSort(T[] a, Comparator<? super T> c) {
+        this.a = a;
+        this.c = c;
+
+        // Allocate temp storage (which may be increased later if necessary)
+        int len = a.length;
+        @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+        T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ?
+                                        len >>> 1 : INITIAL_TMP_STORAGE_LENGTH];
+        tmp = newArray;
+
+        /*
+         * Allocate runs-to-be-merged stack (which cannot be expanded).  The
+         * stack length requirements are described in listsort.txt.  The C
+         * version always uses the same stack length (85), but this was
+         * measured to be too expensive when sorting "mid-sized" arrays (e.g.,
+         * 100 elements) in Java.  Therefore, we use smaller (but sufficiently
+         * large) stack lengths for smaller arrays.  The "magic numbers" in the
+         * computation below must be changed if MIN_MERGE is decreased.  See
+         * the MIN_MERGE declaration above for more information.
+         */
+        int stackLen = (len <    120  ?  5 :
+                        len <   1542  ? 10 :
+                        len < 119151  ? 19 : 40);
+        runBase = new int[stackLen];
+        runLen = new int[stackLen];
+    }
+
+    /*
+     * The next two methods (which are package private and static) constitute
+     * the entire API of this class.  Each of these methods obeys the contract
+     * of the public method with the same signature in java.util.Arrays.
+     */
+
+    static <T> void sort(T[] a, Comparator<? super T> c) {
+        sort(a, 0, a.length, c);
+    }
+
+    static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c) {
+        if (c == null) {
+            Arrays.sort(a, lo, hi);
+            return;
+        }
+
+        rangeCheck(a.length, lo, hi);
+        int nRemaining  = hi - lo;
+        if (nRemaining < 2)
+            return;  // Arrays of size 0 and 1 are always sorted
+
+        // If array is small, do a "mini-TimSort" with no merges
+        if (nRemaining < MIN_MERGE) {
+            int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
+            binarySort(a, lo, hi, lo + initRunLen, c);
+            return;
+        }
+
+        /**
+         * March over the array once, left to right, finding natural runs,
+         * extending short natural runs to minRun elements, and merging runs
+         * to maintain stack invariant.
+         */
+        TimSort<T> ts = new TimSort<T>(a, c);
+        int minRun = minRunLength(nRemaining);
+        do {
+            // Identify next run
+            int runLen = countRunAndMakeAscending(a, lo, hi, c);
+
+            // If run is short, extend to min(minRun, nRemaining)
+            if (runLen < minRun) {
+                int force = nRemaining <= minRun ? nRemaining : minRun;
+                binarySort(a, lo, lo + force, lo + runLen, c);
+                runLen = force;
+            }
+
+            // Push run onto pending-run stack, and maybe merge
+            ts.pushRun(lo, runLen);
+            ts.mergeCollapse();
+
+            // Advance to find next run
+            lo += runLen;
+            nRemaining -= runLen;
+        } while (nRemaining != 0);
+
+        // Merge all remaining runs to complete sort
+        assert lo == hi;
+        ts.mergeForceCollapse();
+        assert ts.stackSize == 1;
+    }
+
+    /**
+     * Sorts the specified portion of the specified array using a binary
+     * insertion sort.  This is the best method for sorting small numbers
+     * of elements.  It requires O(n log n) compares, but O(n^2) data
+     * movement (worst case).
+     *
+     * If the initial part of the specified range is already sorted,
+     * this method can take advantage of it: the method assumes that the
+     * elements from index {@code lo}, inclusive, to {@code start},
+     * exclusive are already sorted.
+     *
+     * @param a the array in which a range is to be sorted
+     * @param lo the index of the first element in the range to be sorted
+     * @param hi the index after the last element in the range to be sorted
+     * @param start the index of the first element in the range that is
+     *        not already known to be sorted (@code lo <= start <= hi}
+     * @param c comparator to used for the sort
+     */
+    @SuppressWarnings("fallthrough")
+    private static <T> void binarySort(T[] a, int lo, int hi, int start,
+                                       Comparator<? super T> c) {
+        assert lo <= start && start <= hi;
+        if (start == lo)
+            start++;
+        for ( ; start < hi; start++) {
+            T pivot = a[start];
+
+            // Set left (and right) to the index where a[start] (pivot) belongs
+            int left = lo;
+            int right = start;
+            assert left <= right;
+            /*
+             * Invariants:
+             *   pivot >= all in [lo, left).
+             *   pivot <  all in [right, start).
+             */
+            while (left < right) {
+                int mid = (left + right) >>> 1;
+                if (c.compare(pivot, a[mid]) < 0)
+                    right = mid;
+                else
+                    left = mid + 1;
+            }
+            assert left == right;
+
+            /*
+             * The invariants still hold: pivot >= all in [lo, left) and
+             * pivot < all in [left, start), so pivot belongs at left.  Note
+             * that if there are elements equal to pivot, left points to the
+             * first slot after them -- that's why this sort is stable.
+             * Slide elements over to make room to make room for pivot.
+             */
+            int n = start - left;  // The number of elements to move
+            // Switch is just an optimization for arraycopy in default case
+            switch(n) {
+                case 2:  a[left + 2] = a[left + 1];
+                case 1:  a[left + 1] = a[left];
+                         break;
+                default: System.arraycopy(a, left, a, left + 1, n);
+            }
+            a[left] = pivot;
+        }
+    }
+
+    /**
+     * Returns the length of the run beginning at the specified position in
+     * the specified array and reverses the run if it is descending (ensuring
+     * that the run will always be ascending when the method returns).
+     *
+     * A run is the longest ascending sequence with:
+     *
+     *    a[lo] <= a[lo + 1] <= a[lo + 2] <= ...
+     *
+     * or the longest descending sequence with:
+     *
+     *    a[lo] >  a[lo + 1] >  a[lo + 2] >  ...
+     *
+     * For its intended use in a stable mergesort, the strictness of the
+     * definition of "descending" is needed so that the call can safely
+     * reverse a descending sequence without violating stability.
+     *
+     * @param a the array in which a run is to be counted and possibly reversed
+     * @param lo index of the first element in the run
+     * @param hi index after the last element that may be contained in the run.
+              It is required that @code{lo < hi}.
+     * @param c the comparator to used for the sort
+     * @return  the length of the run beginning at the specified position in
+     *          the specified array
+     */
+    private static <T> int countRunAndMakeAscending(T[] a, int lo, int hi,
+                                                    Comparator<? super T> c) {
+        assert lo < hi;
+        int runHi = lo + 1;
+        if (runHi == hi)
+            return 1;
+
+        // Find end of run, and reverse range if descending
+        if (c.compare(a[runHi++], a[lo]) < 0) { // Descending
+            while(runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
+                runHi++;
+            reverseRange(a, lo, runHi);
+        } else {                              // Ascending
+            while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0)
+                runHi++;
+        }
+
+        return runHi - lo;
+    }
+
+    /**
+     * Reverse the specified range of the specified array.
+     *
+     * @param a the array in which a range is to be reversed
+     * @param lo the index of the first element in the range to be reversed
+     * @param hi the index after the last element in the range to be reversed
+     */
+    private static void reverseRange(Object[] a, int lo, int hi) {
+        hi--;
+        while (lo < hi) {
+            Object t = a[lo];
+            a[lo++] = a[hi];
+            a[hi--] = t;
+        }
+    }
+
+    /**
+     * Returns the minimum acceptable run length for an array of the specified
+     * length. Natural runs shorter than this will be extended with
+     * {@link #binarySort}.
+     *
+     * Roughly speaking, the computation is:
+     *
+     *  If n < MIN_MERGE, return n (it's too small to bother with fancy stuff).
+     *  Else if n is an exact power of 2, return MIN_MERGE/2.
+     *  Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k
+     *   is close to, but strictly less than, an exact power of 2.
+     *
+     * For the rationale, see listsort.txt.
+     *
+     * @param n the length of the array to be sorted
+     * @return the length of the minimum run to be merged
+     */
+    private static int minRunLength(int n) {
+        assert n >= 0;
+        int r = 0;      // Becomes 1 if any 1 bits are shifted off
+        while (n >= MIN_MERGE) {
+            r |= (n & 1);
+            n >>= 1;
+        }
+        return n + r;
+    }
+
+    /**
+     * Pushes the specified run onto the pending-run stack.
+     *
+     * @param runBase index of the first element in the run
+     * @param runLen  the number of elements in the run
+     */
+    private void pushRun(int runBase, int runLen) {
+        this.runBase[stackSize] = runBase;
+        this.runLen[stackSize] = runLen;
+        stackSize++;
+    }
+
+    /**
+     * Examines the stack of runs waiting to be merged and merges adjacent runs
+     * until the stack invariants are reestablished:
+     *
+     *     1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1]
+     *     2. runLen[i - 2] > runLen[i - 1]
+     *
+     * This method is called each time a new run is pushed onto the stack,
+     * so the invariants are guaranteed to hold for i < stackSize upon
+     * entry to the method.
+     */
+    private void mergeCollapse() {
+        while (stackSize > 1) {
+            int n = stackSize - 2;
+            if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) {
+                if (runLen[n - 1] < runLen[n + 1])
+                    n--;
+                mergeAt(n);
+            } else if (runLen[n] <= runLen[n + 1]) {
+                mergeAt(n);
+            } else {
+                break; // Invariant is established
+            }
+        }
+    }
+
+    /**
+     * Merges all runs on the stack until only one remains.  This method is
+     * called once, to complete the sort.
+     */
+    private void mergeForceCollapse() {
+        while (stackSize > 1) {
+            int n = stackSize - 2;
+            if (n > 0 && runLen[n - 1] < runLen[n + 1])
+                n--;
+            mergeAt(n);
+        }
+    }
+
+    /**
+     * Merges the two runs at stack indices i and i+1.  Run i must be
+     * the penultimate or antepenultimate run on the stack.  In other words,
+     * i must be equal to stackSize-2 or stackSize-3.
+     *
+     * @param i stack index of the first of the two runs to merge
+     */
+    private void mergeAt(int i) {
+        assert stackSize >= 2;
+        assert i >= 0;
+        assert i == stackSize - 2 || i == stackSize - 3;
+
+        int base1 = runBase[i];
+        int len1 = runLen[i];
+        int base2 = runBase[i + 1];
+        int len2 = runLen[i + 1];
+        assert len1 > 0 && len2 > 0;
+        assert base1 + len1 == base2;
+
+        /*
+         * Record the length of the combined runs; if i is the 3rd-last
+         * run now, also slide over the last run (which isn't involved
+         * in this merge).  The current run (i+1) goes away in any case.
+         */
+        runLen[i] = len1 + len2;
+        if (i == stackSize - 3) {
+            runBase[i + 1] = runBase[i + 2];
+            runLen[i + 1] = runLen[i + 2];
+        }
+        stackSize--;
+
+        /*
+         * Find where the first element of run2 goes in run1. Prior elements
+         * in run1 can be ignored (because they're already in place).
+         */
+        int k = gallopRight(a[base2], a, base1, len1, 0, c);
+        assert k >= 0;
+        base1 += k;
+        len1 -= k;
+        if (len1 == 0)
+            return;
+
+        /*
+         * Find where the last element of run1 goes in run2. Subsequent elements
+         * in run2 can be ignored (because they're already in place).
+         */
+        len2 = gallopLeft(a[base1 + len1 - 1], a, base2, len2, len2 - 1, c);
+        assert len2 >= 0;
+        if (len2 == 0)
+            return;
+
+        // Merge remaining runs, using tmp array with min(len1, len2) elements
+        if (len1 <= len2)
+            mergeLo(base1, len1, base2, len2);
+        else
+            mergeHi(base1, len1, base2, len2);
+    }
+
+    /**
+     * Locates the position at which to insert the specified key into the
+     * specified sorted range; if the range contains an element equal to key,
+     * returns the index of the leftmost equal element.
+     *
+     * @param key the key whose insertion point to search for
+     * @param a the array in which to search
+     * @param base the index of the first element in the range
+     * @param len the length of the range; must be > 0
+     * @param hint the index at which to begin the search, 0 <= hint < n.
+     *     The closer hint is to the result, the faster this method will run.
+     * @param c the comparator used to order the range, and to search
+     * @return the int k,  0 <= k <= n such that a[b + k - 1] < key <= a[b + k],
+     *    pretending that a[b - 1] is minus infinity and a[b + n] is infinity.
+     *    In other words, key belongs at index b + k; or in other words,
+     *    the first k elements of a should precede key, and the last n - k
+     *    should follow it.
+     */
+    private static <T> int gallopLeft(T key, T[] a, int base, int len, int hint,
+                                      Comparator<? super T> c) {
+        assert len > 0 && hint >= 0 && hint < len;
+        int lastOfs = 0;
+        int ofs = 1;
+        if (c.compare(key, a[base + hint]) > 0) {
+            // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs]
+            int maxOfs = len - hint;
+            while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) > 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to base
+            lastOfs += hint;
+            ofs += hint;
+        } else { // key <= a[base + hint]
+            // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs]
+            final int maxOfs = hint + 1;
+            while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) <= 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to base
+            int tmp = lastOfs;
+            lastOfs = hint - ofs;
+            ofs = hint - tmp;
+        }
+        assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
+
+        /*
+         * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere
+         * to the right of lastOfs but no farther right than ofs.  Do a binary
+         * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs].
+         */
+        lastOfs++;
+        while (lastOfs < ofs) {
+            int m = lastOfs + ((ofs - lastOfs) >>> 1);
+
+            if (c.compare(key, a[base + m]) > 0)
+                lastOfs = m + 1;  // a[base + m] < key
+            else
+                ofs = m;          // key <= a[base + m]
+        }
+        assert lastOfs == ofs;    // so a[base + ofs - 1] < key <= a[base + ofs]
+        return ofs;
+    }
+
+    /**
+     * Like gallopLeft, except that if the range contains an element equal to
+     * key, gallopRight returns the index after the rightmost equal element.
+     *
+     * @param key the key whose insertion point to search for
+     * @param a the array in which to search
+     * @param base the index of the first element in the range
+     * @param len the length of the range; must be > 0
+     * @param hint the index at which to begin the search, 0 <= hint < n.
+     *     The closer hint is to the result, the faster this method will run.
+     * @param c the comparator used to order the range, and to search
+     * @return the int k,  0 <= k <= n such that a[b + k - 1] <= key < a[b + k]
+     */
+    private static <T> int gallopRight(T key, T[] a, int base, int len,
+                                       int hint, Comparator<? super T> c) {
+        assert len > 0 && hint >= 0 && hint < len;
+
+        int ofs = 1;
+        int lastOfs = 0;
+        if (c.compare(key, a[base + hint]) < 0) {
+            // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs]
+            int maxOfs = hint + 1;
+            while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) < 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to b
+            int tmp = lastOfs;
+            lastOfs = hint - ofs;
+            ofs = hint - tmp;
+        } else { // a[b + hint] <= key
+            // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs]
+            int maxOfs = len - hint;
+            while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) >= 0) {
+                lastOfs = ofs;
+                ofs = (ofs << 1) + 1;
+                if (ofs <= 0)   // int overflow
+                    ofs = maxOfs;
+            }
+            if (ofs > maxOfs)
+                ofs = maxOfs;
+
+            // Make offsets relative to b
+            lastOfs += hint;
+            ofs += hint;
+        }
+        assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
+
+        /*
+         * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to
+         * the right of lastOfs but no farther right than ofs.  Do a binary
+         * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs].
+         */
+        lastOfs++;
+        while (lastOfs < ofs) {
+            int m = lastOfs + ((ofs - lastOfs) >>> 1);
+
+            if (c.compare(key, a[base + m]) < 0)
+                ofs = m;          // key < a[b + m]
+            else
+                lastOfs = m + 1;  // a[b + m] <= key
+        }
+        assert lastOfs == ofs;    // so a[b + ofs - 1] <= key < a[b + ofs]
+        return ofs;
+    }
+
+    /**
+     * Merges two adjacent runs in place, in a stable fashion.  The first
+     * element of the first run must be greater than the first element of the
+     * second run (a[base1] > a[base2]), and the last element of the first run
+     * (a[base1 + len1-1]) must be greater than all elements of the second run.
+     *
+     * For performance, this method should be called only when len1 <= len2;
+     * its twin, mergeHi should be called if len1 >= len2.  (Either method
+     * may be called if len1 == len2.)
+     *
+     * @param base1 index of first element in first run to be merged
+     * @param len1  length of first run to be merged (must be > 0)
+     * @param base2 index of first element in second run to be merged
+     *        (must be aBase + aLen)
+     * @param len2  length of second run to be merged (must be > 0)
+     */
+    private void mergeLo(int base1, int len1, int base2, int len2) {
+        assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
+
+        // Copy first run into temp array
+        T[] a = this.a; // For performance
+        T[] tmp = ensureCapacity(len1);
+        System.arraycopy(a, base1, tmp, 0, len1);
+
+        int cursor1 = 0;       // Indexes into tmp array
+        int cursor2 = base2;   // Indexes int a
+        int dest = base1;      // Indexes int a
+
+        // Move first element of second run and deal with degenerate cases
+        a[dest++] = a[cursor2++];
+        if (--len2 == 0) {
+            System.arraycopy(tmp, cursor1, a, dest, len1);
+            return;
+        }
+        if (len1 == 1) {
+            System.arraycopy(a, cursor2, a, dest, len2);
+            a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge
+            return;
+        }
+
+        Comparator<? super T> c = this.c;  // Use local variable for performance
+        int minGallop = this.minGallop;    //  "    "       "     "      "
+    outer:
+        while (true) {
+            int count1 = 0; // Number of times in a row that first run won
+            int count2 = 0; // Number of times in a row that second run won
+
+            /*
+             * Do the straightforward thing until (if ever) one run starts
+             * winning consistently.
+             */
+            do {
+                assert len1 > 1 && len2 > 0;
+                if (c.compare(a[cursor2], tmp[cursor1]) < 0) {
+                    a[dest++] = a[cursor2++];
+                    count2++;
+                    count1 = 0;
+                    if (--len2 == 0)
+                        break outer;
+                } else {
+                    a[dest++] = tmp[cursor1++];
+                    count1++;
+                    count2 = 0;
+                    if (--len1 == 1)
+                        break outer;
+                }
+            } while ((count1 | count2) < minGallop);
+
+            /*
+             * One run is winning so consistently that galloping may be a
+             * huge win. So try that, and continue galloping until (if ever)
+             * neither run appears to be winning consistently anymore.
+             */
+            do {
+                assert len1 > 1 && len2 > 0;
+                count1 = gallopRight(a[cursor2], tmp, cursor1, len1, 0, c);
+                if (count1 != 0) {
+                    System.arraycopy(tmp, cursor1, a, dest, count1);
+                    dest += count1;
+                    cursor1 += count1;
+                    len1 -= count1;
+                    if (len1 <= 1) // len1 == 1 || len1 == 0
+                        break outer;
+                }
+                a[dest++] = a[cursor2++];
+                if (--len2 == 0)
+                    break outer;
+
+                count2 = gallopLeft(tmp[cursor1], a, cursor2, len2, 0, c);
+                if (count2 != 0) {
+                    System.arraycopy(a, cursor2, a, dest, count2);
+                    dest += count2;
+                    cursor2 += count2;
+                    len2 -= count2;
+                    if (len2 == 0)
+                        break outer;
+                }
+                a[dest++] = tmp[cursor1++];
+                if (--len1 == 1)
+                    break outer;
+                minGallop--;
+            } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
+            if (minGallop < 0)
+                minGallop = 0;
+            minGallop += 2;  // Penalize for leaving gallop mode
+        }  // End of "outer" loop
+        this.minGallop = minGallop < 1 ? 1 : minGallop;  // Write back to field
+
+        if (len1 == 1) {
+            assert len2 > 0;
+            System.arraycopy(a, cursor2, a, dest, len2);
+            a[dest + len2] = tmp[cursor1]; //  Last elt of run 1 to end of merge
+        } else if (len1 == 0) {
+            throw new IllegalArgumentException(
+                "Comparison method violates its general contract!");
+        } else {
+            assert len2 == 0;
+            assert len1 > 1;
+            System.arraycopy(tmp, cursor1, a, dest, len1);
+        }
+    }
+
+    /**
+     * Like mergeLo, except that this method should be called only if
+     * len1 >= len2; mergeLo should be called if len1 <= len2.  (Either method
+     * may be called if len1 == len2.)
+     *
+     * @param base1 index of first element in first run to be merged
+     * @param len1  length of first run to be merged (must be > 0)
+     * @param base2 index of first element in second run to be merged
+     *        (must be aBase + aLen)
+     * @param len2  length of second run to be merged (must be > 0)
+     */
+    private void mergeHi(int base1, int len1, int base2, int len2) {
+        assert len1 > 0 && len2 > 0 && base1 + len1 == base2;
+
+        // Copy second run into temp array
+        T[] a = this.a; // For performance
+        T[] tmp = ensureCapacity(len2);
+        System.arraycopy(a, base2, tmp, 0, len2);
+
+        int cursor1 = base1 + len1 - 1;  // Indexes into a
+        int cursor2 = len2 - 1;          // Indexes into tmp array
+        int dest = base2 + len2 - 1;     // Indexes into a
+
+        // Move last element of first run and deal with degenerate cases
+        a[dest--] = a[cursor1--];
+        if (--len1 == 0) {
+            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+            return;
+        }
+        if (len2 == 1) {
+            dest -= len1;
+            cursor1 -= len1;
+            System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
+            a[dest] = tmp[cursor2];
+            return;
+        }
+
+        Comparator<? super T> c = this.c;  // Use local variable for performance
+        int minGallop = this.minGallop;    //  "    "       "     "      "
+    outer:
+        while (true) {
+            int count1 = 0; // Number of times in a row that first run won
+            int count2 = 0; // Number of times in a row that second run won
+
+            /*
+             * Do the straightforward thing until (if ever) one run
+             * appears to win consistently.
+             */
+            do {
+                assert len1 > 0 && len2 > 1;
+                if (c.compare(tmp[cursor2], a[cursor1]) < 0) {
+                    a[dest--] = a[cursor1--];
+                    count1++;
+                    count2 = 0;
+                    if (--len1 == 0)
+                        break outer;
+                } else {
+                    a[dest--] = tmp[cursor2--];
+                    count2++;
+                    count1 = 0;
+                    if (--len2 == 1)
+                        break outer;
+                }
+            } while ((count1 | count2) < minGallop);
+
+            /*
+             * One run is winning so consistently that galloping may be a
+             * huge win. So try that, and continue galloping until (if ever)
+             * neither run appears to be winning consistently anymore.
+             */
+            do {
+                assert len1 > 0 && len2 > 1;
+                count1 = len1 - gallopRight(tmp[cursor2], a, base1, len1, len1 - 1, c);
+                if (count1 != 0) {
+                    dest -= count1;
+                    cursor1 -= count1;
+                    len1 -= count1;
+                    System.arraycopy(a, cursor1 + 1, a, dest + 1, count1);
+                    if (len1 == 0)
+                        break outer;
+                }
+                a[dest--] = tmp[cursor2--];
+                if (--len2 == 1)
+                    break outer;
+
+                count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c);
+                if (count2 != 0) {
+                    dest -= count2;
+                    cursor2 -= count2;
+                    len2 -= count2;
+                    System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2);
+                    if (len2 <= 1)  // len2 == 1 || len2 == 0
+                        break outer;
+                }
+                a[dest--] = a[cursor1--];
+                if (--len1 == 0)
+                    break outer;
+                minGallop--;
+            } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP);
+            if (minGallop < 0)
+                minGallop = 0;
+            minGallop += 2;  // Penalize for leaving gallop mode
+        }  // End of "outer" loop
+        this.minGallop = minGallop < 1 ? 1 : minGallop;  // Write back to field
+
+        if (len2 == 1) {
+            assert len1 > 0;
+            dest -= len1;
+            cursor1 -= len1;
+            System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
+            a[dest] = tmp[cursor2];  // Move first elt of run2 to front of merge
+        } else if (len2 == 0) {
+            throw new IllegalArgumentException(
+                "Comparison method violates its general contract!");
+        } else {
+            assert len1 == 0;
+            assert len2 > 0;
+            System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2);
+        }
+    }
+
+    /**
+     * Ensures that the external array tmp has at least the specified
+     * number of elements, increasing its size if necessary.  The size
+     * increases exponentially to ensure amortized linear time complexity.
+     *
+     * @param minCapacity the minimum required capacity of the tmp array
+     * @return tmp, whether or not it grew
+     */
+    private T[] ensureCapacity(int minCapacity) {
+        if (tmp.length < minCapacity) {
+            // Compute smallest power of 2 > minCapacity
+            int newSize = minCapacity;
+            newSize |= newSize >> 1;
+            newSize |= newSize >> 2;
+            newSize |= newSize >> 4;
+            newSize |= newSize >> 8;
+            newSize |= newSize >> 16;
+            newSize++;
+
+            if (newSize < 0) // Not bloody likely!
+                newSize = minCapacity;
+            else
+                newSize = Math.min(newSize, a.length >>> 1);
+
+            @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"})
+            T[] newArray = (T[]) new Object[newSize];
+            tmp = newArray;
+        }
+        return tmp;
+    }
+
+    /**
+     * Checks that fromIndex and toIndex are in range, and throws an
+     * appropriate exception if they aren't.
+     *
+     * @param arrayLen the length of the array
+     * @param fromIndex the index of the first element of the range
+     * @param toIndex the index after the last element of the range
+     * @throws IllegalArgumentException if fromIndex > toIndex
+     * @throws ArrayIndexOutOfBoundsException if fromIndex < 0
+     *         or toIndex > arrayLen
+     */
+    private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
+        if (fromIndex > toIndex)
+            throw new IllegalArgumentException("fromIndex(" + fromIndex +
+                       ") > toIndex(" + toIndex+")");
+        if (fromIndex < 0)
+            throw new ArrayIndexOutOfBoundsException(fromIndex);
+        if (toIndex > arrayLen)
+            throw new ArrayIndexOutOfBoundsException(toIndex);
+    }
+}
--- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Tue Aug 18 19:53:43 2009 -0700
@@ -34,9 +34,13 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.atomic.*;
 
+import java.util.AbstractQueue;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Queue;
 
 /**
  * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes.
@@ -47,9 +51,9 @@
  * queue the shortest time. New elements
  * are inserted at the tail of the queue, and the queue retrieval
  * operations obtain elements at the head of the queue.
- * A <tt>ConcurrentLinkedQueue</tt> is an appropriate choice when
+ * A {@code ConcurrentLinkedQueue} is an appropriate choice when
  * many threads will share access to a common collection.
- * This queue does not permit <tt>null</tt> elements.
+ * This queue does not permit {@code null} elements.
  *
  * <p>This implementation employs an efficient &quot;wait-free&quot;
  * algorithm based on one described in <a
@@ -57,7 +61,7 @@
  * Fast, and Practical Non-Blocking and Blocking Concurrent Queue
  * Algorithms</a> by Maged M. Michael and Michael L. Scott.
  *
- * <p>Beware that, unlike in most collections, the <tt>size</tt> method
+ * <p>Beware that, unlike in most collections, the {@code size} method
  * is <em>NOT</em> a constant-time operation. Because of the
  * asynchronous nature of these queues, determining the current number
  * of elements requires a traversal of the elements.
@@ -87,51 +91,102 @@
     private static final long serialVersionUID = 196745693267521676L;
 
     /*
-     * This is a straight adaptation of Michael & Scott algorithm.
-     * For explanation, read the paper.  The only (minor) algorithmic
-     * difference is that this version supports lazy deletion of
-     * internal nodes (method remove(Object)) -- remove CAS'es item
-     * fields to null. The normal queue operations unlink but then
-     * pass over nodes with null item fields. Similarly, iteration
-     * methods ignore those with nulls.
+     * This is a modification of the Michael & Scott algorithm,
+     * adapted for a garbage-collected environment, with support for
+     * interior node deletion (to support remove(Object)).  For
+     * explanation, read the paper.
      *
-     * Also note that like most non-blocking algorithms in this
-     * package, this implementation relies on the fact that in garbage
+     * Note that like most non-blocking algorithms in this package,
+     * this implementation relies on the fact that in garbage
      * collected systems, there is no possibility of ABA problems due
      * to recycled nodes, so there is no need to use "counted
      * pointers" or related techniques seen in versions used in
      * non-GC'ed settings.
+     *
+     * The fundamental invariants are:
+     * - There is exactly one (last) Node with a null next reference,
+     *   which is CASed when enqueueing.  This last Node can be
+     *   reached in O(1) time from tail, but tail is merely an
+     *   optimization - it can always be reached in O(N) time from
+     *   head as well.
+     * - The elements contained in the queue are the non-null items in
+     *   Nodes that are reachable from head.  CASing the item
+     *   reference of a Node to null atomically removes it from the
+     *   queue.  Reachability of all elements from head must remain
+     *   true even in the case of concurrent modifications that cause
+     *   head to advance.  A dequeued Node may remain in use
+     *   indefinitely due to creation of an Iterator or simply a
+     *   poll() that has lost its time slice.
+     *
+     * The above might appear to imply that all Nodes are GC-reachable
+     * from a predecessor dequeued Node.  That would cause two problems:
+     * - allow a rogue Iterator to cause unbounded memory retention
+     * - cause cross-generational linking of old Nodes to new Nodes if
+     *   a Node was tenured while live, which generational GCs have a
+     *   hard time dealing with, causing repeated major collections.
+     * However, only non-deleted Nodes need to be reachable from
+     * dequeued Nodes, and reachability does not necessarily have to
+     * be of the kind understood by the GC.  We use the trick of
+     * linking a Node that has just been dequeued to itself.  Such a
+     * self-link implicitly means to advance to head.
+     *
+     * Both head and tail are permitted to lag.  In fact, failing to
+     * update them every time one could is a significant optimization
+     * (fewer CASes). This is controlled by local "hops" variables
+     * that only trigger helping-CASes after experiencing multiple
+     * lags.
+     *
+     * Since head and tail are updated concurrently and independently,
+     * it is possible for tail to lag behind head (why not)?
+     *
+     * CASing a Node's item reference to null atomically removes the
+     * element from the queue.  Iterators skip over Nodes with null
+     * items.  Prior implementations of this class had a race between
+     * poll() and remove(Object) where the same element would appear
+     * to be successfully removed by two concurrent operations.  The
+     * method remove(Object) also lazily unlinks deleted Nodes, but
+     * this is merely an optimization.
+     *
+     * When constructing a Node (before enqueuing it) we avoid paying
+     * for a volatile write to item by using lazySet instead of a
+     * normal write.  This allows the cost of enqueue to be
+     * "one-and-a-half" CASes.
+     *
+     * Both head and tail may or may not point to a Node with a
+     * non-null item.  If the queue is empty, all items must of course
+     * be null.  Upon creation, both head and tail refer to a dummy
+     * Node with null item.  Both head and tail are only updated using
+     * CAS, so they never regress, although again this is merely an
+     * optimization.
      */
 
     private static class Node<E> {
         private volatile E item;
         private volatile Node<E> next;
 
-        private static final
-            AtomicReferenceFieldUpdater<Node, Node>
-            nextUpdater =
-            AtomicReferenceFieldUpdater.newUpdater
-            (Node.class, Node.class, "next");
-        private static final
-            AtomicReferenceFieldUpdater<Node, Object>
-            itemUpdater =
-            AtomicReferenceFieldUpdater.newUpdater
-            (Node.class, Object.class, "item");
-
-        Node(E x) { item = x; }
-
-        Node(E x, Node<E> n) { item = x; next = n; }
+        Node(E item) {
+            // Piggyback on imminent casNext()
+            lazySetItem(item);
+        }
 
         E getItem() {
             return item;
         }
 
         boolean casItem(E cmp, E val) {
-            return itemUpdater.compareAndSet(this, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val);
         }
 
         void setItem(E val) {
-            itemUpdater.set(this, val);
+            item = val;
+        }
+
+        void lazySetItem(E val) {
+            UNSAFE.putOrderedObject(this, itemOffset, val);
+        }
+
+        void lazySetNext(Node<E> val) {
+            UNSAFE.putOrderedObject(this, nextOffset, val);
         }
 
         Node<E> getNext() {
@@ -139,52 +194,55 @@
         }
 
         boolean casNext(Node<E> cmp, Node<E> val) {
-            return nextUpdater.compareAndSet(this, cmp, val);
+            return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val);
         }
 
-        void setNext(Node<E> val) {
-            nextUpdater.set(this, val);
-        }
+        // Unsafe mechanics
 
+        private static final sun.misc.Unsafe UNSAFE =
+            sun.misc.Unsafe.getUnsafe();
+        private static final long nextOffset =
+            objectFieldOffset(UNSAFE, "next", Node.class);
+        private static final long itemOffset =
+            objectFieldOffset(UNSAFE, "item", Node.class);
     }
 
-    private static final
-        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
-        tailUpdater =
-        AtomicReferenceFieldUpdater.newUpdater
-        (ConcurrentLinkedQueue.class, Node.class, "tail");
-    private static final
-        AtomicReferenceFieldUpdater<ConcurrentLinkedQueue, Node>
-        headUpdater =
-        AtomicReferenceFieldUpdater.newUpdater
-        (ConcurrentLinkedQueue.class,  Node.class, "head");
-
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return tailUpdater.compareAndSet(this, cmp, val);
-    }
-
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return headUpdater.compareAndSet(this, cmp, val);
-    }
-
+    /**
+     * A node from which the first live (non-deleted) node (if any)
+     * can be reached in O(1) time.
+     * Invariants:
+     * - all live nodes are reachable from head via succ()
+     * - head != null
+     * - (tmp = head).next != tmp || tmp != head
+     * Non-invariants:
+     * - head.item may or may not be null.
+     * - it is permitted for tail to lag behind head, that is, for tail
+     *   to not be reachable from head!
+     */
+    private transient volatile Node<E> head = new Node<E>(null);
 
     /**
-     * Pointer to header node, initialized to a dummy node.  The first
-     * actual node is at head.getNext().
+     * A node from which the last node on list (that is, the unique
+     * node with node.next == null) can be reached in O(1) time.
+     * Invariants:
+     * - the last node is always reachable from tail via succ()
+     * - tail != null
+     * Non-invariants:
+     * - tail.item may or may not be null.
+     * - it is permitted for tail to lag behind head, that is, for tail
+     *   to not be reachable from head!
+     * - tail.next may or may not be self-pointing to tail.
      */
-    private transient volatile Node<E> head = new Node<E>(null, null);
-
-    /** Pointer to last node on list **/
     private transient volatile Node<E> tail = head;
 
 
     /**
-     * Creates a <tt>ConcurrentLinkedQueue</tt> that is initially empty.
+     * Creates a {@code ConcurrentLinkedQueue} that is initially empty.
      */
     public ConcurrentLinkedQueue() {}
 
     /**
-     * Creates a <tt>ConcurrentLinkedQueue</tt>
+     * Creates a {@code ConcurrentLinkedQueue}
      * initially containing the elements of the given collection,
      * added in traversal order of the collection's iterator.
      * @param c the collection of elements to initially contain
@@ -201,7 +259,7 @@
     /**
      * Inserts the specified element at the tail of this queue.
      *
-     * @return <tt>true</tt> (as specified by {@link Collection#add})
+     * @return {@code true} (as specified by {@link Collection#add})
      * @throws NullPointerException if the specified element is null
      */
     public boolean add(E e) {
@@ -209,107 +267,135 @@
     }
 
     /**
+     * We don't bother to update head or tail pointers if fewer than
+     * HOPS links from "true" location.  We assume that volatile
+     * writes are significantly more expensive than volatile reads.
+     */
+    private static final int HOPS = 1;
+
+    /**
+     * Try to CAS head to p. If successful, repoint old head to itself
+     * as sentinel for succ(), below.
+     */
+    final void updateHead(Node<E> h, Node<E> p) {
+        if (h != p && casHead(h, p))
+            h.lazySetNext(h);
+    }
+
+    /**
+     * Returns the successor of p, or the head node if p.next has been
+     * linked to self, which will only be true if traversing with a
+     * stale pointer that is now off the list.
+     */
+    final Node<E> succ(Node<E> p) {
+        Node<E> next = p.getNext();
+        return (p == next) ? head : next;
+    }
+
+    /**
      * Inserts the specified element at the tail of this queue.
      *
-     * @return <tt>true</tt> (as specified by {@link Queue#offer})
+     * @return {@code true} (as specified by {@link Queue#offer})
      * @throws NullPointerException if the specified element is null
      */
     public boolean offer(E e) {
         if (e == null) throw new NullPointerException();
-        Node<E> n = new Node<E>(e, null);
+        Node<E> n = new Node<E>(e);
+        retry:
         for (;;) {
             Node<E> t = tail;
-            Node<E> s = t.getNext();
-            if (t == tail) {
-                if (s == null) {
-                    if (t.casNext(s, n)) {
-                        casTail(t, n);
-                        return true;
-                    }
+            Node<E> p = t;
+            for (int hops = 0; ; hops++) {
+                Node<E> next = succ(p);
+                if (next != null) {
+                    if (hops > HOPS && t != tail)
+                        continue retry;
+                    p = next;
+                } else if (p.casNext(null, n)) {
+                    if (hops >= HOPS)
+                        casTail(t, n);  // Failure is OK.
+                    return true;
                 } else {
-                    casTail(t, s);
+                    p = succ(p);
                 }
             }
         }
     }
 
     public E poll() {
-        for (;;) {
-            Node<E> h = head;
-            Node<E> t = tail;
-            Node<E> first = h.getNext();
-            if (h == head) {
-                if (h == t) {
-                    if (first == null)
-                        return null;
-                    else
-                        casTail(t, first);
-                } else if (casHead(h, first)) {
-                    E item = first.getItem();
-                    if (item != null) {
-                        first.setItem(null);
-                        return item;
-                    }
-                    // else skip over deleted item, continue loop,
+        Node<E> h = head;
+        Node<E> p = h;
+        for (int hops = 0; ; hops++) {
+            E item = p.getItem();
+
+            if (item != null && p.casItem(item, null)) {
+                if (hops >= HOPS) {
+                    Node<E> q = p.getNext();
+                    updateHead(h, (q != null) ? q : p);
                 }
+                return item;
             }
+            Node<E> next = succ(p);
+            if (next == null) {
+                updateHead(h, p);
+                break;
+            }
+            p = next;
         }
+        return null;
     }
 
-    public E peek() { // same as poll except don't remove item
+    public E peek() {
+        Node<E> h = head;
+        Node<E> p = h;
+        E item;
         for (;;) {
-            Node<E> h = head;
-            Node<E> t = tail;
-            Node<E> first = h.getNext();
-            if (h == head) {
-                if (h == t) {
-                    if (first == null)
-                        return null;
-                    else
-                        casTail(t, first);
-                } else {
-                    E item = first.getItem();
-                    if (item != null)
-                        return item;
-                    else // remove deleted node and continue
-                        casHead(h, first);
-                }
+            item = p.getItem();
+            if (item != null)
+                break;
+            Node<E> next = succ(p);
+            if (next == null) {
+                break;
             }
+            p = next;
         }
+        updateHead(h, p);
+        return item;
     }
 
     /**
-     * Returns the first actual (non-header) node on list.  This is yet
-     * another variant of poll/peek; here returning out the first
-     * node, not element (so we cannot collapse with peek() without
-     * introducing race.)
+     * Returns the first live (non-deleted) node on list, or null if none.
+     * This is yet another variant of poll/peek; here returning the
+     * first node, not element.  We could make peek() a wrapper around
+     * first(), but that would cost an extra volatile read of item,
+     * and the need to add a retry loop to deal with the possibility
+     * of losing a race to a concurrent poll().
      */
     Node<E> first() {
+        Node<E> h = head;
+        Node<E> p = h;
+        Node<E> result;
         for (;;) {
-            Node<E> h = head;
-            Node<E> t = tail;
-            Node<E> first = h.getNext();
-            if (h == head) {
-                if (h == t) {
-                    if (first == null)
-                        return null;
-                    else
-                        casTail(t, first);
-                } else {
-                    if (first.getItem() != null)
-                        return first;
-                    else // remove deleted node and continue
-                        casHead(h, first);
-                }
+            E item = p.getItem();
+            if (item != null) {
+                result = p;
+                break;
             }
+            Node<E> next = succ(p);
+            if (next == null) {
+                result = null;
+                break;
+            }
+            p = next;
         }
+        updateHead(h, p);
+        return result;
     }
 
-
     /**
-     * Returns <tt>true</tt> if this queue contains no elements.
+     * Returns {@code true} if this queue contains no elements.
      *
-     * @return <tt>true</tt> if this queue contains no elements
+     * @return {@code true} if this queue contains no elements
      */
     public boolean isEmpty() {
         return first() == null;
@@ -317,8 +403,8 @@
 
     /**
      * Returns the number of elements in this queue.  If this queue
-     * contains more than <tt>Integer.MAX_VALUE</tt> elements, returns
-     * <tt>Integer.MAX_VALUE</tt>.
+     * contains more than {@code Integer.MAX_VALUE} elements, returns
+     * {@code Integer.MAX_VALUE}.
      *
      * <p>Beware that, unlike in most collections, this method is
      * <em>NOT</em> a constant-time operation. Because of the
@@ -329,7 +415,7 @@
      */
     public int size() {
         int count = 0;
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             if (p.getItem() != null) {
                 // Collections.size() spec says to max out
                 if (++count == Integer.MAX_VALUE)
@@ -340,16 +426,16 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this queue contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this queue contains
-     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this queue contains the specified element.
+     * More formally, returns {@code true} if and only if this queue contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this queue
-     * @return <tt>true</tt> if this queue contains the specified element
+     * @return {@code true} if this queue contains the specified element
      */
     public boolean contains(Object o) {
         if (o == null) return false;
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.getItem();
             if (item != null &&
                 o.equals(item))
@@ -360,23 +446,29 @@
 
     /**
      * Removes a single instance of the specified element from this queue,
-     * if it is present.  More formally, removes an element <tt>e</tt> such
-     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
      * elements.
-     * Returns <tt>true</tt> if this queue contained the specified element
+     * Returns {@code true} if this queue contained the specified element
      * (or equivalently, if this queue changed as a result of the call).
      *
      * @param o element to be removed from this queue, if present
-     * @return <tt>true</tt> if this queue changed as a result of the call
+     * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
         if (o == null) return false;
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        Node<E> pred = null;
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.getItem();
             if (item != null &&
                 o.equals(item) &&
-                p.casItem(item, null))
+                p.casItem(item, null)) {
+                Node<E> next = succ(p);
+                if (pred != null && next != null)
+                    pred.casNext(p, next);
                 return true;
+            }
+            pred = p;
         }
         return false;
     }
@@ -397,7 +489,7 @@
     public Object[] toArray() {
         // Use ArrayList to deal with resizing.
         ArrayList<E> al = new ArrayList<E>();
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.getItem();
             if (item != null)
                 al.add(item);
@@ -415,22 +507,22 @@
      * <p>If this queue fits in the specified array with room to spare
      * (i.e., the array has more elements than this queue), the element in
      * the array immediately following the end of the queue is set to
-     * <tt>null</tt>.
+     * {@code null}.
      *
      * <p>Like the {@link #toArray()} method, this method acts as bridge between
      * array-based and collection-based APIs.  Further, this method allows
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+     * <p>Suppose {@code x} is a queue known to contain only strings.
      * The following code can be used to dump the queue into a newly
-     * allocated array of <tt>String</tt>:
+     * allocated array of {@code String}:
      *
      * <pre>
      *     String[] y = x.toArray(new String[0]);</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the queue are to
      *          be stored, if it is big enough; otherwise, a new array of the
@@ -441,11 +533,12 @@
      *         this queue
      * @throws NullPointerException if the specified array is null
      */
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
         // try to use sent-in array
         int k = 0;
         Node<E> p;
-        for (p = first(); p != null && k < a.length; p = p.getNext()) {
+        for (p = first(); p != null && k < a.length; p = succ(p)) {
             E item = p.getItem();
             if (item != null)
                 a[k++] = (T)item;
@@ -458,7 +551,7 @@
 
         // If won't fit, use ArrayList version
         ArrayList<E> al = new ArrayList<E>();
-        for (Node<E> q = first(); q != null; q = q.getNext()) {
+        for (Node<E> q = first(); q != null; q = succ(q)) {
             E item = q.getItem();
             if (item != null)
                 al.add(item);
@@ -469,7 +562,8 @@
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
      * The returned iterator is a "weakly consistent" iterator that
-     * will never throw {@link ConcurrentModificationException},
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
@@ -511,7 +605,15 @@
             lastRet = nextNode;
             E x = nextItem;
 
-            Node<E> p = (nextNode == null)? first() : nextNode.getNext();
+            Node<E> pred, p;
+            if (nextNode == null) {
+                p = first();
+                pred = null;
+            } else {
+                pred = nextNode;
+                p = succ(nextNode);
+            }
+
             for (;;) {
                 if (p == null) {
                     nextNode = null;
@@ -523,8 +625,13 @@
                     nextNode = p;
                     nextItem = item;
                     return x;
-                } else // skip over nulls
-                    p = p.getNext();
+                } else {
+                    // skip over nulls
+                    Node<E> next = succ(p);
+                    if (pred != null && next != null)
+                        pred.casNext(p, next);
+                    p = next;
+                }
             }
         }
 
@@ -549,7 +656,7 @@
     /**
      * Save the state to a stream (that is, serialize it).
      *
-     * @serialData All of the elements (each an <tt>E</tt>) in
+     * @serialData All of the elements (each an {@code E}) in
      * the proper order, followed by a null
      * @param s the stream
      */
@@ -560,7 +667,7 @@
         s.defaultWriteObject();
 
         // Write out all elements in the proper order.
-        for (Node<E> p = first(); p != null; p = p.getNext()) {
+        for (Node<E> p = first(); p != null; p = succ(p)) {
             Object item = p.getItem();
             if (item != null)
                 s.writeObject(item);
@@ -579,10 +686,11 @@
         throws java.io.IOException, ClassNotFoundException {
         // Read in capacity, and any hidden stuff
         s.defaultReadObject();
-        head = new Node<E>(null, null);
+        head = new Node<E>(null);
         tail = head;
         // Read in all elements and place in queue
         for (;;) {
+            @SuppressWarnings("unchecked")
             E item = (E)s.readObject();
             if (item == null)
                 break;
@@ -591,4 +699,35 @@
         }
     }
 
+    // Unsafe mechanics
+
+    private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
+    private static final long headOffset =
+        objectFieldOffset(UNSAFE, "head", ConcurrentLinkedQueue.class);
+    private static final long tailOffset =
+        objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedQueue.class);
+
+    private boolean casTail(Node<E> cmp, Node<E> val) {
+        return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
+    }
+
+    private boolean casHead(Node<E> cmp, Node<E> val) {
+        return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
+    }
+
+    private void lazySetHead(Node<E> val) {
+        UNSAFE.putOrderedObject(this, headOffset, val);
+    }
+
+    static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
+                                  String field, Class<?> klazz) {
+        try {
+            return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
+        } catch (NoSuchFieldException e) {
+            // Convert Exception to corresponding Error
+            NoSuchFieldError error = new NoSuchFieldError(field);
+            error.initCause(e);
+            throw error;
+        }
+    }
 }
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java	Tue Aug 18 19:53:43 2009 -0700
@@ -34,8 +34,13 @@
  */
 
 package java.util.concurrent;
-import java.util.*;
-import java.util.concurrent.locks.*;
+
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
 
 /**
  * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on
@@ -73,6 +78,20 @@
     /*
      * Implemented as a simple doubly-linked list protected by a
      * single lock and using conditions to manage blocking.
+     *
+     * To implement weakly consistent iterators, it appears we need to
+     * keep all Nodes GC-reachable from a predecessor dequeued Node.
+     * That would cause two problems:
+     * - allow a rogue Iterator to cause unbounded memory retention
+     * - cause cross-generational linking of old Nodes to new Nodes if
+     *   a Node was tenured while live, which generational GCs have a
+     *   hard time dealing with, causing repeated major collections.
+     * However, only non-deleted Nodes need to be reachable from
+     * dequeued Nodes, and reachability does not necessarily have to
+     * be of the kind understood by the GC.  We use the trick of
+     * linking a Node that has just been dequeued to itself.  Such a
+     * self-link implicitly means to jump to "first" (for next links)
+     * or "last" (for prev links).
      */
 
     /*
@@ -86,9 +105,27 @@
 
     /** Doubly-linked list node class */
     static final class Node<E> {
+        /**
+         * The item, or null if this node has been removed.
+         */
         E item;
+
+        /**
+         * One of:
+         * - the real predecessor Node
+         * - this Node, meaning the predecessor is tail
+         * - null, meaning there is no predecessor
+         */
         Node<E> prev;
+
+        /**
+         * One of:
+         * - the real successor Node
+         * - this Node, meaning the successor is head
+         * - null, meaning there is no successor
+         */
         Node<E> next;
+
         Node(E x, Node<E> p, Node<E> n) {
             item = x;
             prev = p;
@@ -96,23 +133,37 @@
         }
     }
 
-    /** Pointer to first node */
-    private transient Node<E> first;
-    /** Pointer to last node */
-    private transient Node<E> last;
+    /**
+     * Pointer to first node.
+     * Invariant: (first == null && last == null) ||
+     *            (first.prev == null && first.item != null)
+     */
+    transient Node<E> first;
+
+    /**
+     * Pointer to last node.
+     * Invariant: (first == null && last == null) ||
+     *            (last.next == null && last.item != null)
+     */
+    transient Node<E> last;
+
     /** Number of items in the deque */
     private transient int count;
+
     /** Maximum number of items in the deque */
     private final int capacity;
+
     /** Main lock guarding all access */
-    private final ReentrantLock lock = new ReentrantLock();
+    final ReentrantLock lock = new ReentrantLock();
+
     /** Condition for waiting takes */
     private final Condition notEmpty = lock.newCondition();
+
     /** Condition for waiting puts */
     private final Condition notFull = lock.newCondition();
 
     /**
-     * Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
+     * Creates a {@code LinkedBlockingDeque} with a capacity of
      * {@link Integer#MAX_VALUE}.
      */
     public LinkedBlockingDeque() {
@@ -120,10 +171,10 @@
     }
 
     /**
-     * Creates a <tt>LinkedBlockingDeque</tt> with the given (fixed) capacity.
+     * Creates a {@code LinkedBlockingDeque} with the given (fixed) capacity.
      *
      * @param capacity the capacity of this deque
-     * @throws IllegalArgumentException if <tt>capacity</tt> is less than 1
+     * @throws IllegalArgumentException if {@code capacity} is less than 1
      */
     public LinkedBlockingDeque(int capacity) {
         if (capacity <= 0) throw new IllegalArgumentException();
@@ -131,7 +182,7 @@
     }
 
     /**
-     * Creates a <tt>LinkedBlockingDeque</tt> with a capacity of
+     * Creates a {@code LinkedBlockingDeque} with a capacity of
      * {@link Integer#MAX_VALUE}, initially containing the elements of
      * the given collection, added in traversal order of the
      * collection's iterator.
@@ -142,8 +193,18 @@
      */
     public LinkedBlockingDeque(Collection<? extends E> c) {
         this(Integer.MAX_VALUE);
-        for (E e : c)
-            add(e);
+        final ReentrantLock lock = this.lock;
+        lock.lock(); // Never contended, but necessary for visibility
+        try {
+            for (E e : c) {
+                if (e == null)
+                    throw new NullPointerException();
+                if (!linkLast(e))
+                    throw new IllegalStateException("Deque full");
+            }
+        } finally {
+            lock.unlock();
+        }
     }
 
 
@@ -153,9 +214,9 @@
      * Links e as first element, or returns false if full.
      */
     private boolean linkFirst(E e) {
+        // assert lock.isHeldByCurrentThread();
         if (count >= capacity)
             return false;
-        ++count;
         Node<E> f = first;
         Node<E> x = new Node<E>(e, null, f);
         first = x;
@@ -163,6 +224,7 @@
             last = x;
         else
             f.prev = x;
+        ++count;
         notEmpty.signal();
         return true;
     }
@@ -171,9 +233,9 @@
      * Links e as last element, or returns false if full.
      */
     private boolean linkLast(E e) {
+        // assert lock.isHeldByCurrentThread();
         if (count >= capacity)
             return false;
-        ++count;
         Node<E> l = last;
         Node<E> x = new Node<E>(e, l, null);
         last = x;
@@ -181,6 +243,7 @@
             first = x;
         else
             l.next = x;
+        ++count;
         notEmpty.signal();
         return true;
     }
@@ -189,10 +252,14 @@
      * Removes and returns first element, or null if empty.
      */
     private E unlinkFirst() {
+        // assert lock.isHeldByCurrentThread();
         Node<E> f = first;
         if (f == null)
             return null;
         Node<E> n = f.next;
+        E item = f.item;
+        f.item = null;
+        f.next = f; // help GC
         first = n;
         if (n == null)
             last = null;
@@ -200,17 +267,21 @@
             n.prev = null;
         --count;
         notFull.signal();
-        return f.item;
+        return item;
     }
 
     /**
      * Removes and returns last element, or null if empty.
      */
     private E unlinkLast() {
+        // assert lock.isHeldByCurrentThread();
         Node<E> l = last;
         if (l == null)
             return null;
         Node<E> p = l.prev;
+        E item = l.item;
+        l.item = null;
+        l.prev = l; // help GC
         last = p;
         if (p == null)
             first = null;
@@ -218,31 +289,29 @@
             p.next = null;
         --count;
         notFull.signal();
-        return l.item;
+        return item;
     }
 
     /**
-     * Unlink e
+     * Unlinks x.
      */
-    private void unlink(Node<E> x) {
+    void unlink(Node<E> x) {
+        // assert lock.isHeldByCurrentThread();
         Node<E> p = x.prev;
         Node<E> n = x.next;
         if (p == null) {
-            if (n == null)
-                first = last = null;
-            else {
-                n.prev = null;
-                first = n;
-            }
+            unlinkFirst();
         } else if (n == null) {
-            p.next = null;
-            last = p;
+            unlinkLast();
         } else {
             p.next = n;
             n.prev = p;
+            x.item = null;
+            // Don't mess with x's links.  They may still be in use by
+            // an iterator.
+            --count;
+            notFull.signal();
         }
-        --count;
-        notFull.signalAll();
     }
 
     // BlockingDeque methods
@@ -270,6 +339,7 @@
      */
     public boolean offerFirst(E e) {
         if (e == null) throw new NullPointerException();
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return linkFirst(e);
@@ -283,6 +353,7 @@
      */
     public boolean offerLast(E e) {
         if (e == null) throw new NullPointerException();
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return linkLast(e);
@@ -297,6 +368,7 @@
      */
     public void putFirst(E e) throws InterruptedException {
         if (e == null) throw new NullPointerException();
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             while (!linkFirst(e))
@@ -312,6 +384,7 @@
      */
     public void putLast(E e) throws InterruptedException {
         if (e == null) throw new NullPointerException();
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             while (!linkLast(e))
@@ -329,15 +402,15 @@
         throws InterruptedException {
         if (e == null) throw new NullPointerException();
         long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
-            for (;;) {
-                if (linkFirst(e))
-                    return true;
+            while (!linkFirst(e)) {
                 if (nanos <= 0)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
+            return true;
         } finally {
             lock.unlock();
         }
@@ -351,15 +424,15 @@
         throws InterruptedException {
         if (e == null) throw new NullPointerException();
         long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
-            for (;;) {
-                if (linkLast(e))
-                    return true;
+            while (!linkLast(e)) {
                 if (nanos <= 0)
                     return false;
                 nanos = notFull.awaitNanos(nanos);
             }
+            return true;
         } finally {
             lock.unlock();
         }
@@ -384,6 +457,7 @@
     }
 
     public E pollFirst() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return unlinkFirst();
@@ -393,6 +467,7 @@
     }
 
     public E pollLast() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return unlinkLast();
@@ -402,6 +477,7 @@
     }
 
     public E takeFirst() throws InterruptedException {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             E x;
@@ -414,6 +490,7 @@
     }
 
     public E takeLast() throws InterruptedException {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             E x;
@@ -428,16 +505,16 @@
     public E pollFirst(long timeout, TimeUnit unit)
         throws InterruptedException {
         long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
-            for (;;) {
-                E x = unlinkFirst();
-                if (x != null)
-                    return x;
+            E x;
+            while ( (x = unlinkFirst()) == null) {
                 if (nanos <= 0)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
+            return x;
         } finally {
             lock.unlock();
         }
@@ -446,16 +523,16 @@
     public E pollLast(long timeout, TimeUnit unit)
         throws InterruptedException {
         long nanos = unit.toNanos(timeout);
+        final ReentrantLock lock = this.lock;
         lock.lockInterruptibly();
         try {
-            for (;;) {
-                E x = unlinkLast();
-                if (x != null)
-                    return x;
+            E x;
+            while ( (x = unlinkLast()) == null) {
                 if (nanos <= 0)
                     return null;
                 nanos = notEmpty.awaitNanos(nanos);
             }
+            return x;
         } finally {
             lock.unlock();
         }
@@ -480,6 +557,7 @@
     }
 
     public E peekFirst() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return (first == null) ? null : first.item;
@@ -489,6 +567,7 @@
     }
 
     public E peekLast() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return (last == null) ? null : last.item;
@@ -499,6 +578,7 @@
 
     public boolean removeFirstOccurrence(Object o) {
         if (o == null) return false;
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             for (Node<E> p = first; p != null; p = p.next) {
@@ -515,6 +595,7 @@
 
     public boolean removeLastOccurrence(Object o) {
         if (o == null) return false;
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             for (Node<E> p = last; p != null; p = p.prev) {
@@ -619,14 +700,15 @@
      * Returns the number of additional elements that this deque can ideally
      * (in the absence of memory or resource constraints) accept without
      * blocking. This is always equal to the initial capacity of this deque
-     * less the current <tt>size</tt> of this deque.
+     * less the current {@code size} of this deque.
      *
      * <p>Note that you <em>cannot</em> always tell if an attempt to insert
-     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * an element will succeed by inspecting {@code remainingCapacity}
      * because it may be the case that another thread is about to
      * insert or remove an element.
      */
     public int remainingCapacity() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return capacity - count;
@@ -642,22 +724,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        if (c == null)
-            throw new NullPointerException();
-        if (c == this)
-            throw new IllegalArgumentException();
-        lock.lock();
-        try {
-            for (Node<E> p = first; p != null; p = p.next)
-                c.add(p.item);
-            int n = count;
-            count = 0;
-            first = last = null;
-            notFull.signalAll();
-            return n;
-        } finally {
-            lock.unlock();
-        }
+        return drainTo(c, Integer.MAX_VALUE);
     }
 
     /**
@@ -671,19 +738,14 @@
             throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
-            int n = 0;
-            while (n < maxElements && first != null) {
-                c.add(first.item);
-                first.prev = null;
-                first = first.next;
-                --count;
-                ++n;
+            int n = Math.min(maxElements, count);
+            for (int i = 0; i < n; i++) {
+                c.add(first.item);   // In this order, in case add() throws.
+                unlinkFirst();
             }
-            if (first == null)
-                last = null;
-            notFull.signalAll();
             return n;
         } finally {
             lock.unlock();
@@ -712,16 +774,16 @@
     /**
      * Removes the first occurrence of the specified element from this deque.
      * If the deque does not contain the element, it is unchanged.
-     * More formally, removes the first element <tt>e</tt> such that
-     * <tt>o.equals(e)</tt> (if such an element exists).
-     * Returns <tt>true</tt> if this deque contained the specified element
+     * More formally, removes the first element {@code e} such that
+     * {@code o.equals(e)} (if such an element exists).
+     * Returns {@code true} if this deque contained the specified element
      * (or equivalently, if this deque changed as a result of the call).
      *
      * <p>This method is equivalent to
      * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}.
      *
      * @param o element to be removed from this deque, if present
-     * @return <tt>true</tt> if this deque changed as a result of the call
+     * @return {@code true} if this deque changed as a result of the call
      */
     public boolean remove(Object o) {
         return removeFirstOccurrence(o);
@@ -733,6 +795,7 @@
      * @return the number of elements in this deque
      */
     public int size() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return count;
@@ -742,15 +805,16 @@
     }
 
     /**
-     * Returns <tt>true</tt> if this deque contains the specified element.
-     * More formally, returns <tt>true</tt> if and only if this deque contains
-     * at least one element <tt>e</tt> such that <tt>o.equals(e)</tt>.
+     * Returns {@code true} if this deque contains the specified element.
+     * More formally, returns {@code true} if and only if this deque contains
+     * at least one element {@code e} such that {@code o.equals(e)}.
      *
      * @param o object to be checked for containment in this deque
-     * @return <tt>true</tt> if this deque contains the specified element
+     * @return {@code true} if this deque contains the specified element
      */
     public boolean contains(Object o) {
         if (o == null) return false;
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             for (Node<E> p = first; p != null; p = p.next)
@@ -762,24 +826,46 @@
         }
     }
 
-    /**
-     * Variant of removeFirstOccurrence needed by iterator.remove.
-     * Searches for the node, not its contents.
+    /*
+     * TODO: Add support for more efficient bulk operations.
+     *
+     * We don't want to acquire the lock for every iteration, but we
+     * also want other threads a chance to interact with the
+     * collection, especially when count is close to capacity.
      */
-    boolean removeNode(Node<E> e) {
-        lock.lock();
-        try {
-            for (Node<E> p = first; p != null; p = p.next) {
-                if (p == e) {
-                    unlink(p);
-                    return true;
-                }
-            }
-            return false;
-        } finally {
-            lock.unlock();
-        }
-    }
+
+//     /**
+//      * Adds all of the elements in the specified collection to this
+//      * queue.  Attempts to addAll of a queue to itself result in
+//      * {@code IllegalArgumentException}. Further, the behavior of
+//      * this operation is undefined if the specified collection is
+//      * modified while the operation is in progress.
+//      *
+//      * @param c collection containing elements to be added to this queue
+//      * @return {@code true} if this queue changed as a result of the call
+//      * @throws ClassCastException            {@inheritDoc}
+//      * @throws NullPointerException          {@inheritDoc}
+//      * @throws IllegalArgumentException      {@inheritDoc}
+//      * @throws IllegalStateException         {@inheritDoc}
+//      * @see #add(Object)
+//      */
+//     public boolean addAll(Collection<? extends E> c) {
+//         if (c == null)
+//             throw new NullPointerException();
+//         if (c == this)
+//             throw new IllegalArgumentException();
+//         final ReentrantLock lock = this.lock;
+//         lock.lock();
+//         try {
+//             boolean modified = false;
+//             for (E e : c)
+//                 if (linkLast(e))
+//                     modified = true;
+//             return modified;
+//         } finally {
+//             lock.unlock();
+//         }
+//     }
 
     /**
      * Returns an array containing all of the elements in this deque, in
@@ -794,7 +880,9 @@
      *
      * @return an array containing all of the elements in this deque
      */
+    @SuppressWarnings("unchecked")
     public Object[] toArray() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             Object[] a = new Object[count];
@@ -817,22 +905,22 @@
      * <p>If this deque fits in the specified array with room to spare
      * (i.e., the array has more elements than this deque), the element in
      * the array immediately following the end of the deque is set to
-     * <tt>null</tt>.
+     * {@code null}.
      *
      * <p>Like the {@link #toArray()} method, this method acts as bridge between
      * array-based and collection-based APIs.  Further, this method allows
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a deque known to contain only strings.
+     * <p>Suppose {@code x} is a deque known to contain only strings.
      * The following code can be used to dump the deque into a newly
-     * allocated array of <tt>String</tt>:
+     * allocated array of {@code String}:
      *
      * <pre>
      *     String[] y = x.toArray(new String[0]);</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the deque are to
      *          be stored, if it is big enough; otherwise, a new array of the
@@ -843,14 +931,14 @@
      *         this deque
      * @throws NullPointerException if the specified array is null
      */
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             if (a.length < count)
-                a = (T[])java.lang.reflect.Array.newInstance(
-                    a.getClass().getComponentType(),
-                    count
-                    );
+                a = (T[])java.lang.reflect.Array.newInstance
+                    (a.getClass().getComponentType(), count);
 
             int k = 0;
             for (Node<E> p = first; p != null; p = p.next)
@@ -864,6 +952,7 @@
     }
 
     public String toString() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             return super.toString();
@@ -877,8 +966,16 @@
      * The deque will be empty after this call returns.
      */
     public void clear() {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
+            for (Node<E> f = first; f != null; ) {
+                f.item = null;
+                Node<E> n = f.next;
+                f.prev = null;
+                f.next = null;
+                f = n;
+            }
             first = last = null;
             count = 0;
             notFull.signalAll();
@@ -890,8 +987,9 @@
     /**
      * Returns an iterator over the elements in this deque in proper sequence.
      * The elements will be returned in order from first (head) to last (tail).
-     * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link ConcurrentModificationException},
+     * The returned {@code Iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
@@ -906,8 +1004,9 @@
      * Returns an iterator over the elements in this deque in reverse
      * sequential order.  The elements will be returned in order from
      * last (tail) to first (head).
-     * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link ConcurrentModificationException},
+     * The returned {@code Iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
@@ -921,7 +1020,7 @@
      */
     private abstract class AbstractItr implements Iterator<E> {
         /**
-         * The next node to return in next
+         * The next node to return in next()
          */
          Node<E> next;
 
@@ -939,15 +1038,44 @@
          */
         private Node<E> lastRet;
 
+        abstract Node<E> firstNode();
+        abstract Node<E> nextNode(Node<E> n);
+
         AbstractItr() {
-            advance(); // set to initial position
+            // set to initial position
+            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+            lock.lock();
+            try {
+                next = firstNode();
+                nextItem = (next == null) ? null : next.item;
+            } finally {
+                lock.unlock();
+            }
         }
 
         /**
-         * Advances next, or if not yet initialized, sets to first node.
-         * Implemented to move forward vs backward in the two subclasses.
+         * Advances next.
          */
-        abstract void advance();
+        void advance() {
+            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
+            lock.lock();
+            try {
+                // assert next != null;
+                Node<E> s = nextNode(next);
+                if (s == next) {
+                    next = firstNode();
+                } else {
+                    // Skip over removed nodes.
+                    // May be necessary if multiple interior Nodes are removed.
+                    while (s != null && s.item == null)
+                        s = nextNode(s);
+                    next = s;
+                }
+                nextItem = (next == null) ? null : next.item;
+            } finally {
+                lock.unlock();
+            }
+        }
 
         public boolean hasNext() {
             return next != null;
@@ -967,52 +1095,39 @@
             if (n == null)
                 throw new IllegalStateException();
             lastRet = null;
-            // Note: removeNode rescans looking for this node to make
-            // sure it was not already removed. Otherwise, trying to
-            // re-remove could corrupt list.
-            removeNode(n);
-        }
-    }
-
-    /** Forward iterator */
-    private class Itr extends AbstractItr {
-        void advance() {
             final ReentrantLock lock = LinkedBlockingDeque.this.lock;
             lock.lock();
             try {
-                next = (next == null)? first : next.next;
-                nextItem = (next == null)? null : next.item;
+                if (n.item != null)
+                    unlink(n);
             } finally {
                 lock.unlock();
             }
         }
     }
 
-    /**
-     * Descending iterator for LinkedBlockingDeque
-     */
+    /** Forward iterator */
+    private class Itr extends AbstractItr {
+        Node<E> firstNode() { return first; }
+        Node<E> nextNode(Node<E> n) { return n.next; }
+    }
+
+    /** Descending iterator */
     private class DescendingItr extends AbstractItr {
-        void advance() {
-            final ReentrantLock lock = LinkedBlockingDeque.this.lock;
-            lock.lock();
-            try {
-                next = (next == null)? last : next.prev;
-                nextItem = (next == null)? null : next.item;
-            } finally {
-                lock.unlock();
-            }
-        }
+        Node<E> firstNode() { return last; }
+        Node<E> nextNode(Node<E> n) { return n.prev; }
     }
 
     /**
      * Save the state of this deque to a stream (that is, serialize it).
      *
      * @serialData The capacity (int), followed by elements (each an
-     * <tt>Object</tt>) in the proper order, followed by a null
+     * {@code Object}) in the proper order, followed by a null
      * @param s the stream
      */
     private void writeObject(java.io.ObjectOutputStream s)
         throws java.io.IOException {
+        final ReentrantLock lock = this.lock;
         lock.lock();
         try {
             // Write out capacity and any hidden stuff
@@ -1040,6 +1155,7 @@
         last = null;
         // Read in all elements and place in queue
         for (;;) {
+            @SuppressWarnings("unchecked")
             E item = (E)s.readObject();
             if (item == null)
                 break;
--- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java	Tue Aug 18 19:53:43 2009 -0700
@@ -34,9 +34,14 @@
  */
 
 package java.util.concurrent;
-import java.util.concurrent.atomic.*;
-import java.util.concurrent.locks.*;
-import java.util.*;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.AbstractQueue;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
 
 /**
  * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on
@@ -86,15 +91,43 @@
      * items have been entered since the signal. And symmetrically for
      * takes signalling puts. Operations such as remove(Object) and
      * iterators acquire both locks.
+     *
+     * Visibility between writers and readers is provided as follows:
+     *
+     * Whenever an element is enqueued, the putLock is acquired and
+     * count updated.  A subsequent reader guarantees visibility to the
+     * enqueued Node by either acquiring the putLock (via fullyLock)
+     * or by acquiring the takeLock, and then reading n = count.get();
+     * this gives visibility to the first n items.
+     *
+     * To implement weakly consistent iterators, it appears we need to
+     * keep all Nodes GC-reachable from a predecessor dequeued Node.
+     * That would cause two problems:
+     * - allow a rogue Iterator to cause unbounded memory retention
+     * - cause cross-generational linking of old Nodes to new Nodes if
+     *   a Node was tenured while live, which generational GCs have a
+     *   hard time dealing with, causing repeated major collections.
+     * However, only non-deleted Nodes need to be reachable from
+     * dequeued Nodes, and reachability does not necessarily have to
+     * be of the kind understood by the GC.  We use the trick of
+     * linking a Node that has just been dequeued to itself.  Such a
+     * self-link implicitly means to advance to head.next.
      */
 
     /**
      * Linked list node class
      */
     static class Node<E> {
-        /** The item, volatile to ensure barrier separating write and read */
-        volatile E item;
+        E item;
+
+        /**
+         * One of:
+         * - the real successor Node
+         * - this Node, meaning the successor is head.next
+         * - null, meaning there is no successor (this is the last node)
+         */
         Node<E> next;
+
         Node(E x) { item = x; }
     }
 
@@ -104,10 +137,16 @@
     /** Current number of elements */
     private final AtomicInteger count = new AtomicInteger(0);
 
-    /** Head of linked list */
+    /**
+     * Head of linked list.
+     * Invariant: head.item == null
+     */
     private transient Node<E> head;
 
-    /** Tail of linked list */
+    /**
+     * Tail of linked list.
+     * Invariant: last.next == null
+     */
     private transient Node<E> last;
 
     /** Lock held by take, poll, etc */
@@ -151,18 +190,26 @@
 
     /**
      * Creates a node and links it at end of queue.
+     *
      * @param x the item
      */
-    private void insert(E x) {
+    private void enqueue(E x) {
+        // assert putLock.isHeldByCurrentThread();
+        // assert last.next == null;
         last = last.next = new Node<E>(x);
     }
 
     /**
-     * Removes a node from head of queue,
+     * Removes a node from head of queue.
+     *
      * @return the node
      */
-    private E extract() {
-        Node<E> first = head.next;
+    private E dequeue() {
+        // assert takeLock.isHeldByCurrentThread();
+        // assert head.item == null;
+        Node<E> h = head;
+        Node<E> first = h.next;
+        h.next = h; // help GC
         head = first;
         E x = first.item;
         first.item = null;
@@ -172,7 +219,7 @@
     /**
      * Lock to prevent both puts and takes.
      */
-    private void fullyLock() {
+    void fullyLock() {
         putLock.lock();
         takeLock.lock();
     }
@@ -180,14 +227,21 @@
     /**
      * Unlock to allow both puts and takes.
      */
-    private void fullyUnlock() {
+    void fullyUnlock() {
         takeLock.unlock();
         putLock.unlock();
     }
 
+//     /**
+//      * Tells whether both locks are held by current thread.
+//      */
+//     boolean isFullyLocked() {
+//         return (putLock.isHeldByCurrentThread() &&
+//                 takeLock.isHeldByCurrentThread());
+//     }
 
     /**
-     * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+     * Creates a {@code LinkedBlockingQueue} with a capacity of
      * {@link Integer#MAX_VALUE}.
      */
     public LinkedBlockingQueue() {
@@ -195,10 +249,10 @@
     }
 
     /**
-     * Creates a <tt>LinkedBlockingQueue</tt> with the given (fixed) capacity.
+     * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity.
      *
      * @param capacity the capacity of this queue
-     * @throws IllegalArgumentException if <tt>capacity</tt> is not greater
+     * @throws IllegalArgumentException if {@code capacity} is not greater
      *         than zero
      */
     public LinkedBlockingQueue(int capacity) {
@@ -208,7 +262,7 @@
     }
 
     /**
-     * Creates a <tt>LinkedBlockingQueue</tt> with a capacity of
+     * Creates a {@code LinkedBlockingQueue} with a capacity of
      * {@link Integer#MAX_VALUE}, initially containing the elements of the
      * given collection,
      * added in traversal order of the collection's iterator.
@@ -219,8 +273,22 @@
      */
     public LinkedBlockingQueue(Collection<? extends E> c) {
         this(Integer.MAX_VALUE);
-        for (E e : c)
-            add(e);
+        final ReentrantLock putLock = this.putLock;
+        putLock.lock(); // Never contended, but necessary for visibility
+        try {
+            int n = 0;
+            for (E e : c) {
+                if (e == null)
+                    throw new NullPointerException();
+                if (n == capacity)
+                    throw new IllegalStateException("Queue full");
+                enqueue(e);
+                ++n;
+            }
+            count.set(n);
+        } finally {
+            putLock.unlock();
+        }
     }
 
 
@@ -241,10 +309,10 @@
      * Returns the number of additional elements that this queue can ideally
      * (in the absence of memory or resource constraints) accept without
      * blocking. This is always equal to the initial capacity of this queue
-     * less the current <tt>size</tt> of this queue.
+     * less the current {@code size} of this queue.
      *
      * <p>Note that you <em>cannot</em> always tell if an attempt to insert
-     * an element will succeed by inspecting <tt>remainingCapacity</tt>
+     * an element will succeed by inspecting {@code remainingCapacity}
      * because it may be the case that another thread is about to
      * insert or remove an element.
      */
@@ -261,8 +329,8 @@
      */
     public void put(E e) throws InterruptedException {
         if (e == null) throw new NullPointerException();
-        // Note: convention in all put/take/etc is to preset
-        // local var holding count  negative to indicate failure unless set.
+        // Note: convention in all put/take/etc is to preset local var
+        // holding count negative to indicate failure unless set.
         int c = -1;
         final ReentrantLock putLock = this.putLock;
         final AtomicInteger count = this.count;
@@ -273,18 +341,13 @@
              * not protected by lock. This works because count can
              * only decrease at this point (all other puts are shut
              * out by lock), and we (or some other waiting put) are
-             * signalled if it ever changes from
-             * capacity. Similarly for all other uses of count in
-             * other wait guards.
+             * signalled if it ever changes from capacity. Similarly
+             * for all other uses of count in other wait guards.
              */
-            try {
-                while (count.get() == capacity)
-                    notFull.await();
-            } catch (InterruptedException ie) {
-                notFull.signal(); // propagate to a non-interrupted thread
-                throw ie;
+            while (count.get() == capacity) {
+                notFull.await();
             }
-            insert(e);
+            enqueue(e);
             c = count.getAndIncrement();
             if (c + 1 < capacity)
                 notFull.signal();
@@ -299,7 +362,7 @@
      * Inserts the specified element at the tail of this queue, waiting if
      * necessary up to the specified wait time for space to become available.
      *
-     * @return <tt>true</tt> if successful, or <tt>false</tt> if
+     * @return {@code true} if successful, or {@code false} if
      *         the specified waiting time elapses before space is available.
      * @throws InterruptedException {@inheritDoc}
      * @throws NullPointerException {@inheritDoc}
@@ -314,23 +377,15 @@
         final AtomicInteger count = this.count;
         putLock.lockInterruptibly();
         try {
-            for (;;) {
-                if (count.get() < capacity) {
-                    insert(e);
-                    c = count.getAndIncrement();
-                    if (c + 1 < capacity)
-                        notFull.signal();
-                    break;
-                }
+            while (count.get() == capacity) {
                 if (nanos <= 0)
                     return false;
-                try {
-                    nanos = notFull.awaitNanos(nanos);
-                } catch (InterruptedException ie) {
-                    notFull.signal(); // propagate to a non-interrupted thread
-                    throw ie;
-                }
+                nanos = notFull.awaitNanos(nanos);
             }
+            enqueue(e);
+            c = count.getAndIncrement();
+            if (c + 1 < capacity)
+                notFull.signal();
         } finally {
             putLock.unlock();
         }
@@ -342,7 +397,7 @@
     /**
      * Inserts the specified element at the tail of this queue if it is
      * possible to do so immediately without exceeding the queue's capacity,
-     * returning <tt>true</tt> upon success and <tt>false</tt> if this queue
+     * returning {@code true} upon success and {@code false} if this queue
      * is full.
      * When using a capacity-restricted queue, this method is generally
      * preferable to method {@link BlockingQueue#add add}, which can fail to
@@ -360,7 +415,7 @@
         putLock.lock();
         try {
             if (count.get() < capacity) {
-                insert(e);
+                enqueue(e);
                 c = count.getAndIncrement();
                 if (c + 1 < capacity)
                     notFull.signal();
@@ -381,15 +436,10 @@
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lockInterruptibly();
         try {
-            try {
-                while (count.get() == 0)
-                    notEmpty.await();
-            } catch (InterruptedException ie) {
-                notEmpty.signal(); // propagate to a non-interrupted thread
-                throw ie;
+            while (count.get() == 0) {
+                notEmpty.await();
             }
-
-            x = extract();
+            x = dequeue();
             c = count.getAndDecrement();
             if (c > 1)
                 notEmpty.signal();
@@ -409,23 +459,15 @@
         final ReentrantLock takeLock = this.takeLock;
         takeLock.lockInterruptibly();
         try {
-            for (;;) {
-                if (count.get() > 0) {
-                    x = extract();
-                    c = count.getAndDecrement();
-                    if (c > 1)
-                        notEmpty.signal();
-                    break;
-                }
+            while (count.get() == 0) {
                 if (nanos <= 0)
                     return null;
-                try {
-                    nanos = notEmpty.awaitNanos(nanos);
-                } catch (InterruptedException ie) {
-                    notEmpty.signal(); // propagate to a non-interrupted thread
-                    throw ie;
-                }
+                nanos = notEmpty.awaitNanos(nanos);
             }
+            x = dequeue();
+            c = count.getAndDecrement();
+            if (c > 1)
+                notEmpty.signal();
         } finally {
             takeLock.unlock();
         }
@@ -444,7 +486,7 @@
         takeLock.lock();
         try {
             if (count.get() > 0) {
-                x = extract();
+                x = dequeue();
                 c = count.getAndDecrement();
                 if (c > 1)
                     notEmpty.signal();
@@ -457,7 +499,6 @@
         return x;
     }
 
-
     public E peek() {
         if (count.get() == 0)
             return null;
@@ -475,43 +516,47 @@
     }
 
     /**
+     * Unlinks interior Node p with predecessor trail.
+     */
+    void unlink(Node<E> p, Node<E> trail) {
+        // assert isFullyLocked();
+        // p.next is not changed, to allow iterators that are
+        // traversing p to maintain their weak-consistency guarantee.
+        p.item = null;
+        trail.next = p.next;
+        if (last == p)
+            last = trail;
+        if (count.getAndDecrement() == capacity)
+            notFull.signal();
+    }
+
+    /**
      * Removes a single instance of the specified element from this queue,
-     * if it is present.  More formally, removes an element <tt>e</tt> such
-     * that <tt>o.equals(e)</tt>, if this queue contains one or more such
+     * if it is present.  More formally, removes an element {@code e} such
+     * that {@code o.equals(e)}, if this queue contains one or more such
      * elements.
-     * Returns <tt>true</tt> if this queue contained the specified element
+     * Returns {@code true} if this queue contained the specified element
      * (or equivalently, if this queue changed as a result of the call).
      *
      * @param o element to be removed from this queue, if present
-     * @return <tt>true</tt> if this queue changed as a result of the call
+     * @return {@code true} if this queue changed as a result of the call
      */
     public boolean remove(Object o) {
         if (o == null) return false;
-        boolean removed = false;
         fullyLock();
         try {
-            Node<E> trail = head;
-            Node<E> p = head.next;
-            while (p != null) {
+            for (Node<E> trail = head, p = trail.next;
+                 p != null;
+                 trail = p, p = p.next) {
                 if (o.equals(p.item)) {
-                    removed = true;
-                    break;
+                    unlink(p, trail);
+                    return true;
                 }
-                trail = p;
-                p = p.next;
             }
-            if (removed) {
-                p.item = null;
-                trail.next = p.next;
-                if (last == p)
-                    last = trail;
-                if (count.getAndDecrement() == capacity)
-                    notFull.signalAll();
-            }
+            return false;
         } finally {
             fullyUnlock();
         }
-        return removed;
     }
 
     /**
@@ -551,22 +596,22 @@
      * <p>If this queue fits in the specified array with room to spare
      * (i.e., the array has more elements than this queue), the element in
      * the array immediately following the end of the queue is set to
-     * <tt>null</tt>.
+     * {@code null}.
      *
      * <p>Like the {@link #toArray()} method, this method acts as bridge between
      * array-based and collection-based APIs.  Further, this method allows
      * precise control over the runtime type of the output array, and may,
      * under certain circumstances, be used to save allocation costs.
      *
-     * <p>Suppose <tt>x</tt> is a queue known to contain only strings.
+     * <p>Suppose {@code x} is a queue known to contain only strings.
      * The following code can be used to dump the queue into a newly
-     * allocated array of <tt>String</tt>:
+     * allocated array of {@code String}:
      *
      * <pre>
      *     String[] y = x.toArray(new String[0]);</pre>
      *
-     * Note that <tt>toArray(new Object[0])</tt> is identical in function to
-     * <tt>toArray()</tt>.
+     * Note that {@code toArray(new Object[0])} is identical in function to
+     * {@code toArray()}.
      *
      * @param a the array into which the elements of the queue are to
      *          be stored, if it is big enough; otherwise, a new array of the
@@ -577,6 +622,7 @@
      *         this queue
      * @throws NullPointerException if the specified array is null
      */
+    @SuppressWarnings("unchecked")
     public <T> T[] toArray(T[] a) {
         fullyLock();
         try {
@@ -586,7 +632,7 @@
                     (a.getClass().getComponentType(), size);
 
             int k = 0;
-            for (Node p = head.next; p != null; p = p.next)
+            for (Node<E> p = head.next; p != null; p = p.next)
                 a[k++] = (T)p.item;
             if (a.length > k)
                 a[k] = null;
@@ -612,11 +658,14 @@
     public void clear() {
         fullyLock();
         try {
-            head.next = null;
-            assert head.item == null;
-            last = head;
+            for (Node<E> p, h = head; (p = h.next) != null; h = p) {
+                h.next = h;
+                p.item = null;
+            }
+            head = last;
+            // assert head.item == null && head.next == null;
             if (count.getAndSet(0) == capacity)
-                notFull.signalAll();
+                notFull.signal();
         } finally {
             fullyUnlock();
         }
@@ -629,30 +678,7 @@
      * @throws IllegalArgumentException      {@inheritDoc}
      */
     public int drainTo(Collection<? super E> c) {
-        if (c == null)
-            throw new NullPointerException();
-        if (c == this)
-            throw new IllegalArgumentException();
-        Node<E> first;
-        fullyLock();
-        try {
-            first = head.next;
-            head.next = null;
-            assert head.item == null;
-            last = head;
-            if (count.getAndSet(0) == capacity)
-                notFull.signalAll();
-        } finally {
-            fullyUnlock();
-        }
-        // Transfer the elements outside of locks
-        int n = 0;
-        for (Node<E> p = first; p != null; p = p.next) {
-            c.add(p.item);
-            p.item = null;
-            ++n;
-        }
-        return n;
+        return drainTo(c, Integer.MAX_VALUE);
     }
 
     /**
@@ -666,34 +692,44 @@
             throw new NullPointerException();
         if (c == this)
             throw new IllegalArgumentException();
-        fullyLock();
+        boolean signalNotFull = false;
+        final ReentrantLock takeLock = this.takeLock;
+        takeLock.lock();
         try {
-            int n = 0;
-            Node<E> p = head.next;
-            while (p != null && n < maxElements) {
-                c.add(p.item);
-                p.item = null;
-                p = p.next;
-                ++n;
+            int n = Math.min(maxElements, count.get());
+            // count.get provides visibility to first n Nodes
+            Node<E> h = head;
+            int i = 0;
+            try {
+                while (i < n) {
+                    Node<E> p = h.next;
+                    c.add(p.item);
+                    p.item = null;
+                    h.next = h;
+                    h = p;
+                    ++i;
+                }
+                return n;
+            } finally {
+                // Restore invariants even if c.add() threw
+                if (i > 0) {
+                    // assert h.item == null;
+                    head = h;
+                    signalNotFull = (count.getAndAdd(-i) == capacity);
+                }
             }
-            if (n != 0) {
-                head.next = p;
-                assert head.item == null;
-                if (p == null)
-                    last = head;
-                if (count.getAndAdd(-n) == capacity)
-                    notFull.signalAll();
-            }
-            return n;
         } finally {
-            fullyUnlock();
+            takeLock.unlock();
+            if (signalNotFull)
+                signalNotFull();
         }
     }
 
     /**
      * Returns an iterator over the elements in this queue in proper sequence.
-     * The returned <tt>Iterator</tt> is a "weakly consistent" iterator that
-     * will never throw {@link ConcurrentModificationException},
+     * The returned {@code Iterator} is a "weakly consistent" iterator that
+     * will never throw {@link java.util.ConcurrentModificationException
+     * ConcurrentModificationException},
      * and guarantees to traverse elements as they existed upon
      * construction of the iterator, and may (but is not guaranteed to)
      * reflect any modifications subsequent to construction.
@@ -706,7 +742,7 @@
 
     private class Itr implements Iterator<E> {
         /*
-         * Basic weak-consistent iterator.  At all times hold the next
+         * Basic weakly-consistent iterator.  At all times hold the next
          * item to hand out so that if hasNext() reports true, we will
          * still have it to return even if lost race with a take etc.
          */
@@ -715,17 +751,13 @@
         private E currentElement;
 
         Itr() {
-            final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
-            final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
-            putLock.lock();
-            takeLock.lock();
+            fullyLock();
             try {
                 current = head.next;
                 if (current != null)
                     currentElement = current.item;
             } finally {
-                takeLock.unlock();
-                putLock.unlock();
+                fullyUnlock();
             }
         }
 
@@ -733,54 +765,54 @@
             return current != null;
         }
 
+        /**
+         * Unlike other traversal methods, iterators need to handle:
+         * - dequeued nodes (p.next == p)
+         * - interior removed nodes (p.item == null)
+         */
+        private Node<E> nextNode(Node<E> p) {
+            Node<E> s = p.next;
+            if (p == s)
+                return head.next;
+            // Skip over removed nodes.
+            // May be necessary if multiple interior Nodes are removed.
+            while (s != null && s.item == null)
+                s = s.next;
+            return s;
+        }
+
         public E next() {
-            final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
-            final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
-            putLock.lock();
-            takeLock.lock();
+            fullyLock();
             try {
                 if (current == null)
                     throw new NoSuchElementException();
                 E x = currentElement;
                 lastRet = current;
-                current = current.next;
-                if (current != null)
-                    currentElement = current.item;
+                current = nextNode(current);
+                currentElement = (current == null) ? null : current.item;
                 return x;
             } finally {
-                takeLock.unlock();
-                putLock.unlock();
+                fullyUnlock();
             }
         }
 
         public void remove() {
             if (lastRet == null)
                 throw new IllegalStateException();
-            final ReentrantLock putLock = LinkedBlockingQueue.this.putLock;
-            final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock;
-            putLock.lock();
-            takeLock.lock();
+            fullyLock();
             try {
                 Node<E> node = lastRet;
                 lastRet = null;
-                Node<E> trail = head;
-                Node<E> p = head.next;
-                while (p != null && p != node) {
-                    trail = p;
-                    p = p.next;
-                }
-                if (p == node) {
-                    p.item = null;
-                    trail.next = p.next;
-                    if (last == p)
-                        last = trail;
-                    int c = count.getAndDecrement();
-                    if (c == capacity)
-                        notFull.signalAll();
+                for (Node<E> trail = head, p = trail.next;
+                     p != null;
+                     trail = p, p = p.next) {
+                    if (p == node) {
+                        unlink(p, trail);
+                        break;
+                    }
                 }
             } finally {
-                takeLock.unlock();
-                putLock.unlock();
+                fullyUnlock();
             }
         }
     }
@@ -789,7 +821,7 @@
      * Save the state to a stream (that is, serialize it).
      *
      * @serialData The capacity is emitted (int), followed by all of
-     * its elements (each an <tt>Object</tt>) in the proper order,
+     * its elements (each an {@code Object}) in the proper order,
      * followed by a null
      * @param s the stream
      */
@@ -815,6 +847,7 @@
     /**
      * Reconstitute this queue instance from a stream (that is,
      * deserialize it).
+     *
      * @param s the stream
      */
     private void readObject(java.io.ObjectInputStream s)
@@ -827,6 +860,7 @@
 
         // Read in all elements and place in queue
         for (;;) {
+            @SuppressWarnings("unchecked")
             E item = (E)s.readObject();
             if (item == null)
                 break;
--- a/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java	Tue Aug 18 19:53:43 2009 -0700
@@ -44,15 +44,11 @@
      * localized display strings.
      */
     public Object[][] getContents() {
-        return contents;
-    }
+        // The table holding the mapping between the programmatic keys
+        // and the display strings for the en_US locale.
+        return new Object[][] {
 
-    /**
-     * The table holding the mapping between the programmatic keys
-     * and the display strings for the en_US locale.
-     */
-    static final Object[][] contents = {
-    // LOCALIZE THIS
+        // LOCALIZE THIS
         // Role names
 //        { "application","application" },
 //        { "border","border" },
@@ -151,5 +147,6 @@
         { "vertical","vertical" },
         { "horizontal","horizontal" }
     // END OF MATERIAL TO LOCALIZE
-    };
+        };
+    }
 }
--- a/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java	Tue Aug 18 19:53:43 2009 -0700
@@ -78,7 +78,7 @@
         super(locale);
 
         // Set compression types ("BI_RGB" denotes uncompressed).
-        compressionTypes = BMPConstants.compressionTypeNames;
+        compressionTypes = BMPConstants.compressionTypeNames.clone();
 
         // Set compression flag.
         canWriteCompressed = true;
--- a/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -77,7 +77,10 @@
      * A single-element array, initially containing
      * <code>ImageInputStream.class</code>, to be returned from
      * <code>getInputTypes</code>.
+     * @deprecated Instead of using this field, directly create
+     * the equivalent array <code>{ ImageInputStream.class }<code>.
      */
+    @Deprecated
     public static final Class[] STANDARD_INPUT_TYPE =
         { ImageInputStream.class };
 
@@ -227,7 +230,11 @@
             throw new IllegalArgumentException
                 ("inputTypes.length == 0!");
         }
-        this.inputTypes = (Class[])inputTypes.clone();
+
+        this.inputTypes = (inputTypes == STANDARD_INPUT_TYPE) ?
+            new Class<?>[] { ImageInputStream.class } :
+            inputTypes.clone();
+
         // If length == 0, leave it null
         if (writerSpiNames != null && writerSpiNames.length > 0) {
             this.writerSpiNames = (String[])writerSpiNames.clone();
--- a/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -77,9 +77,12 @@
 
     /**
      * A single-element array, initially containing
-     * <code>ImageInputStream.class</code>, to be returned from
-     * <code>getInputTypes</code>.
+     * <code>ImageOutputStream.class</code>, to be returned from
+     * <code>getOutputTypes</code>.
+     * @deprecated Instead of using this field, directly create
+     * the equivalent array <code>{ ImageOutputStream.class }<code>.
      */
+    @Deprecated
     public static final Class[] STANDARD_OUTPUT_TYPE =
         { ImageOutputStream.class };
 
@@ -228,7 +231,11 @@
             throw new IllegalArgumentException
                 ("outputTypes.length == 0!");
         }
-        this.outputTypes = (Class[])outputTypes.clone();
+
+        this.outputTypes = (outputTypes == STANDARD_OUTPUT_TYPE) ?
+            new Class<?>[] { ImageOutputStream.class } :
+            outputTypes.clone();
+
         // If length == 0, leave it null
         if (readerSpiNames != null && readerSpiNames.length > 0) {
             this.readerSpiNames = (String[])readerSpiNames.clone();
--- a/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java	Tue Aug 18 19:53:43 2009 -0700
@@ -62,6 +62,10 @@
     /** The DisposerRecord that closes the underlying cache. */
     private final DisposerRecord disposerRecord;
 
+    /** The CloseAction that closes the stream in
+     *  the StreamCloser's shutdown hook                     */
+    private final StreamCloser.CloseAction closeAction;
+
     /**
      * Constructs a <code>FileCacheImageInputStream</code> that will read
      * from a given <code>InputStream</code>.
@@ -96,7 +100,9 @@
         this.cacheFile =
             File.createTempFile("imageio", ".tmp", cacheDir);
         this.cache = new RandomAccessFile(cacheFile, "rw");
-        StreamCloser.addToQueue(this);
+
+        this.closeAction = StreamCloser.createCloseAction(this);
+        StreamCloser.addToQueue(closeAction);
 
         disposerRecord = new StreamDisposerRecord(cacheFile, cache);
         if (getClass() == FileCacheImageInputStream.class) {
@@ -242,7 +248,7 @@
         stream = null;
         cache = null;
         cacheFile = null;
-        StreamCloser.removeFromQueue(this);
+        StreamCloser.removeFromQueue(closeAction);
     }
 
     /**
--- a/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java	Tue Aug 18 19:53:43 2009 -0700
@@ -48,6 +48,10 @@
     // Pos after last (rightmost) byte written
     private long maxStreamPos = 0L;
 
+    /** The CloseAction that closes the stream in
+     *  the StreamCloser's shutdown hook                     */
+    private final StreamCloser.CloseAction closeAction;
+
     /**
      * Constructs a <code>FileCacheImageOutputStream</code> that will write
      * to a given <code>outputStream</code>.
@@ -82,7 +86,9 @@
         this.cacheFile =
             File.createTempFile("imageio", ".tmp", cacheDir);
         this.cache = new RandomAccessFile(cacheFile, "rw");
-        StreamCloser.addToQueue(this);
+
+        this.closeAction = StreamCloser.createCloseAction(this);
+        StreamCloser.addToQueue(closeAction);
     }
 
     public int read() throws IOException {
@@ -227,7 +233,7 @@
         cacheFile = null;
         stream.flush();
         stream = null;
-        StreamCloser.removeFromQueue(this);
+        StreamCloser.removeFromQueue(closeAction);
     }
 
     public void flushBefore(long pos) throws IOException {
--- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java	Tue Aug 18 19:53:43 2009 -0700
@@ -690,7 +690,7 @@
     private static <T> T convertFromString(String s, OpenType<T> openType) {
         Class<T> c;
         try {
-            c = cast(Class.forName(openType.getClassName()));
+            c = cast(Class.forName(openType.safeGetClassName()));
         } catch (ClassNotFoundException e) {
             throw new NoClassDefFoundError(e.toString());  // can't happen
         }
@@ -711,7 +711,7 @@
             } catch (Exception e) {
                 final String msg =
                     "Could not convert \"" + s + "\" using method: " + valueOf;
-                throw new IllegalArgumentException(msg);
+                throw new IllegalArgumentException(msg, e);
             }
         }
 
@@ -728,7 +728,7 @@
             } catch (Exception e) {
                 final String msg =
                     "Could not convert \"" + s + "\" using constructor: " + con;
-                throw new IllegalArgumentException(msg);
+                throw new IllegalArgumentException(msg, e);
             }
         }
 
@@ -757,7 +757,7 @@
             stringArrayClass =
                 Class.forName(squareBrackets + "Ljava.lang.String;");
             targetArrayClass =
-                Class.forName(squareBrackets + "L" + baseType.getClassName() +
+                Class.forName(squareBrackets + "L" + baseType.safeGetClassName() +
                               ";");
         } catch (ClassNotFoundException e) {
             throw new NoClassDefFoundError(e.toString());  // can't happen
--- a/jdk/src/share/classes/javax/management/openmbean/OpenType.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/management/openmbean/OpenType.java	Tue Aug 18 19:53:43 2009 -0700
@@ -304,7 +304,12 @@
      * @return the class name.
      */
     public String getClassName() {
+        return className;
+    }
 
+    // A version of getClassName() that can only be called from within this
+    // package and that cannot be overridden.
+    String safeGetClassName() {
         return className;
     }
 
--- a/jdk/src/share/classes/javax/swing/plaf/synth/Region.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/swing/plaf/synth/Region.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-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
@@ -24,8 +24,13 @@
  */
 package javax.swing.plaf.synth;
 
-import javax.swing.*;
-import java.util.*;
+import sun.awt.AppContext;
+
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import javax.swing.JComponent;
+import javax.swing.UIDefaults;
 
 /**
  * A distinct rendering area of a Swing component.  A component may
@@ -67,8 +72,8 @@
  * @author Scott Violet
  */
 public class Region {
-    private static final Map<String, Region> uiToRegionMap = new HashMap<String, Region>();
-    private static final Map<Region, String> lowerCaseNameMap = new HashMap<Region, String>();
+    private static final Object UI_TO_REGION_MAP_KEY = new Object();
+    private static final Object LOWER_CASE_NAME_MAP_KEY = new Object();
 
     /**
      * ArrowButton's are special types of buttons that also render a
@@ -77,396 +82,433 @@
      * To bind a style to this <code>Region</code> use the name
      * <code>ArrowButton</code>.
      */
-    public static final Region ARROW_BUTTON = new Region("ArrowButton",
-                                                         "ArrowButtonUI");
+    public static final Region ARROW_BUTTON = new Region("ArrowButton", false);
 
     /**
      * Button region. To bind a style to this <code>Region</code> use the name
      * <code>Button</code>.
      */
-    public static final Region BUTTON = new Region("Button",
-                                                   "ButtonUI");
+    public static final Region BUTTON = new Region("Button", false);
 
     /**
      * CheckBox region. To bind a style to this <code>Region</code> use the name
      * <code>CheckBox</code>.
      */
-    public static final Region CHECK_BOX = new Region("CheckBox",
-                                                   "CheckBoxUI");
+    public static final Region CHECK_BOX = new Region("CheckBox", false);
 
     /**
      * CheckBoxMenuItem region. To bind a style to this <code>Region</code> use
      * the name <code>CheckBoxMenuItem</code>.
      */
-    public static final Region CHECK_BOX_MENU_ITEM = new Region(
-                                     "CheckBoxMenuItem", "CheckBoxMenuItemUI");
+    public static final Region CHECK_BOX_MENU_ITEM = new Region("CheckBoxMenuItem", false);
 
     /**
      * ColorChooser region. To bind a style to this <code>Region</code> use
      * the name <code>ColorChooser</code>.
      */
-    public static final Region COLOR_CHOOSER = new Region(
-                                     "ColorChooser", "ColorChooserUI");
+    public static final Region COLOR_CHOOSER = new Region("ColorChooser", false);
 
     /**
      * ComboBox region. To bind a style to this <code>Region</code> use
      * the name <code>ComboBox</code>.
      */
-    public static final Region COMBO_BOX = new Region(
-                                     "ComboBox", "ComboBoxUI");
+    public static final Region COMBO_BOX = new Region("ComboBox", false);
 
     /**
      * DesktopPane region. To bind a style to this <code>Region</code> use
      * the name <code>DesktopPane</code>.
      */
-    public static final Region DESKTOP_PANE = new Region("DesktopPane",
-                                                         "DesktopPaneUI");
+    public static final Region DESKTOP_PANE = new Region("DesktopPane", false);
+
     /**
      * DesktopIcon region. To bind a style to this <code>Region</code> use
      * the name <code>DesktopIcon</code>.
      */
-    public static final Region DESKTOP_ICON = new Region("DesktopIcon",
-                                                         "DesktopIconUI");
+    public static final Region DESKTOP_ICON = new Region("DesktopIcon", false);
 
     /**
      * EditorPane region. To bind a style to this <code>Region</code> use
      * the name <code>EditorPane</code>.
      */
-    public static final Region EDITOR_PANE = new Region("EditorPane",
-                                                        "EditorPaneUI");
+    public static final Region EDITOR_PANE = new Region("EditorPane", false);
 
     /**
      * FileChooser region. To bind a style to this <code>Region</code> use
      * the name <code>FileChooser</code>.
      */
-    public static final Region FILE_CHOOSER = new Region("FileChooser",
-                                                         "FileChooserUI");
+    public static final Region FILE_CHOOSER = new Region("FileChooser", false);
 
     /**
      * FormattedTextField region. To bind a style to this <code>Region</code> use
      * the name <code>FormattedTextField</code>.
      */
-    public static final Region FORMATTED_TEXT_FIELD = new Region(
-                            "FormattedTextField", "FormattedTextFieldUI");
+    public static final Region FORMATTED_TEXT_FIELD = new Region("FormattedTextField", false);
 
     /**
      * InternalFrame region. To bind a style to this <code>Region</code> use
      * the name <code>InternalFrame</code>.
      */
-    public static final Region INTERNAL_FRAME = new Region("InternalFrame",
-                                                           "InternalFrameUI");
+    public static final Region INTERNAL_FRAME = new Region("InternalFrame", false);
+
     /**
      * TitlePane of an InternalFrame. The TitlePane typically
      * shows a menu, title, widgets to manipulate the internal frame.
      * To bind a style to this <code>Region</code> use the name
      * <code>InternalFrameTitlePane</code>.
      */
-    public static final Region INTERNAL_FRAME_TITLE_PANE =
-                         new Region("InternalFrameTitlePane",
-                                    "InternalFrameTitlePaneUI");
+    public static final Region INTERNAL_FRAME_TITLE_PANE = new Region("InternalFrameTitlePane", false);
 
     /**
      * Label region. To bind a style to this <code>Region</code> use the name
      * <code>Label</code>.
      */
-    public static final Region LABEL = new Region("Label", "LabelUI");
+    public static final Region LABEL = new Region("Label", false);
 
     /**
      * List region. To bind a style to this <code>Region</code> use the name
      * <code>List</code>.
      */
-    public static final Region LIST = new Region("List", "ListUI");
+    public static final Region LIST = new Region("List", false);
 
     /**
      * Menu region. To bind a style to this <code>Region</code> use the name
      * <code>Menu</code>.
      */
-    public static final Region MENU = new Region("Menu", "MenuUI");
+    public static final Region MENU = new Region("Menu", false);
 
     /**
      * MenuBar region. To bind a style to this <code>Region</code> use the name
      * <code>MenuBar</code>.
      */
-    public static final Region MENU_BAR = new Region("MenuBar", "MenuBarUI");
+    public static final Region MENU_BAR = new Region("MenuBar", false);
 
     /**
      * MenuItem region. To bind a style to this <code>Region</code> use the name
      * <code>MenuItem</code>.
      */
-    public static final Region MENU_ITEM = new Region("MenuItem","MenuItemUI");
+    public static final Region MENU_ITEM = new Region("MenuItem", false);
 
     /**
      * Accelerator region of a MenuItem. To bind a style to this
      * <code>Region</code> use the name <code>MenuItemAccelerator</code>.
      */
-    public static final Region MENU_ITEM_ACCELERATOR = new Region(
-                                         "MenuItemAccelerator");
+    public static final Region MENU_ITEM_ACCELERATOR = new Region("MenuItemAccelerator", true);
 
     /**
      * OptionPane region. To bind a style to this <code>Region</code> use
      * the name <code>OptionPane</code>.
      */
-    public static final Region OPTION_PANE = new Region("OptionPane",
-                                                        "OptionPaneUI");
+    public static final Region OPTION_PANE = new Region("OptionPane", false);
 
     /**
      * Panel region. To bind a style to this <code>Region</code> use the name
      * <code>Panel</code>.
      */
-    public static final Region PANEL = new Region("Panel", "PanelUI");
+    public static final Region PANEL = new Region("Panel", false);
 
     /**
      * PasswordField region. To bind a style to this <code>Region</code> use
      * the name <code>PasswordField</code>.
      */
-    public static final Region PASSWORD_FIELD = new Region("PasswordField",
-                                                           "PasswordFieldUI");
+    public static final Region PASSWORD_FIELD = new Region("PasswordField", false);
 
     /**
      * PopupMenu region. To bind a style to this <code>Region</code> use
      * the name <code>PopupMenu</code>.
      */
-    public static final Region POPUP_MENU = new Region("PopupMenu",
-                                                       "PopupMenuUI");
+    public static final Region POPUP_MENU = new Region("PopupMenu", false);
 
     /**
      * PopupMenuSeparator region. To bind a style to this <code>Region</code>
      * use the name <code>PopupMenuSeparator</code>.
      */
-    public static final Region POPUP_MENU_SEPARATOR = new Region(
-                           "PopupMenuSeparator", "PopupMenuSeparatorUI");
+    public static final Region POPUP_MENU_SEPARATOR = new Region("PopupMenuSeparator", false);
 
     /**
      * ProgressBar region. To bind a style to this <code>Region</code>
      * use the name <code>ProgressBar</code>.
      */
-    public static final Region PROGRESS_BAR = new Region("ProgressBar",
-                                                         "ProgressBarUI");
+    public static final Region PROGRESS_BAR = new Region("ProgressBar", false);
 
     /**
      * RadioButton region. To bind a style to this <code>Region</code>
      * use the name <code>RadioButton</code>.
      */
-    public static final Region RADIO_BUTTON = new Region(
-                               "RadioButton", "RadioButtonUI");
+    public static final Region RADIO_BUTTON = new Region("RadioButton", false);
 
     /**
      * RegionButtonMenuItem region. To bind a style to this <code>Region</code>
      * use the name <code>RadioButtonMenuItem</code>.
      */
-    public static final Region RADIO_BUTTON_MENU_ITEM = new Region(
-                               "RadioButtonMenuItem", "RadioButtonMenuItemUI");
+    public static final Region RADIO_BUTTON_MENU_ITEM = new Region("RadioButtonMenuItem", false);
 
     /**
      * RootPane region. To bind a style to this <code>Region</code> use
      * the name <code>RootPane</code>.
      */
-    public static final Region ROOT_PANE = new Region("RootPane",
-                                                      "RootPaneUI");
+    public static final Region ROOT_PANE = new Region("RootPane", false);
 
     /**
      * ScrollBar region. To bind a style to this <code>Region</code> use
      * the name <code>ScrollBar</code>.
      */
-    public static final Region SCROLL_BAR = new Region("ScrollBar",
-                                                       "ScrollBarUI");
+    public static final Region SCROLL_BAR = new Region("ScrollBar", false);
+
     /**
      * Track of the ScrollBar. To bind a style to this <code>Region</code> use
      * the name <code>ScrollBarTrack</code>.
      */
-    public static final Region SCROLL_BAR_TRACK = new Region("ScrollBarTrack");
+    public static final Region SCROLL_BAR_TRACK = new Region("ScrollBarTrack", true);
+
     /**
      * Thumb of the ScrollBar. The thumb is the region of the ScrollBar
      * that gives a graphical depiction of what percentage of the View is
      * currently visible. To bind a style to this <code>Region</code> use
      * the name <code>ScrollBarThumb</code>.
      */
-    public static final Region SCROLL_BAR_THUMB = new Region("ScrollBarThumb");
+    public static final Region SCROLL_BAR_THUMB = new Region("ScrollBarThumb", true);
 
     /**
      * ScrollPane region. To bind a style to this <code>Region</code> use
      * the name <code>ScrollPane</code>.
      */
-    public static final Region SCROLL_PANE = new Region("ScrollPane",
-                                                        "ScrollPaneUI");
+    public static final Region SCROLL_PANE = new Region("ScrollPane", false);
 
     /**
      * Separator region. To bind a style to this <code>Region</code> use
      * the name <code>Separator</code>.
      */
-    public static final Region SEPARATOR = new Region("Separator",
-                                                      "SeparatorUI");
+    public static final Region SEPARATOR = new Region("Separator", false);
 
     /**
      * Slider region. To bind a style to this <code>Region</code> use
      * the name <code>Slider</code>.
      */
-    public static final Region SLIDER = new Region("Slider", "SliderUI");
+    public static final Region SLIDER = new Region("Slider", false);
+
     /**
      * Track of the Slider. To bind a style to this <code>Region</code> use
      * the name <code>SliderTrack</code>.
      */
-    public static final Region SLIDER_TRACK = new Region("SliderTrack");
+    public static final Region SLIDER_TRACK = new Region("SliderTrack", true);
+
     /**
      * Thumb of the Slider. The thumb of the Slider identifies the current
      * value. To bind a style to this <code>Region</code> use the name
      * <code>SliderThumb</code>.
      */
-    public static final Region SLIDER_THUMB = new Region("SliderThumb");
+    public static final Region SLIDER_THUMB = new Region("SliderThumb", true);
 
     /**
      * Spinner region. To bind a style to this <code>Region</code> use the name
      * <code>Spinner</code>.
      */
-    public static final Region SPINNER = new Region("Spinner", "SpinnerUI");
+    public static final Region SPINNER = new Region("Spinner", false);
 
     /**
      * SplitPane region. To bind a style to this <code>Region</code> use the name
      * <code>SplitPane</code>.
      */
-    public static final Region SPLIT_PANE = new Region("SplitPane",
-                                                      "SplitPaneUI");
+    public static final Region SPLIT_PANE = new Region("SplitPane", false);
 
     /**
      * Divider of the SplitPane. To bind a style to this <code>Region</code>
      * use the name <code>SplitPaneDivider</code>.
      */
-    public static final Region SPLIT_PANE_DIVIDER = new Region(
-                                        "SplitPaneDivider");
+    public static final Region SPLIT_PANE_DIVIDER = new Region("SplitPaneDivider", true);
 
     /**
      * TabbedPane region. To bind a style to this <code>Region</code> use
      * the name <code>TabbedPane</code>.
      */
-    public static final Region TABBED_PANE = new Region("TabbedPane",
-                                                        "TabbedPaneUI");
+    public static final Region TABBED_PANE = new Region("TabbedPane", false);
+
     /**
      * Region of a TabbedPane for one tab. To bind a style to this
      * <code>Region</code> use the name <code>TabbedPaneTab</code>.
      */
-    public static final Region TABBED_PANE_TAB = new Region("TabbedPaneTab");
+    public static final Region TABBED_PANE_TAB = new Region("TabbedPaneTab", true);
+
     /**
      * Region of a TabbedPane containing the tabs. To bind a style to this
      * <code>Region</code> use the name <code>TabbedPaneTabArea</code>.
      */
-    public static final Region TABBED_PANE_TAB_AREA =
-                                 new Region("TabbedPaneTabArea");
+    public static final Region TABBED_PANE_TAB_AREA = new Region("TabbedPaneTabArea", true);
+
     /**
      * Region of a TabbedPane containing the content. To bind a style to this
      * <code>Region</code> use the name <code>TabbedPaneContent</code>.
      */
-    public static final Region TABBED_PANE_CONTENT =
-                                 new Region("TabbedPaneContent");
+    public static final Region TABBED_PANE_CONTENT = new Region("TabbedPaneContent", true);
 
     /**
      * Table region. To bind a style to this <code>Region</code> use
      * the name <code>Table</code>.
      */
-    public static final Region TABLE = new Region("Table", "TableUI");
+    public static final Region TABLE = new Region("Table", false);
 
     /**
      * TableHeader region. To bind a style to this <code>Region</code> use
      * the name <code>TableHeader</code>.
      */
-    public static final Region TABLE_HEADER = new Region("TableHeader",
-                                                         "TableHeaderUI");
+    public static final Region TABLE_HEADER = new Region("TableHeader", false);
+
     /**
      * TextArea region. To bind a style to this <code>Region</code> use
      * the name <code>TextArea</code>.
      */
-    public static final Region TEXT_AREA = new Region("TextArea",
-                                                      "TextAreaUI");
+    public static final Region TEXT_AREA = new Region("TextArea", false);
 
     /**
      * TextField region. To bind a style to this <code>Region</code> use
      * the name <code>TextField</code>.
      */
-    public static final Region TEXT_FIELD = new Region("TextField",
-                                                       "TextFieldUI");
+    public static final Region TEXT_FIELD = new Region("TextField", false);
 
     /**
      * TextPane region. To bind a style to this <code>Region</code> use
      * the name <code>TextPane</code>.
      */
-    public static final Region TEXT_PANE = new Region("TextPane",
-                                                      "TextPaneUI");
+    public static final Region TEXT_PANE = new Region("TextPane", false);
 
     /**
      * ToggleButton region. To bind a style to this <code>Region</code> use
      * the name <code>ToggleButton</code>.
      */
-    public static final Region TOGGLE_BUTTON = new Region("ToggleButton",
-                                                          "ToggleButtonUI");
+    public static final Region TOGGLE_BUTTON = new Region("ToggleButton", false);
 
     /**
      * ToolBar region. To bind a style to this <code>Region</code> use
      * the name <code>ToolBar</code>.
      */
-    public static final Region TOOL_BAR = new Region("ToolBar", "ToolBarUI");
+    public static final Region TOOL_BAR = new Region("ToolBar", false);
+
     /**
      * Region of the ToolBar containing the content. To bind a style to this
      * <code>Region</code> use the name <code>ToolBarContent</code>.
      */
-    public static final Region TOOL_BAR_CONTENT = new Region("ToolBarContent");
+    public static final Region TOOL_BAR_CONTENT = new Region("ToolBarContent", true);
+
     /**
      * Region for the Window containing the ToolBar. To bind a style to this
      * <code>Region</code> use the name <code>ToolBarDragWindow</code>.
      */
-    public static final Region TOOL_BAR_DRAG_WINDOW = new Region(
-                                        "ToolBarDragWindow", null, false);
+    public static final Region TOOL_BAR_DRAG_WINDOW = new Region("ToolBarDragWindow", false);
 
     /**
      * ToolTip region. To bind a style to this <code>Region</code> use
      * the name <code>ToolTip</code>.
      */
-    public static final Region TOOL_TIP = new Region("ToolTip", "ToolTipUI");
+    public static final Region TOOL_TIP = new Region("ToolTip", false);
 
     /**
      * ToolBar separator region. To bind a style to this <code>Region</code> use
      * the name <code>ToolBarSeparator</code>.
      */
-    public static final Region TOOL_BAR_SEPARATOR = new Region(
-                          "ToolBarSeparator", "ToolBarSeparatorUI");
+    public static final Region TOOL_BAR_SEPARATOR = new Region("ToolBarSeparator", false);
 
     /**
      * Tree region. To bind a style to this <code>Region</code> use the name
      * <code>Tree</code>.
      */
-    public static final Region TREE = new Region("Tree", "TreeUI");
+    public static final Region TREE = new Region("Tree", false);
+
     /**
      * Region of the Tree for one cell. To bind a style to this
      * <code>Region</code> use the name <code>TreeCell</code>.
      */
-    public static final Region TREE_CELL = new Region("TreeCell");
+    public static final Region TREE_CELL = new Region("TreeCell", true);
 
     /**
      * Viewport region. To bind a style to this <code>Region</code> use
      * the name <code>Viewport</code>.
      */
-    public static final Region VIEWPORT = new Region("Viewport", "ViewportUI");
-
+    public static final Region VIEWPORT = new Region("Viewport", false);
 
-    private String name;
-    private boolean subregion;
+    private static Map<String, Region> getUItoRegionMap() {
+        AppContext context = AppContext.getAppContext();
+        Map<String, Region> map = (Map<String, Region>) context.get(UI_TO_REGION_MAP_KEY);
+        if (map == null) {
+            map = new HashMap<String, Region>();
+            map.put("ArrowButtonUI", ARROW_BUTTON);
+            map.put("ButtonUI", BUTTON);
+            map.put("CheckBoxUI", CHECK_BOX);
+            map.put("CheckBoxMenuItemUI", CHECK_BOX_MENU_ITEM);
+            map.put("ColorChooserUI", COLOR_CHOOSER);
+            map.put("ComboBoxUI", COMBO_BOX);
+            map.put("DesktopPaneUI", DESKTOP_PANE);
+            map.put("DesktopIconUI", DESKTOP_ICON);
+            map.put("EditorPaneUI", EDITOR_PANE);
+            map.put("FileChooserUI", FILE_CHOOSER);
+            map.put("FormattedTextFieldUI", FORMATTED_TEXT_FIELD);
+            map.put("InternalFrameUI", INTERNAL_FRAME);
+            map.put("InternalFrameTitlePaneUI", INTERNAL_FRAME_TITLE_PANE);
+            map.put("LabelUI", LABEL);
+            map.put("ListUI", LIST);
+            map.put("MenuUI", MENU);
+            map.put("MenuBarUI", MENU_BAR);
+            map.put("MenuItemUI", MENU_ITEM);
+            map.put("OptionPaneUI", OPTION_PANE);
+            map.put("PanelUI", PANEL);
+            map.put("PasswordFieldUI", PASSWORD_FIELD);
+            map.put("PopupMenuUI", POPUP_MENU);
+            map.put("PopupMenuSeparatorUI", POPUP_MENU_SEPARATOR);
+            map.put("ProgressBarUI", PROGRESS_BAR);
+            map.put("RadioButtonUI", RADIO_BUTTON);
+            map.put("RadioButtonMenuItemUI", RADIO_BUTTON_MENU_ITEM);
+            map.put("RootPaneUI", ROOT_PANE);
+            map.put("ScrollBarUI", SCROLL_BAR);
+            map.put("ScrollPaneUI", SCROLL_PANE);
+            map.put("SeparatorUI", SEPARATOR);
+            map.put("SliderUI", SLIDER);
+            map.put("SpinnerUI", SPINNER);
+            map.put("SplitPaneUI", SPLIT_PANE);
+            map.put("TabbedPaneUI", TABBED_PANE);
+            map.put("TableUI", TABLE);
+            map.put("TableHeaderUI", TABLE_HEADER);
+            map.put("TextAreaUI", TEXT_AREA);
+            map.put("TextFieldUI", TEXT_FIELD);
+            map.put("TextPaneUI", TEXT_PANE);
+            map.put("ToggleButtonUI", TOGGLE_BUTTON);
+            map.put("ToolBarUI", TOOL_BAR);
+            map.put("ToolTipUI", TOOL_TIP);
+            map.put("ToolBarSeparatorUI", TOOL_BAR_SEPARATOR);
+            map.put("TreeUI", TREE);
+            map.put("ViewportUI", VIEWPORT);
+            context.put(UI_TO_REGION_MAP_KEY, map);
+        }
+        return map;
+    }
 
+    private static Map<Region, String> getLowerCaseNameMap() {
+        AppContext context = AppContext.getAppContext();
+        Map<Region, String> map = (Map<Region, String>) context.get(LOWER_CASE_NAME_MAP_KEY);
+        if (map == null) {
+            map = new HashMap<Region, String>();
+            context.put(LOWER_CASE_NAME_MAP_KEY, map);
+        }
+        return map;
+    }
 
     static Region getRegion(JComponent c) {
-        return uiToRegionMap.get(c.getUIClassID());
+        return getUItoRegionMap().get(c.getUIClassID());
     }
 
     static void registerUIs(UIDefaults table) {
-        for (String key : uiToRegionMap.keySet()) {
+        for (Object key : getUItoRegionMap().keySet()) {
             table.put(key, "javax.swing.plaf.synth.SynthLookAndFeel");
         }
     }
 
+    private final String name;
+    private final boolean subregion;
 
-    Region(String name) {
-        this(name, null, true);
-    }
-
-    Region(String name, String ui) {
-        this(name, ui, false);
+    private Region(String name, boolean subregion) {
+        if (name == null) {
+            throw new NullPointerException("You must specify a non-null name");
+        }
+        this.name = name;
+        this.subregion = subregion;
     }
 
     /**
@@ -481,14 +523,10 @@
      * @param subregion Whether or not this is a subregion.
      */
     protected Region(String name, String ui, boolean subregion) {
-        if (name == null) {
-            throw new NullPointerException("You must specify a non-null name");
+        this(name, subregion);
+        if (ui != null) {
+            getUItoRegionMap().put(ui, this);
         }
-        this.name = name;
-        if (ui != null) {
-            uiToRegionMap.put(ui, this);
-        }
-        this.subregion = subregion;
     }
 
     /**
@@ -514,16 +552,17 @@
 
     /**
      * Returns the name, in lowercase.
+     *
+     * @return lower case representation of the name of the Region
      */
     String getLowerCaseName() {
-        synchronized(lowerCaseNameMap) {
-            String lowerCaseName = lowerCaseNameMap.get(this);
-            if (lowerCaseName == null) {
-                lowerCaseName = getName().toLowerCase();
-                lowerCaseNameMap.put(this, lowerCaseName);
-            }
-            return lowerCaseName;
+        Map<Region, String> lowerCaseNameMap = getLowerCaseNameMap();
+        String lowerCaseName = lowerCaseNameMap.get(this);
+        if (lowerCaseName == null) {
+            lowerCaseName = name.toLowerCase(Locale.ENGLISH);
+            lowerCaseNameMap.put(this, lowerCaseName);
         }
+        return lowerCaseName;
     }
 
     /**
@@ -531,6 +570,7 @@
      *
      * @return name of the Region.
      */
+    @Override
     public String toString() {
         return name;
     }
--- a/jdk/src/share/classes/javax/swing/text/LayoutQueue.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/javax/swing/text/LayoutQueue.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,6 +25,7 @@
 package javax.swing.text;
 
 import java.util.Vector;
+import sun.awt.AppContext;
 
 /**
  * A queue of text layout tasks.
@@ -35,10 +36,10 @@
  */
 public class LayoutQueue {
 
-    Vector<Runnable> tasks;
-    Thread worker;
+    private static final Object DEFAULT_QUEUE = new Object();
 
-    static LayoutQueue defaultQueue;
+    private Vector<Runnable> tasks;
+    private Thread worker;
 
     /**
      * Construct a layout queue.
@@ -51,10 +52,15 @@
      * Fetch the default layout queue.
      */
     public static LayoutQueue getDefaultQueue() {
-        if (defaultQueue == null) {
-            defaultQueue = new LayoutQueue();
+        AppContext ac = AppContext.getAppContext();
+        synchronized (DEFAULT_QUEUE) {
+            LayoutQueue defaultQueue = (LayoutQueue) ac.get(DEFAULT_QUEUE);
+            if (defaultQueue == null) {
+                defaultQueue = new LayoutQueue();
+                ac.put(DEFAULT_QUEUE, defaultQueue);
+            }
+            return defaultQueue;
         }
-        return defaultQueue;
     }
 
     /**
@@ -63,7 +69,9 @@
      * @param q the new queue.
      */
     public static void setDefaultQueue(LayoutQueue q) {
-        defaultQueue = q;
+        synchronized (DEFAULT_QUEUE) {
+            AppContext.getAppContext().put(DEFAULT_QUEUE, q);
+        }
     }
 
     /**
--- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java	Tue Aug 18 19:53:43 2009 -0700
@@ -19,7 +19,7 @@
  *
  */
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2005-2009 Sun Microsystems, Inc. All rights reserved.
  */
 /*
  * $Id: DOMHMACSignatureMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $
@@ -58,6 +58,7 @@
         Logger.getLogger("org.jcp.xml.dsig.internal.dom");
     private Mac hmac;
     private int outputLength;
+    private boolean outputLengthSet;
 
     /**
      * Creates a <code>DOMHMACSignatureMethod</code> with the specified params
@@ -87,6 +88,7 @@
                     ("params must be of type HMACParameterSpec");
             }
             outputLength = ((HMACParameterSpec) params).getOutputLength();
+            outputLengthSet = true;
             if (log.isLoggable(Level.FINE)) {
                 log.log(Level.FINE,
                     "Setting outputLength from HMACParameterSpec to: "
@@ -101,6 +103,7 @@
         throws MarshalException {
         outputLength = new Integer
             (paramsElem.getFirstChild().getNodeValue()).intValue();
+        outputLengthSet = true;
         if (log.isLoggable(Level.FINE)) {
             log.log(Level.FINE, "unmarshalled outputLength: " + outputLength);
         }
@@ -135,23 +138,13 @@
                 throw new XMLSignatureException(nsae);
             }
         }
-        if (log.isLoggable(Level.FINE)) {
-            log.log(Level.FINE, "outputLength = " + outputLength);
+        if (outputLengthSet && outputLength < getDigestLength()) {
+            throw new XMLSignatureException
+                ("HMACOutputLength must not be less than " + getDigestLength());
         }
         hmac.init((SecretKey) key);
         si.canonicalize(context, new MacOutputStream(hmac));
         byte[] result = hmac.doFinal();
-        if (log.isLoggable(Level.FINE)) {
-            log.log(Level.FINE, "resultLength = " + result.length);
-        }
-        if (outputLength != -1) {
-            int byteLength = outputLength/8;
-            if (result.length > byteLength) {
-                byte[] truncated = new byte[byteLength];
-                System.arraycopy(result, 0, truncated, 0, byteLength);
-                result = truncated;
-            }
-        }
 
         return MessageDigest.isEqual(sig, result);
     }
@@ -171,18 +164,13 @@
                 throw new XMLSignatureException(nsae);
             }
         }
+        if (outputLengthSet && outputLength < getDigestLength()) {
+            throw new XMLSignatureException
+                ("HMACOutputLength must not be less than " + getDigestLength());
+        }
         hmac.init((SecretKey) key);
         si.canonicalize(context, new MacOutputStream(hmac));
-        byte[] result = hmac.doFinal();
-        if (outputLength != -1) {
-            int byteLength = outputLength/8;
-            if (result.length > byteLength) {
-                byte[] truncated = new byte[byteLength];
-                System.arraycopy(result, 0, truncated, 0, byteLength);
-                result = truncated;
-            }
-        }
-        return result;
+        return hmac.doFinal();
     }
 
     boolean paramsEqual(AlgorithmParameterSpec spec) {
@@ -197,6 +185,11 @@
         return (outputLength == ospec.getOutputLength());
     }
 
+    /**
+     * Returns the output length of the hash/digest.
+     */
+    abstract int getDigestLength();
+
     static final class SHA1 extends DOMHMACSignatureMethod {
         SHA1(AlgorithmParameterSpec params)
             throws InvalidAlgorithmParameterException {
@@ -211,6 +204,9 @@
         String getSignatureAlgorithm() {
             return "HmacSHA1";
         }
+        int getDigestLength() {
+            return 160;
+        }
     }
 
     static final class SHA256 extends DOMHMACSignatureMethod {
@@ -227,6 +223,9 @@
         String getSignatureAlgorithm() {
             return "HmacSHA256";
         }
+        int getDigestLength() {
+            return 256;
+        }
     }
 
     static final class SHA384 extends DOMHMACSignatureMethod {
@@ -243,6 +242,9 @@
         String getSignatureAlgorithm() {
             return "HmacSHA384";
         }
+        int getDigestLength() {
+            return 384;
+        }
     }
 
     static final class SHA512 extends DOMHMACSignatureMethod {
@@ -259,5 +261,8 @@
         String getSignatureAlgorithm() {
             return "HmacSHA512";
         }
+        int getDigestLength() {
+            return 512;
+        }
     }
 }
--- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java	Tue Aug 18 19:53:43 2009 -0700
@@ -16,7 +16,7 @@
  *
  * 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 Sf, tifth Floor, Boston, MA 02110-1301 USA.
+ * 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
--- a/jdk/src/share/classes/sun/misc/URLClassPath.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/misc/URLClassPath.java	Tue Aug 18 19:53:43 2009 -0700
@@ -51,6 +51,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.security.cert.Certificate;
 import sun.misc.FileURLMapper;
+import sun.net.util.URLUtil;
 
 /**
  * This class is used to maintain a search path of URLs for loading classes
@@ -80,7 +81,7 @@
     ArrayList<Loader> loaders = new ArrayList<Loader>();
 
     /* Map of each URL opened to its corresponding Loader */
-    HashMap<URL, Loader> lmap = new HashMap<URL, Loader>();
+    HashMap<String, Loader> lmap = new HashMap<String, Loader>();
 
     /* The jar protocol handler to use when creating new URLs */
     private URLStreamHandler jarHandler;
@@ -317,7 +318,8 @@
             // Skip this URL if it already has a Loader. (Loader
             // may be null in the case where URL has not been opened
             // but is referenced by a JAR index.)
-            if (lmap.containsKey(url)) {
+            String urlNoFragString = URLUtil.urlNoFragString(url);
+            if (lmap.containsKey(urlNoFragString)) {
                 continue;
             }
             // Otherwise, create a new Loader for the URL.
@@ -336,7 +338,7 @@
             }
             // Finally, add the Loader to the search path.
             loaders.add(loader);
-            lmap.put(url, loader);
+            lmap.put(urlNoFragString, loader);
         }
         return loaders.get(index);
     }
@@ -576,7 +578,7 @@
         private JarIndex index;
         private MetaIndex metaIndex;
         private URLStreamHandler handler;
-        private HashMap<URL, Loader> lmap;
+        private HashMap<String, Loader> lmap;
         private boolean closed = false;
 
         /*
@@ -584,7 +586,7 @@
          * a JAR file.
          */
         JarLoader(URL url, URLStreamHandler jarHandler,
-                  HashMap<URL, Loader> loaderMap)
+                  HashMap<String, Loader> loaderMap)
             throws IOException
         {
             super(new URL("jar", "", -1, url + "!/", jarHandler));
@@ -663,8 +665,9 @@
                                         try {
                                             URL jarURL = new URL(csu, jarfiles[i]);
                                             // If a non-null loader already exists, leave it alone.
-                                            if (!lmap.containsKey(jarURL)) {
-                                                lmap.put(jarURL, null);
+                                            String urlNoFragString = URLUtil.urlNoFragString(jarURL);
+                                            if (!lmap.containsKey(urlNoFragString)) {
+                                                lmap.put(urlNoFragString, null);
                                             }
                                         } catch (MalformedURLException e) {
                                             continue;
@@ -806,7 +809,7 @@
             if (index == null)
                 return null;
 
-            HashSet<URL> visited = new HashSet<URL>();
+            HashSet<String> visited = new HashSet<String>();
             return getResource(name, check, visited);
         }
 
@@ -818,7 +821,7 @@
          * non-existent resource
          */
         Resource getResource(final String name, boolean check,
-                             Set<URL> visited) {
+                             Set<String> visited) {
 
             Resource res;
             Object[] jarFiles;
@@ -843,7 +846,8 @@
 
                     try{
                         url = new URL(csu, jarName);
-                        if ((newLoader = (JarLoader)lmap.get(url)) == null) {
+                        String urlNoFragString = URLUtil.urlNoFragString(url);
+                        if ((newLoader = (JarLoader)lmap.get(urlNoFragString)) == null) {
                             /* no loader has been set up for this jar file
                              * before
                              */
@@ -867,7 +871,7 @@
                             }
 
                             /* put it in the global hashtable */
-                            lmap.put(url, newLoader);
+                            lmap.put(urlNoFragString, newLoader);
                         }
                     } catch (java.security.PrivilegedActionException pae) {
                         continue;
@@ -879,7 +883,7 @@
                     /* Note that the addition of the url to the list of visited
                      * jars incorporates a check for presence in the hashmap
                      */
-                    boolean visitedURL = !visited.add(url);
+                    boolean visitedURL = !visited.add(URLUtil.urlNoFragString(url));
                     if (!visitedURL) {
                         try {
                             newLoader.ensureOpen();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/ApplicationProxy.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,43 @@
+/*
+ * 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.net;
+
+import java.net.Proxy;
+import java.net.SocketAddress;
+
+/**
+ * Proxy wrapper class so that we can determine application set
+ * proxies by type.
+ */
+public final class ApplicationProxy extends Proxy {
+    private ApplicationProxy(Proxy proxy) {
+        super(proxy.type(), proxy.address());
+    }
+
+    public static ApplicationProxy create(Proxy proxy) {
+        return new ApplicationProxy(proxy);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/util/URLUtil.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,80 @@
+/*
+ * 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.net.util;
+
+import java.net.URL;
+
+/**
+ * URL Utility class.
+ */
+public class URLUtil {
+    /**
+     * Returns a string form of the url suitable for use as a key in HashMap/Sets.
+     *
+     * The string form should be behave in the same manner as the URL when
+     * compared for equality in a HashMap/Set, except that no nameservice
+     * lookup is done on the hostname (only string comparison), and the fragment
+     * is not considered.
+     *
+     * @see java.net.URLStreamHandler.sameFile(java.net.URL)
+     */
+    public static String urlNoFragString(URL url) {
+        StringBuilder strForm = new StringBuilder();
+
+        String protocol = url.getProtocol();
+        if (protocol != null) {
+            /* protocol is compared case-insensitive, so convert to lowercase */
+            protocol = protocol.toLowerCase();
+            strForm.append(protocol);
+            strForm.append("://");
+        }
+
+        String host = url.getHost();
+        if (host != null) {
+            /* host is compared case-insensitive, so convert to lowercase */
+            host = host.toLowerCase();
+            strForm.append(host);
+
+            int port = url.getPort();
+            if (port == -1) {
+                /* if no port is specificed then use the protocols
+                 * default, if there is one */
+                port = url.getDefaultPort();
+            }
+            if (port != -1) {
+                strForm.append(":").append(port);
+            }
+        }
+
+        String file = url.getFile();
+        if (file != null) {
+            strForm.append(file);
+        }
+
+        return strForm.toString();
+    }
+}
+
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Tue Aug 18 19:53:43 2009 -0700
@@ -578,12 +578,20 @@
         responses = new MessageHeader();
         this.handler = handler;
         instProxy = p;
-        cookieHandler = java.security.AccessController.doPrivileged(
-            new java.security.PrivilegedAction<CookieHandler>() {
+        if (instProxy instanceof sun.net.ApplicationProxy) {
+            /* Application set Proxies should not have access to cookies
+             * in a secure environment unless explicitly allowed. */
+            try {
+                cookieHandler = CookieHandler.getDefault();
+            } catch (SecurityException se) { /* swallow exception */ }
+        } else {
+            cookieHandler = java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<CookieHandler>() {
                 public CookieHandler run() {
-                return CookieHandler.getDefault();
-            }
-        });
+                    return CookieHandler.getDefault();
+                }
+            });
+        }
         cacheHandler = java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<ResponseCache>() {
                 public ResponseCache run() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/classes/sun/security/ec/ECDSASignature.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/classes/sun/security/ec/SunEC.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/classes/sun/security/ec/SunECEntries.java	Tue Aug 18 19:53:43 2009 -0700
@@ -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");
+    }
+}
--- a/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-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
@@ -27,14 +27,13 @@
 
 import org.ietf.jgss.*;
 import sun.security.jgss.spi.*;
-import sun.security.jgss.*;
 import sun.security.util.ObjectIdentifier;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-
+import com.sun.security.jgss.*;
 
 /**
  * This class represents the JGSS security context and its associated
@@ -88,7 +87,7 @@
  * per-message operations are returned in an instance of the MessageProp
  * class, which is used as an argument in these calls.</dl>
  */
-class GSSContextImpl implements GSSContext {
+class GSSContextImpl implements ExtendedGSSContext {
 
     private GSSManagerImpl gssManager = null;
 
@@ -630,4 +629,16 @@
         srcName = null;
         targName = null;
     }
+
+    @Override
+    public Object inquireSecContext(InquireType type) throws GSSException {
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkPermission(new InquireSecContextPermission(type.toString()));
+        }
+        if (mechCtxt == null) {
+            throw new GSSException(GSSException.NO_CONTEXT);
+        }
+        return mechCtxt.inquireSecContext(type);
+    }
 }
--- a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2000-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
@@ -25,12 +25,14 @@
 
 package sun.security.jgss.krb5;
 
+import com.sun.security.jgss.AuthorizationDataEntry;
 import org.ietf.jgss.*;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.IOException;
 import sun.security.krb5.*;
 import java.net.InetAddress;
+import sun.security.krb5.internal.AuthorizationData;
+import sun.security.krb5.internal.KerberosTime;
 
 class InitSecContextToken extends InitialToken {
 
@@ -59,6 +61,9 @@
 
         Checksum checksum = gssChecksum.getChecksum();
 
+        context.setTktFlags(serviceTicket.getFlags());
+        context.setAuthTime(
+                new KerberosTime(serviceTicket.getAuthTime()).toString());
         apReq = new KrbApReq(serviceTicket,
                              mutualRequired,
                              useSubkey,
@@ -143,6 +148,21 @@
             // Use the same sequence number as the peer
             // (Behaviour exhibited by the Windows SSPI server)
             context.resetMySequenceNumber(peerSeqNumber);
+        context.setAuthTime(
+                new KerberosTime(apReq.getCreds().getAuthTime()).toString());
+        context.setTktFlags(apReq.getCreds().getFlags());
+        AuthorizationData ad = apReq.getCreds().getAuthzData();
+        if (ad == null) {
+            context.setAuthzData(null);
+        } else {
+            AuthorizationDataEntry[] authzData =
+                    new AuthorizationDataEntry[ad.count()];
+            for (int i=0; i<ad.count(); i++) {
+                authzData[i] = new AuthorizationDataEntry(
+                        ad.item(i).adType, ad.item(i).adData);
+            }
+            context.setAuthzData(authzData);
+        }
     }
 
     public final KrbApReq getKrbApReq() {
--- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,6 +25,7 @@
 
 package sun.security.jgss.krb5;
 
+import com.sun.security.jgss.InquireType;
 import org.ietf.jgss.*;
 import sun.misc.HexDumpEncoder;
 import sun.security.jgss.GSSUtil;
@@ -38,6 +39,7 @@
 import java.security.Provider;
 import java.security.AccessController;
 import java.security.AccessControlContext;
+import java.security.Key;
 import java.security.PrivilegedExceptionAction;
 import java.security.PrivilegedActionException;
 import javax.crypto.Cipher;
@@ -1283,4 +1285,81 @@
         // Currently used by InitialToken only
         return caller;
     }
+
+    /**
+     * The session key returned by inquireSecContext(KRB5_INQ_SSPI_SESSION_KEY)
+     */
+    static class KerberosSessionKey implements Key {
+        private final EncryptionKey key;
+
+        KerberosSessionKey(EncryptionKey key) {
+            this.key = key;
+        }
+
+        @Override
+        public String getAlgorithm() {
+            return Integer.toString(key.getEType());
+        }
+
+        @Override
+        public String getFormat() {
+            return "RAW";
+        }
+
+        @Override
+        public byte[] getEncoded() {
+            return key.getBytes().clone();
+        }
+
+        @Override
+        public String toString() {
+            return "Kerberos session key: etype: " + key.getEType() + "\n" +
+                    new sun.misc.HexDumpEncoder().encodeBuffer(key.getBytes());
+        }
+    }
+
+    /**
+     * Return the mechanism-specific attribute associated with {@code type}.
+     */
+    public Object inquireSecContext(InquireType type)
+            throws GSSException {
+        if (!isEstablished()) {
+             throw new GSSException(GSSException.NO_CONTEXT, -1,
+                     "Security context not established.");
+        }
+        switch (type) {
+            case KRB5_GET_SESSION_KEY:
+                return new KerberosSessionKey(key);
+            case KRB5_GET_TKT_FLAGS:
+                return tktFlags.clone();
+            case KRB5_GET_AUTHZ_DATA:
+                if (isInitiator()) {
+                    throw new GSSException(GSSException.UNAVAILABLE, -1,
+                            "AuthzData not available on initiator side.");
+                } else {
+                    return (authzData==null)?null:authzData.clone();
+                }
+            case KRB5_GET_AUTHTIME:
+                return authTime;
+        }
+        throw new GSSException(GSSException.UNAVAILABLE, -1,
+                "Inquire type not supported.");
+    }
+
+    // Helpers for inquireSecContext
+    private boolean[] tktFlags;
+    private String authTime;
+    private com.sun.security.jgss.AuthorizationDataEntry[] authzData;
+
+    public void setTktFlags(boolean[] tktFlags) {
+        this.tktFlags = tktFlags;
+    }
+
+    public void setAuthTime(String authTime) {
+        this.authTime = authTime;
+    }
+
+    public void setAuthzData(com.sun.security.jgss.AuthorizationDataEntry[] authzData) {
+        this.authzData = authzData;
+    }
 }
--- a/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright 2000-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Portions Copyright 2000-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
@@ -46,6 +46,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.Provider;
+import com.sun.security.jgss.*;
 
 /**
  * This interface is implemented by a mechanism specific instance of a GSS
@@ -265,7 +266,6 @@
      * @param msgPro on input it contains the requested qop and
      *    confidentiality state, on output, the applied values
      * @exception GSSException may be thrown
-     * @see MessageInfo
      * @see unwrap
      */
     public void wrap(InputStream is, OutputStream os, MessageProp msgProp)
@@ -315,7 +315,6 @@
      * @param msgProp will contain the applied qop and confidentiality
      *    of the input token and any informatory status values
      * @exception GSSException may be thrown
-     * @see MessageInfo
      * @see wrap
      */
     public void unwrap(InputStream is, OutputStream os,
@@ -403,4 +402,15 @@
      * @exception GSSException may be thrown
      */
     public void dispose() throws GSSException;
+
+    /**
+     * Return the mechanism-specific attribute associated with (@code type}.
+     *
+     * @param type the type of the attribute requested
+     * @return the attribute
+     * @throws GSSException see {@link ExtendedGSSContext#inquireSecContext}
+     * for details
+     */
+    public Object inquireSecContext(InquireType type)
+            throws GSSException;
 }
--- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,10 +25,10 @@
 
 package sun.security.jgss.spnego;
 
+import com.sun.security.jgss.ExtendedGSSContext;
+import com.sun.security.jgss.InquireType;
 import java.io.*;
 import java.security.Provider;
-import java.util.List;
-import java.util.ArrayList;
 import org.ietf.jgss.*;
 import sun.security.jgss.*;
 import sun.security.jgss.spi.*;
@@ -1185,4 +1185,22 @@
                 return ("Unknown state " + state);
         }
     }
+
+    /**
+     * Retrieve attribute of the context for {@code type}.
+     */
+    public Object inquireSecContext(InquireType type)
+            throws GSSException {
+        if (mechContext == null) {
+            throw new GSSException(GSSException.NO_CONTEXT, -1,
+                    "Underlying mech not established.");
+        }
+        if (mechContext instanceof ExtendedGSSContext) {
+            return ((ExtendedGSSContext)mechContext).inquireSecContext(type);
+        } else {
+            throw new GSSException(GSSException.BAD_MECH, -1,
+                    "inquireSecContext not supported by underlying mech.");
+        }
+    }
+
 }
--- a/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-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
@@ -36,6 +36,7 @@
 import sun.security.jgss.spnego.NegTokenInit;
 import sun.security.jgss.spnego.NegTokenTarg;
 import javax.security.auth.kerberos.DelegationPermission;
+import com.sun.security.jgss.InquireType;
 import java.io.*;
 
 
@@ -615,4 +616,10 @@
     protected void finalize() throws Throwable {
         dispose();
     }
+
+    public Object inquireSecContext(InquireType type)
+            throws GSSException {
+        throw new GSSException(GSSException.UNAVAILABLE, -1,
+                "Inquire type not supported.");
+    }
 }
--- a/jdk/src/share/classes/sun/security/krb5/Credentials.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/Credentials.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Portions Copyright 2000-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
@@ -63,6 +63,7 @@
     KerberosTime renewTill;
     HostAddresses cAddr;
     EncryptionKey serviceKey;
+    AuthorizationData authzData;
     private static boolean DEBUG = Krb5.DEBUG;
     private static CredentialsCache cache;
     static boolean alreadyLoaded = false;
@@ -78,6 +79,22 @@
                        KerberosTime new_startTime,
                        KerberosTime new_endTime,
                        KerberosTime renewTill,
+                       HostAddresses cAddr,
+                       AuthorizationData authzData) {
+        this(new_ticket, new_client, new_server, new_key, new_flags,
+                authTime, new_startTime, new_endTime, renewTill, cAddr);
+        this.authzData = authzData;
+    }
+
+    public Credentials(Ticket new_ticket,
+                       PrincipalName new_client,
+                       PrincipalName new_server,
+                       EncryptionKey new_key,
+                       TicketFlags new_flags,
+                       KerberosTime authTime,
+                       KerberosTime new_startTime,
+                       KerberosTime new_endTime,
+                       KerberosTime renewTill,
                        HostAddresses cAddr) {
         ticket = new_ticket;
         client = new_client;
@@ -213,6 +230,9 @@
         return flags;
     }
 
+    public AuthorizationData getAuthzData() {
+        return authzData;
+    }
     /**
      * Checks if the service ticket returned by the KDC has the OK-AS-DELEGATE
      * flag set
--- a/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/KrbApReq.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Portions Copyright 2000-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
@@ -356,12 +356,13 @@
                                 authenticator.cname,
                                 apReqMessg.ticket.sname,
                                 enc_ticketPart.key,
-                                null,
+                                enc_ticketPart.flags,
                                 enc_ticketPart.authtime,
                                 enc_ticketPart.starttime,
                                 enc_ticketPart.endtime,
                                 enc_ticketPart.renewTill,
-                                enc_ticketPart.caddr);
+                                enc_ticketPart.caddr,
+                                enc_ticketPart.authorizationData);
         if (DEBUG) {
             System.out.println(">>> KrbApReq: authenticate succeed.");
         }
--- a/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java	Tue Aug 18 19:53:43 2009 -0700
@@ -174,4 +174,12 @@
         }
         return retVal;
     }
+
+    public int count() {
+        return entry.length;
+    }
+
+    public AuthorizationDataEntry item(int i) {
+        return (AuthorizationDataEntry)entry[i].clone();
+    }
 }
--- a/jdk/src/share/classes/sun/security/tools/JarSigner.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java	Tue Aug 18 19:53:43 2009 -0700
@@ -412,6 +412,16 @@
         }
         storetype = KeyStoreUtil.niceStoreTypeName(storetype);
 
+        try {
+            if (signedjar != null && new File(signedjar).getCanonicalPath().equals(
+                    new File(jarfile).getCanonicalPath())) {
+                signedjar = null;
+            }
+        } catch (IOException ioe) {
+            // File system error?
+            // Just ignore it.
+        }
+
         if (P11KEYSTORE.equalsIgnoreCase(storetype) ||
                 KeyStoreUtil.isWindowsKeyStore(storetype)) {
             token = true;
--- a/jdk/src/share/classes/sun/security/tools/KeyTool.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java	Tue Aug 18 19:53:43 2009 -0700
@@ -880,41 +880,41 @@
             // might not work properly, since -gencert is slow
             // and there's no data in the pipe at the beginning.
             ByteArrayOutputStream bout = new ByteArrayOutputStream();
-            byte[] b = new byte[4096];
-            while (true) {
-                int len = inStream.read(b);
-                if (len < 0) break;
-                bout.write(b, 0, len);
-            }
-            inStream = new ByteArrayInputStream(bout.toByteArray());
             try {
-                String importAlias = (alias!=null)?alias:keyAlias;
-                if (keyStore.entryInstanceOf(importAlias, KeyStore.PrivateKeyEntry.class)) {
-                    kssave = installReply(importAlias, inStream);
-                    if (kssave) {
-                        System.err.println(rb.getString
-                            ("Certificate reply was installed in keystore"));
-                    } else {
-                        System.err.println(rb.getString
-                            ("Certificate reply was not installed in keystore"));
-                    }
-                } else if (!keyStore.containsAlias(importAlias) ||
-                        keyStore.entryInstanceOf(importAlias,
-                            KeyStore.TrustedCertificateEntry.class)) {
-                    kssave = addTrustedCert(importAlias, inStream);
-                    if (kssave) {
-                        System.err.println(rb.getString
-                            ("Certificate was added to keystore"));
-                    } else {
-                        System.err.println(rb.getString
-                            ("Certificate was not added to keystore"));
-                    }
+                byte[] b = new byte[4096];
+                while (true) {
+                    int len = inStream.read(b);
+                    if (len < 0) break;
+                    bout.write(b, 0, len);
                 }
             } finally {
                 if (inStream != System.in) {
                     inStream.close();
                 }
             }
+            inStream = new ByteArrayInputStream(bout.toByteArray());
+            String importAlias = (alias!=null)?alias:keyAlias;
+            if (keyStore.entryInstanceOf(importAlias, KeyStore.PrivateKeyEntry.class)) {
+                kssave = installReply(importAlias, inStream);
+                if (kssave) {
+                    System.err.println(rb.getString
+                        ("Certificate reply was installed in keystore"));
+                } else {
+                    System.err.println(rb.getString
+                        ("Certificate reply was not installed in keystore"));
+                }
+            } else if (!keyStore.containsAlias(importAlias) ||
+                    keyStore.entryInstanceOf(importAlias,
+                        KeyStore.TrustedCertificateEntry.class)) {
+                kssave = addTrustedCert(importAlias, inStream);
+                if (kssave) {
+                    System.err.println(rb.getString
+                        ("Certificate was added to keystore"));
+                } else {
+                    System.err.println(rb.getString
+                        ("Certificate was not added to keystore"));
+                }
+            }
         } else if (command == IMPORTKEYSTORE) {
             doImportKeyStore();
             kssave = true;
--- a/jdk/src/share/classes/sun/security/tools/PolicyTool.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/classes/sun/security/tools/PolicyTool.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-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
@@ -35,21 +35,16 @@
 import java.lang.reflect.*;
 import java.text.Collator;
 import java.text.MessageFormat;
-import sun.misc.BASE64Decoder;
-import sun.security.provider.PolicyParser.PermissionEntry;
 import sun.security.util.PropertyExpander;
 import sun.security.util.PropertyExpander.ExpandException;
 import java.awt.*;
 import java.awt.event.*;
 import java.security.cert.Certificate;
-import java.security.cert.CertificateFactory;
-import java.security.cert.X509Certificate;
 import java.security.cert.CertificateException;
 import java.security.*;
 import sun.security.provider.*;
 import sun.security.util.PolicyUtil;
 import javax.security.auth.x500.X500Principal;
-import java.util.HashSet;
 
 /**
  * PolicyTool may be used by users and administrators to configure the
@@ -1459,6 +1454,7 @@
         PERM_ARRAY.add(new AWTPerm());
         PERM_ARRAY.add(new DelegationPerm());
         PERM_ARRAY.add(new FilePerm());
+        PERM_ARRAY.add(new InqSecContextPerm());
         PERM_ARRAY.add(new LogPerm());
         PERM_ARRAY.add(new MgmtPerm());
         PERM_ARRAY.add(new MBeanPerm());
@@ -3961,6 +3957,20 @@
     }
 }
 
+class InqSecContextPerm extends Perm {
+    public InqSecContextPerm() {
+    super("InquireSecContextPermission",
+        "com.sun.security.jgss.InquireSecContextPermission",
+        new String[]    {
+                "KRB5_GET_SESSION_KEY",
+                "KRB5_GET_TKT_FLAGS",
+                "KRB5_GET_AUTHZ_DATA",
+                "KRB5_GET_AUTHTIME"
+                },
+        null);
+    }
+}
+
 class LogPerm extends Perm {
     public LogPerm() {
     super("LoggingPermission",
--- a/jdk/src/share/lib/security/java.security	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/lib/security/java.security	Tue Aug 18 19:53:43 2009 -0700
@@ -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
@@ -127,7 +128,7 @@
 # passed to checkPackageAccess unless the
 # corresponding RuntimePermission ("accessClassInPackage."+package) has
 # been granted.
-package.access=sun.
+package.access=sun.,com.sun.imageio.
 
 #
 # List of comma-separated packages that start with or equal this string
--- a/jdk/src/share/lib/security/java.security-solaris	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/lib/security/java.security-solaris	Tue Aug 18 19:53:43 2009 -0700
@@ -46,12 +46,13 @@
 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
@@ -128,7 +129,7 @@
 # passed to checkPackageAccess unless the
 # corresponding RuntimePermission ("accessClassInPackage."+package) has
 # been granted.
-package.access=sun.
+package.access=sun.,com.sun.imageio.
 
 #
 # List of comma-separated packages that start with or equal this string
--- a/jdk/src/share/lib/security/java.security-windows	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/lib/security/java.security-windows	Tue Aug 18 19:53:43 2009 -0700
@@ -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
@@ -128,7 +129,7 @@
 # passed to checkPackageAccess unless the
 # corresponding RuntimePermission ("accessClassInPackage."+package) has
 # been granted.
-package.access=sun.
+package.access=sun.,com.sun.imageio.
 
 #
 # List of comma-separated packages that start with or equal this string
--- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp	Tue Aug 18 19:53:43 2009 -0700
@@ -908,10 +908,12 @@
 
   // place a limit on future CP growth:
   int generous = 0;
-  generous += u->ic_count*3; // implicit name, outer, outer.utf8
-  generous += 40;  // WKUs, misc
-  generous += u->class_count;  // implicit SourceFile strings
-  maxentries = nentries + generous;
+  generous = add_size(generous, u->ic_count); // implicit name
+  generous = add_size(generous, u->ic_count); // outer
+  generous = add_size(generous, u->ic_count); // outer.utf8
+  generous = add_size(generous, 40); // WKUs, misc
+  generous = add_size(generous, u->class_count); // implicit SourceFile strings
+  maxentries = add_size(nentries, generous);
 
   // Note that this CP does not include "empty" entries
   // for longs and doubles.  Those are introduced when
--- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c	Tue Aug 18 19:53:43 2009 -0700
@@ -139,21 +139,45 @@
 
     splash->width = cinfo->output_width;
     splash->height = cinfo->output_height;
+
+    if (!SAFE_TO_ALLOC(splash->imageFormat.depthBytes, splash->width)) {
+        return 0;
+    }
     stride = splash->width * splash->imageFormat.depthBytes;
 
+    if (!SAFE_TO_ALLOC(stride, splash->height)) {
+        return 0;
+    }
+    if (!SAFE_TO_ALLOC(cinfo->output_width, cinfo->output_components)) {
+        return 0;
+    }
+
     splash->frameCount = 1;
     splash->frames = (SplashImage *) malloc(sizeof(SplashImage) *
         splash->frameCount);
+    if (splash->frames == NULL) {
+        return 0;
+    }
     memset(splash->frames, 0, sizeof(SplashImage) *
         splash->frameCount);
+
     splash->loopCount = 1;
+    splash->frames[0].delay = 0;
     splash->frames[0].bitmapBits = malloc(stride * splash->height);
-    splash->frames[0].delay = 0;
+    if (splash->frames[0].bitmapBits == NULL) {
+        free(splash->frames);
+        return 0;
+    }
 
     rowStride = cinfo->output_width * cinfo->output_components;
 
     buffer = (*cinfo->mem->alloc_sarray)
         ((j_common_ptr) cinfo, JPOOL_IMAGE, rowStride, 1);
+    if (buffer == NULL) {
+        free(splash->frames[0].bitmapBits);
+        free(splash->frames);
+        return 0;
+    }
 
     initFormat(&srcFormat, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000);
     srcFormat.byteOrder = BYTE_ORDER_LSBFIRST;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec2.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec2_163.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec2_193.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec2_233.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec2_aff.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec2_mont.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ec_naf.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecc_impl.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecdecode.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl-curve.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl-exp.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl-priv.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl_curve.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl_gf.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecl_mult.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_192.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_224.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_256.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_384.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_521.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_aff.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_jac.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_jm.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/ecp_mont.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/logtab.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/mp_gf2m-priv.h	Tue Aug 18 19:53:43 2009 -0700
@@ -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/jdk/src/share/native/sun/security/ec/mp_gf2m.c	Tue Aug 18 19:53:43 2009 -0700
@@ -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];
+}
+
+/* Compute xor-multiply of two binary polynomials  (a3, a2, a1, a0) x (b3, b2, b1, b0)
+ * result is a binary polynomial in 8 mp_digits r[8].
+ * The caller MUST ensure that r has the right amount of space allocated.
+ */
+void s_bmul_4x4(mp_digit *r, const mp_digit a3, const mp_digit a2, const mp_digit a1,
+        const mp_digit a0, const mp_digit b3, const mp_digit b2, const mp_digit b1,
+        const mp_digit b0)
+{
+        mp_digit zm[4];
+
+        s_bmul_2x2(r+4, a3, a2, b3, b2);            /* fill top 4 words */
+        s_bmul_2x2(zm, a3^a1, a2^a0, b3^b1, b2^b0); /* fill middle 4 words */
+        s_bmul_2x2(r, a1, a0, b1, b0);              /* fill bottom 4 words */
+
+        zm[3] ^= r[3] ^ r[7];
+        zm[2] ^= r[2] ^ r[6];
+        zm[1] ^= r[1] ^ r[5];
+        zm[0] ^= r[0] ^ r[4];
+
+        r[5]  ^= zm[3];
+        r[4]  ^= zm[2];
+        r[3]  ^= zm[1];
+        r[2]  ^= zm[0];
+}
+
+/* Compute addition of two binary polynomials a and b,
+ * store result in c; c could be a or b, a and b could be equal;
+ * c is the bitwise XOR of a and b.
+ */
+mp_err
+mp_badd(const mp_int *a, const mp_int *b, mp_int *c)
+{
+    mp_digit *pa, *pb, *pc;
+    mp_size ix;
+    mp_size used_pa, used_pb;
+    mp_err res = MP_OKAY;
+
+    /* Add all digits up to the precision of b.  If b had more
+     * precision than a initially, swap a, b first
+     */
+    if (MP_USED(a) >= MP_USED(b)) {
+        pa = MP_DIGITS(a);
+        pb = MP_DIGITS(b);
+        used_pa = MP_USED(a);
+        used_pb = MP_USED(b);
+    } else {
+        pa = MP_DIGITS(b);
+        pb = MP_DIGITS(a);
+        used_pa = MP_USED(b);
+        used_pb = MP_USED(a);
+    }
+
+    /* Make sure c has enough precision for the output value */
+    MP_CHECKOK( s_mp_pad(c, used_pa) );
+
+    /* Do word-by-word xor */
+    pc = MP_DIGITS(c);
+    for (ix = 0; ix < used_pb; ix++) {
+        (*pc++) = (*pa++) ^ (*pb++);
+    }
+
+    /* Finish the rest of digits until we're actually done */
+    for (; ix < used_pa; ++ix) {
+        *pc++ = *pa++;
+    }
+
+    MP_USED(c) = used_pa;
+    MP_SIGN(c) = ZPOS;
+    s_mp_clamp(c);
+
+CLEANUP:
+    return res;
+}
+
+#define s_mp_div2(a) MP_CHECKOK( mpl_rsh((a), (a), 1) );
+
+/* Compute binary polynomial multiply d = a * b */
+static void
+s_bmul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
+{
+    mp_digit a_i, a0b0, a1b1, carry = 0;
+    while (a_len--) {
+        a_i = *a++;
+        s_bmul_1x1(&a1b1, &a0b0, a_i, b);
+        *d++ = a0b0 ^ carry;
+        carry = a1b1;
+    }
+    *d = carry;
+}
+
+/* Compute binary polynomial xor multiply accumulate d ^= a * b */
+static void
+s_bmul_d_add(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *d)
+{
+    mp_digit a_i, a0b0, a1b1, carry = 0;
+    while (a_len--) {
+        a_i = *a++;
+        s_bmul_1x1(&a1b1, &a0b0, a_i, b);
+        *d++ ^= a0b0 ^ carry;
+        carry = a1b1;
+    }
+    *d ^= carry;
+}
+
+/* Compute binary polynomial xor multiply c = a * b.
+ * All parameters may be identical.
+ */
+mp_err
+mp_bmul(const mp_int *a, const mp_int *b, mp_int *c)
+{
+    mp_digit *pb, b_i;
+    mp_int tmp;
+    mp_size ib, a_used, b_used;
+    mp_err res = MP_OKAY;
+
+    MP_DIGITS(&tmp) = 0;
+
+    ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+    if (a == c) {
+        MP_CHECKOK( mp_init_copy(&tmp, a) );
+        if (a == b)
+            b = &tmp;
+        a = &tmp;
+    } else if (b == c) {
+        MP_CHECKOK( mp_init_copy(&tmp, b) );
+        b = &tmp;
+    }
+
+    if (MP_USED(a) < MP_USED(b)) {
+        const mp_int *xch = b;      /* switch a and b if b longer */
+        b = a;
+        a = xch;
+    }
+
+    MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
+    MP_CHECKOK( s_mp_pad(c, USED(a) + USED(b)) );
+
+    pb = MP_DIGITS(b);
+    s_bmul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
+
+    /* Outer loop:  Digits of b */
+    a_used = MP_USED(a);
+    b_used = MP_USED(b);
+        MP_USED(c) = a_used + b_used;
+    for (ib = 1; ib < b_used; ib++) {
+        b_i = *pb++;
+
+        /* Inner product:  Digits of a */
+        if (b_i)
+            s_bmul_d_add(MP_DIGITS(a), a_used, b_i, MP_DIGITS(c) + ib);
+        else
+            MP_DIGIT(c, ib + a_used) = b_i;
+    }
+
+    s_mp_clamp(c);
+
+    SIGN(c) = ZPOS;
+
+CLEANUP:
+    mp_clear(&tmp);
+    return res;
+}
+
+
+/* Compute modular reduction of a and store result in r.
+ * r could be a.
+ * For modular arithmetic, the irreducible polynomial f(t) is represented
+ * as an array of int[], where f(t) is of the form:
+ *     f(t) = t^p[0] + t^p[1] + ... + t^p[k]
+ * where m = p[0] > p[1] > ... > p[k] = 0.
+ */
+mp_err
+mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r)
+{
+    int j, k;
+    int n, dN, d0, d1;
+    mp_digit zz, *z, tmp;
+    mp_size used;
+    mp_err res = MP_OKAY;
+
+    /* The algorithm does the reduction in place in r,
+     * if a != r, copy a into r first so reduction can be done in r
+     */
+    if (a != r) {
+        MP_CHECKOK( mp_copy(a, r) );
+    }
+    z = MP_DIGITS(r);
+
+    /* start reduction */
+    dN = p[0] / MP_DIGIT_BITS;
+    used = MP_USED(r);
+
+    for (j = used - 1; j > dN;) {
+
+        zz = z[j];
+        if (zz == 0) {
+            j--; continue;
+        }
+        z[j] = 0;
+
+        for (k = 1; p[k] > 0; k++) {
+            /* reducing component t^p[k] */
+            n = p[0] - p[k];
+            d0 = n % MP_DIGIT_BITS;
+            d1 = MP_DIGIT_BITS - d0;
+            n /= MP_DIGIT_BITS;
+            z[j-n] ^= (zz>>d0);
+            if (d0)
+                z[j-n-1] ^= (zz<<d1);
+        }
+
+        /* reducing component t^0 */
+        n = dN;
+        d0 = p[0] % MP_DIGIT_BITS;
+        d1 = MP_DIGIT_BITS - d0;
+        z[j-n] ^= (zz >> d0);
+        if (d0)
+            z[j-n-1] ^= (zz << d1);
+
+    }
+
+    /* final round of reduction */
+    while (j == dN) {
+
+        d0 = p[0] % MP_DIGIT_BITS;
+        zz = z[dN] >> d0;
+        if (zz == 0) break;
+        d1 = MP_DIGIT_BITS - d0;
+
+        /* clear up the top d1 bits */
+        if (d0) z[dN] = (z[dN] << d1) >> d1;
+        *z ^= zz; /* reduction t^0 component */
+
+        for (k = 1; p[k] > 0; k++) {
+            /* reducing component t^p[k]*/
+            n = p[k] / MP_DIGIT_BITS;
+            d0 = p[k] % MP_DIGIT_BITS;
+            d1 = MP_DIGIT_BITS - d0;
+            z[n] ^= (zz << d0);
+            tmp = zz >> d1;
+            if (d0 && tmp)
+                z[n+1] ^= tmp;
+        }
+    }
+
+    s_mp_clamp(r);
+CLEANUP:
+    return res;
+}
+
+/* Compute the product of two polynomials a and b, reduce modulo p,
+ * Store the result in r.  r could be a or b; a could be b.
+ */
+mp_err
+mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[], mp_int *r)
+{
+    mp_err res;
+
+    if (a == b) return mp_bsqrmod(a, p, r);
+    if ((res = mp_bmul(a, b, r) ) != MP_OKAY)
+        return res;
+    return mp_bmod(r, p, r);
+}
+
+/* Compute binary polynomial squaring c = a*a mod p .
+ * Parameter r and a can be identical.
+ */
+
+mp_err
+mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r)
+{
+    mp_digit *pa, *pr, a_i;
+    mp_int tmp;
+    mp_size ia, a_used;
+    mp_err res;
+
+    ARGCHK(a != NULL && r != NULL, MP_BADARG);
+    MP_DIGITS(&tmp) = 0;
+
+    if (a == r) {
+        MP_CHECKOK( mp_init_copy(&tmp, a) );
+        a = &tmp;
+    }
+
+    MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
+    MP_CHECKOK( s_mp_pad(r, 2*USED(a)) );
+
+    pa = MP_DIGITS(a);
+    pr = MP_DIGITS(r);
+    a_used = MP_USED(a);
+        MP_USED(r) = 2 * a_used;
+
+    for (ia = 0; ia < a_used; ia++) {
+        a_i = *pa++;
+        *pr++ = gf2m_SQR0(a_i);
+        *pr++ = gf2m_SQR1(a_i);
+    }
+
+    MP_CHECKOK( mp_bmod(r, p, r) );
+    s_mp_clamp(r);
+    SIGN(r) = ZPOS;
+
+CLEANUP:
+    mp_clear(&tmp);
+    return res;
+}
+
+/* Compute binary polynomial y/x mod p, y divided by x, reduce modulo p.
+ * Store the result in r. r could be x or y, and x could equal y.
+ * Uses algorithm Modular_Division_GF(2^m) from
+ *     Chang-Shantz, S.  "From Euclid's GCD to Montgomery Multiplication to
+ *     the Great Divide".
+ */
+int
+mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
+    const unsigned int p[], mp_int *r)
+{
+    mp_int aa, bb, uu;
+    mp_int *a, *b, *u, *v;
+    mp_err res = MP_OKAY;
+
+    MP_DIGITS(&aa) = 0;
+    MP_DIGITS(&bb) = 0;
+    MP_DIGITS(&uu) = 0;
+
+    MP_CHECKOK( mp_init_copy(&aa, x) );
+    MP_CHECKOK( mp_init_copy(&uu, y) );
+    MP_CHECKOK( mp_init_copy(&bb, pp) );
+    MP_CHECKOK( s_mp_pad(r, USED(pp)) );
+    MP_USED(r) = 1; MP_DIGIT(r, 0) = 0;
+
+    a = &aa; b= &bb; u=&uu; v=r;
+    /* reduce x and y mod p */
+    MP_CHECKOK( mp_bmod(a, p, a) );
+    MP_CHECKOK( mp_bmod(u, p, u) );
+
+    while (!mp_isodd(a)) {
+        s_mp_div2(a);
+        if (mp_isodd(u)) {
+            MP_CHECKOK( mp_badd(u, pp, u) );
+        }
+        s_mp_div2(u);
+    }
+
+    do {
+        if (mp_cmp_mag(b, a) > 0) {
+            MP_CHECKOK( mp_badd(b, a, b) );
+            MP_CHECKOK( mp_badd(v, u, v) );
+            do {
+                s_mp_div2(b);
+                if (mp_isodd(v)) {
+                    MP_CHECKOK( mp_badd(v, pp, v) );
+                }
+                s_mp_div2(v);
+            } while (!mp_isodd(b));
+        }
+        else if ((MP_DIGIT(a,0) == 1) && (MP_USED(a) == 1))
+            break;
+        else {
+            MP_CHECKOK( mp_badd(a, b, a) );
+            MP_CHECKOK( mp_badd(u, v, u) );
+            do {
+                s_mp_div2(a);
+                if (mp_isodd(u)) {
+                    MP_CHECKOK( mp_badd(u, pp, u) );
+                }
+                s_mp_div2(u);
+            } while (!mp_isodd(a));
+        }
+    } while (1);
+
+    MP_CHECKOK( mp_copy(u, r) );
+
+CLEANUP:
+    /* XXX this appears to be a memory leak in the NSS code */
+    mp_clear(&aa);
+    mp_clear(&bb);
+    mp_clear(&uu);
+    return res;
+
+}
+
+/* Convert the bit-string representation of a polynomial a into an array
+ * of integers corresponding to the bits with non-zero coefficient.
+ * Up to max elements of the array will be filled.  Return value is total
+ * number of coefficients that would be extracted if array was large enough.
+ */
+int
+mp_bpoly2arr(const mp_int *a, unsigned int p[], int max)
+{
+    int i, j, k;
+    mp_digit top_bit, mask;
+
+    top_bit = 1;
+    top_bit <<= MP_DIGIT_BIT - 1;
+
+    for (k = 0; k < max; k++) p[k] = 0;
+    k = 0;
+
+    for (i = MP_USED(a) - 1; i >= 0; i--) {
+        mask = top_bit;
+        for (j = MP_DIGIT_BIT - 1; j >= 0; j--) {
+            if (MP_DIGITS(a)[i] & mask) {
+                if (k < max) p[k] = MP_DIGIT_BIT * i + j;
+                k++;
+            }
+            mask >>= 1;
+        }
+    }
+
+    return k;
+}
+
+/* Convert the coefficient array representation of a polynomial to a
+ * bit-string.  The array must be terminated by 0.
+ */
+mp_err
+mp_barr2poly(const unsigned int p[], mp_int *a)
+{
+
+    mp_err res = MP_OKAY;
+    int i;
+
+    mp_zero(a);
+    for (i = 0; p[i] > 0; i++) {
+        MP_CHECKOK( mpl_set_bit(a, p[i], 1) );
+    }
+    MP_CHECKOK( mpl_set_bit(a, 0, 1) );
+
+CLEANUP:
+    return res;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mp_gf2m.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,83 @@
+/* *********************************************************************
+ *
+ * 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_H_
+#define _MP_GF2M_H_
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+#include "mpi.h"
+
+mp_err mp_badd(const mp_int *a, const mp_int *b, mp_int *c);
+mp_err mp_bmul(const mp_int *a, const mp_int *b, mp_int *c);
+
+/* For modular arithmetic, the irreducible polynomial f(t) is represented
+ * as an array of int[], where f(t) is of the form:
+ *     f(t) = t^p[0] + t^p[1] + ... + t^p[k]
+ * where m = p[0] > p[1] > ... > p[k] = 0.
+ */
+mp_err mp_bmod(const mp_int *a, const unsigned int p[], mp_int *r);
+mp_err mp_bmulmod(const mp_int *a, const mp_int *b, const unsigned int p[],
+    mp_int *r);
+mp_err mp_bsqrmod(const mp_int *a, const unsigned int p[], mp_int *r);
+mp_err mp_bdivmod(const mp_int *y, const mp_int *x, const mp_int *pp,
+    const unsigned int p[], mp_int *r);
+
+int mp_bpoly2arr(const mp_int *a, unsigned int p[], int max);
+mp_err mp_barr2poly(const unsigned int p[], mp_int *a);
+
+#endif /* _MP_GF2M_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mpi-config.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,130 @@
+/* *********************************************************************
+ *
+ * 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1997
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Netscape Communications Corporation
+ *
+ * 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 _MPI_CONFIG_H
+#define _MPI_CONFIG_H
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+/* $Id: mpi-config.h,v 1.5 2004/04/25 15:03:10 gerv%gerv.net Exp $ */
+
+/*
+  For boolean options,
+  0 = no
+  1 = yes
+
+  Other options are documented individually.
+
+ */
+
+#ifndef MP_IOFUNC
+#define MP_IOFUNC     0  /* include mp_print() ?                */
+#endif
+
+#ifndef MP_MODARITH
+#define MP_MODARITH   1  /* include modular arithmetic ?        */
+#endif
+
+#ifndef MP_NUMTH
+#define MP_NUMTH      1  /* include number theoretic functions? */
+#endif
+
+#ifndef MP_LOGTAB
+#define MP_LOGTAB     1  /* use table of logs instead of log()? */
+#endif
+
+#ifndef MP_MEMSET
+#define MP_MEMSET     1  /* use memset() to zero buffers?       */
+#endif
+
+#ifndef MP_MEMCPY
+#define MP_MEMCPY     1  /* use memcpy() to copy buffers?       */
+#endif
+
+#ifndef MP_CRYPTO
+#define MP_CRYPTO     1  /* erase memory on free?               */
+#endif
+
+#ifndef MP_ARGCHK
+/*
+  0 = no parameter checks
+  1 = runtime checks, continue execution and return an error to caller
+  2 = assertions; dump core on parameter errors
+ */
+#ifdef DEBUG
+#define MP_ARGCHK     2  /* how to check input arguments        */
+#else
+#define MP_ARGCHK     1  /* how to check input arguments        */
+#endif
+#endif
+
+#ifndef MP_DEBUG
+#define MP_DEBUG      0  /* print diagnostic output?            */
+#endif
+
+#ifndef MP_DEFPREC
+#define MP_DEFPREC    64 /* default precision, in digits        */
+#endif
+
+#ifndef MP_MACRO
+#define MP_MACRO      0  /* use macros for frequent calls?      */
+#endif
+
+#ifndef MP_SQUARE
+#define MP_SQUARE     1  /* use separate squaring code?         */
+#endif
+
+#endif /* _MPI_CONFIG_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mpi-priv.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,340 @@
+/* *********************************************************************
+ *
+ * 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:
+ *
+ *  Arbitrary precision integer arithmetic library
+ *
+ *  NOTE WELL: the content of this header file is NOT part of the "public"
+ *  API for the MPI library, and may change at any time.
+ *  Application programs that use libmpi should NOT include this header 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Netscape Communications Corporation
+ *
+ * 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 _MPI_PRIV_H
+#define _MPI_PRIV_H
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+/* $Id: mpi-priv.h,v 1.20 2005/11/22 07:16:43 relyea%netscape.com Exp $ */
+
+#include "mpi.h"
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#endif /* _KERNEL */
+
+#if MP_DEBUG
+#include <stdio.h>
+
+#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}
+#else
+#define DIAG(T,V)
+#endif
+
+/* If we aren't using a wired-in logarithm table, we need to include
+   the math library to get the log() function
+ */
+
+/* {{{ s_logv_2[] - log table for 2 in various bases */
+
+#if MP_LOGTAB
+/*
+  A table of the logs of 2 for various bases (the 0 and 1 entries of
+  this table are meaningless and should not be referenced).
+
+  This table is used to compute output lengths for the mp_toradix()
+  function.  Since a number n in radix r takes up about log_r(n)
+  digits, we estimate the output size by taking the least integer
+  greater than log_r(n), where:
+
+  log_r(n) = log_2(n) * log_r(2)
+
+  This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
+  which are the output bases supported.
+ */
+
+extern const float s_logv_2[];
+#define LOG_V_2(R)  s_logv_2[(R)]
+
+#else
+
+/*
+   If MP_LOGTAB is not defined, use the math library to compute the
+   logarithms on the fly.  Otherwise, use the table.
+   Pick which works best for your system.
+ */
+
+#include <math.h>
+#define LOG_V_2(R)  (log(2.0)/log(R))
+
+#endif /* if MP_LOGTAB */
+
+/* }}} */
+
+/* {{{ Digit arithmetic macros */
+
+/*
+  When adding and multiplying digits, the results can be larger than
+  can be contained in an mp_digit.  Thus, an mp_word is used.  These
+  macros mask off the upper and lower digits of the mp_word (the
+  mp_word may be more than 2 mp_digits wide, but we only concern
+  ourselves with the low-order 2 mp_digits)
+ */
+
+#define  CARRYOUT(W)  (mp_digit)((W)>>DIGIT_BIT)
+#define  ACCUM(W)     (mp_digit)(W)
+
+#define MP_MIN(a,b)   (((a) < (b)) ? (a) : (b))
+#define MP_MAX(a,b)   (((a) > (b)) ? (a) : (b))
+#define MP_HOWMANY(a,b) (((a) + (b) - 1)/(b))
+#define MP_ROUNDUP(a,b) (MP_HOWMANY(a,b) * (b))
+
+/* }}} */
+
+/* {{{ Comparison constants */
+
+#define  MP_LT       -1
+#define  MP_EQ        0
+#define  MP_GT        1
+
+/* }}} */
+
+/* {{{ private function declarations */
+
+/*
+   If MP_MACRO is false, these will be defined as actual functions;
+   otherwise, suitable macro definitions will be used.  This works
+   around the fact that ANSI C89 doesn't support an 'inline' keyword
+   (although I hear C9x will ... about bloody time).  At present, the
+   macro definitions are identical to the function bodies, but they'll
+   expand in place, instead of generating a function call.
+
+   I chose these particular functions to be made into macros because
+   some profiling showed they are called a lot on a typical workload,
+   and yet they are primarily housekeeping.
+ */
+#if MP_MACRO == 0
+ void     s_mp_setz(mp_digit *dp, mp_size count); /* zero digits           */
+ void     s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count); /* copy */
+ void    *s_mp_alloc(size_t nb, size_t ni, int flag); /* general allocator    */
+ void     s_mp_free(void *ptr, mp_size);          /* general free function */
+extern unsigned long mp_allocs;
+extern unsigned long mp_frees;
+extern unsigned long mp_copies;
+#else
+
+ /* Even if these are defined as macros, we need to respect the settings
+    of the MP_MEMSET and MP_MEMCPY configuration options...
+  */
+ #if MP_MEMSET == 0
+  #define  s_mp_setz(dp, count) \
+       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;}
+ #else
+  #define  s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit))
+ #endif /* MP_MEMSET */
+
+ #if MP_MEMCPY == 0
+  #define  s_mp_copy(sp, dp, count) \
+       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];}
+ #else
+  #define  s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit))
+ #endif /* MP_MEMCPY */
+
+ #define  s_mp_alloc(nb, ni)  calloc(nb, ni)
+ #define  s_mp_free(ptr) {if(ptr) free(ptr);}
+#endif /* MP_MACRO */
+
+mp_err   s_mp_grow(mp_int *mp, mp_size min);   /* increase allocated size */
+mp_err   s_mp_pad(mp_int *mp, mp_size min);    /* left pad with zeroes    */
+
+#if MP_MACRO == 0
+ void     s_mp_clamp(mp_int *mp);               /* clip leading zeroes     */
+#else
+ #define  s_mp_clamp(mp)\
+  { mp_size used = MP_USED(mp); \
+    while (used > 1 && DIGIT(mp, used - 1) == 0) --used; \
+    MP_USED(mp) = used; \
+  }
+#endif /* MP_MACRO */
+
+void     s_mp_exch(mp_int *a, mp_int *b);      /* swap a and b in place   */
+
+mp_err   s_mp_lshd(mp_int *mp, mp_size p);     /* left-shift by p digits  */
+void     s_mp_rshd(mp_int *mp, mp_size p);     /* right-shift by p digits */
+mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d);  /* multiply by 2^d in place */
+void     s_mp_div_2d(mp_int *mp, mp_digit d);  /* divide by 2^d in place  */
+void     s_mp_mod_2d(mp_int *mp, mp_digit d);  /* modulo 2^d in place     */
+void     s_mp_div_2(mp_int *mp);               /* divide by 2 in place    */
+mp_err   s_mp_mul_2(mp_int *mp);               /* multiply by 2 in place  */
+mp_err   s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd);
+                                               /* normalize for division  */
+mp_err   s_mp_add_d(mp_int *mp, mp_digit d);   /* unsigned digit addition */
+mp_err   s_mp_sub_d(mp_int *mp, mp_digit d);   /* unsigned digit subtract */
+mp_err   s_mp_mul_d(mp_int *mp, mp_digit d);   /* unsigned digit multiply */
+mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);
+                                               /* unsigned digit divide   */
+mp_err   s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu);
+                                               /* Barrett reduction       */
+mp_err   s_mp_add(mp_int *a, const mp_int *b); /* magnitude addition      */
+mp_err   s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c);
+mp_err   s_mp_sub(mp_int *a, const mp_int *b); /* magnitude subtract      */
+mp_err   s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c);
+mp_err   s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset);
+                                               /* a += b * RADIX^offset   */
+mp_err   s_mp_mul(mp_int *a, const mp_int *b); /* magnitude multiply      */
+#if MP_SQUARE
+mp_err   s_mp_sqr(mp_int *a);                  /* magnitude square        */
+#else
+#define  s_mp_sqr(a) s_mp_mul(a, a)
+#endif
+mp_err   s_mp_div(mp_int *rem, mp_int *div, mp_int *quot); /* magnitude div */
+mp_err   s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
+mp_err   s_mp_2expt(mp_int *a, mp_digit k);    /* a = 2^k                 */
+int      s_mp_cmp(const mp_int *a, const mp_int *b); /* magnitude comparison */
+int      s_mp_cmp_d(const mp_int *a, mp_digit d); /* magnitude digit compare */
+int      s_mp_ispow2(const mp_int *v);         /* is v a power of 2?      */
+int      s_mp_ispow2d(mp_digit d);             /* is d a power of 2?      */
+
+int      s_mp_tovalue(char ch, int r);          /* convert ch to value    */
+char     s_mp_todigit(mp_digit val, int r, int low); /* convert val to digit */
+int      s_mp_outlen(int bits, int r);          /* output length in bytes */
+mp_digit s_mp_invmod_radix(mp_digit P);   /* returns (P ** -1) mod RADIX */
+mp_err   s_mp_invmod_odd_m( const mp_int *a, const mp_int *m, mp_int *c);
+mp_err   s_mp_invmod_2d(    const mp_int *a, mp_size k,       mp_int *c);
+mp_err   s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c);
+
+#ifdef NSS_USE_COMBA
+
+#define IS_POWER_OF_2(a) ((a) && !((a) & ((a)-1)))
+
+void s_mp_mul_comba_4(const mp_int *A, const mp_int *B, mp_int *C);
+void s_mp_mul_comba_8(const mp_int *A, const mp_int *B, mp_int *C);
+void s_mp_mul_comba_16(const mp_int *A, const mp_int *B, mp_int *C);
+void s_mp_mul_comba_32(const mp_int *A, const mp_int *B, mp_int *C);
+
+void s_mp_sqr_comba_4(const mp_int *A, mp_int *B);
+void s_mp_sqr_comba_8(const mp_int *A, mp_int *B);
+void s_mp_sqr_comba_16(const mp_int *A, mp_int *B);
+void s_mp_sqr_comba_32(const mp_int *A, mp_int *B);
+
+#endif /* end NSS_USE_COMBA */
+
+/* ------ mpv functions, operate on arrays of digits, not on mp_int's ------ */
+#if defined (__OS2__) && defined (__IBMC__)
+#define MPI_ASM_DECL __cdecl
+#else
+#define MPI_ASM_DECL
+#endif
+
+#ifdef MPI_AMD64
+
+mp_digit MPI_ASM_DECL s_mpv_mul_set_vec64(mp_digit*, mp_digit *, mp_size, mp_digit);
+mp_digit MPI_ASM_DECL s_mpv_mul_add_vec64(mp_digit*, const mp_digit*, mp_size, mp_digit);
+
+/* c = a * b */
+#define s_mpv_mul_d(a, a_len, b, c) \
+        ((unsigned long*)c)[a_len] = s_mpv_mul_set_vec64(c, a, a_len, b)
+
+/* c += a * b */
+#define s_mpv_mul_d_add(a, a_len, b, c) \
+        ((unsigned long*)c)[a_len] = s_mpv_mul_add_vec64(c, a, a_len, b)
+
+#else
+
+void     MPI_ASM_DECL s_mpv_mul_d(const mp_digit *a, mp_size a_len,
+                                        mp_digit b, mp_digit *c);
+void     MPI_ASM_DECL s_mpv_mul_d_add(const mp_digit *a, mp_size a_len,
+                                            mp_digit b, mp_digit *c);
+
+#endif
+
+void     MPI_ASM_DECL s_mpv_mul_d_add_prop(const mp_digit *a,
+                                                mp_size a_len, mp_digit b,
+                                                mp_digit *c);
+void     MPI_ASM_DECL s_mpv_sqr_add_prop(const mp_digit *a,
+                                                mp_size a_len,
+                                                mp_digit *sqrs);
+
+mp_err   MPI_ASM_DECL s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo,
+                            mp_digit divisor, mp_digit *quot, mp_digit *rem);
+
+/* c += a * b * (MP_RADIX ** offset);  */
+#define s_mp_mul_d_add_offset(a, b, c, off) \
+(s_mpv_mul_d_add_prop(MP_DIGITS(a), MP_USED(a), b, MP_DIGITS(c) + off), MP_OKAY)
+
+typedef struct {
+  mp_int       N;       /* modulus N */
+  mp_digit     n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */
+  mp_size      b;       /* R == 2 ** b,  also b = # significant bits in N */
+} mp_mont_modulus;
+
+mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
+                       mp_mont_modulus *mmm);
+mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm);
+
+/*
+ * s_mpi_getProcessorLineSize() returns the size in bytes of the cache line
+ * if a cache exists, or zero if there is no cache. If more than one
+ * cache line exists, it should return the smallest line size (which is
+ * usually the L1 cache).
+ *
+ * mp_modexp uses this information to make sure that private key information
+ * isn't being leaked through the cache.
+ *
+ * see mpcpucache.c for the implementation.
+ */
+unsigned long s_mpi_getProcessorLineSize();
+
+/* }}} */
+#endif /* _MPI_PRIV_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mpi.c	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,4886 @@
+/* *********************************************************************
+ *
+ * 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:
+ *
+ *
+ *  Arbitrary precision integer arithmetic library
+ *
+ * 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Netscape Communications Corporation
+ *   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"
+
+/* $Id: mpi.c,v 1.45 2006/09/29 20:12:21 alexei.volkov.bugs%sun.com Exp $ */
+
+#include "mpi-priv.h"
+#if defined(OSF1)
+#include <c_asm.h>
+#endif
+
+#if MP_LOGTAB
+/*
+  A table of the logs of 2 for various bases (the 0 and 1 entries of
+  this table are meaningless and should not be referenced).
+
+  This table is used to compute output lengths for the mp_toradix()
+  function.  Since a number n in radix r takes up about log_r(n)
+  digits, we estimate the output size by taking the least integer
+  greater than log_r(n), where:
+
+  log_r(n) = log_2(n) * log_r(2)
+
+  This table, therefore, is a table of log_r(2) for 2 <= r <= 36,
+  which are the output bases supported.
+ */
+#include "logtab.h"
+#endif
+
+/* {{{ Constant strings */
+
+/* Constant strings returned by mp_strerror() */
+static const char *mp_err_string[] = {
+  "unknown result code",     /* say what?            */
+  "boolean true",            /* MP_OKAY, MP_YES      */
+  "boolean false",           /* MP_NO                */
+  "out of memory",           /* MP_MEM               */
+  "argument out of range",   /* MP_RANGE             */
+  "invalid input parameter", /* MP_BADARG            */
+  "result is undefined"      /* MP_UNDEF             */
+};
+
+/* Value to digit maps for radix conversion   */
+
+/* s_dmap_1 - standard digits and letters */
+static const char *s_dmap_1 =
+  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
+
+/* }}} */
+
+unsigned long mp_allocs;
+unsigned long mp_frees;
+unsigned long mp_copies;
+
+/* {{{ Default precision manipulation */
+
+/* Default precision for newly created mp_int's      */
+static mp_size s_mp_defprec = MP_DEFPREC;
+
+mp_size mp_get_prec(void)
+{
+  return s_mp_defprec;
+
+} /* end mp_get_prec() */
+
+void         mp_set_prec(mp_size prec)
+{
+  if(prec == 0)
+    s_mp_defprec = MP_DEFPREC;
+  else
+    s_mp_defprec = prec;
+
+} /* end mp_set_prec() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ mp_init(mp, kmflag) */
+
+/*
+  mp_init(mp, kmflag)
+
+  Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,
+  MP_MEM if memory could not be allocated for the structure.
+ */
+
+mp_err mp_init(mp_int *mp, int kmflag)
+{
+  return mp_init_size(mp, s_mp_defprec, kmflag);
+
+} /* end mp_init() */
+
+/* }}} */
+
+/* {{{ mp_init_size(mp, prec, kmflag) */
+
+/*
+  mp_init_size(mp, prec, kmflag)
+
+  Initialize a new zero-valued mp_int with at least the given
+  precision; returns MP_OKAY if successful, or MP_MEM if memory could
+  not be allocated for the structure.
+ */
+
+mp_err mp_init_size(mp_int *mp, mp_size prec, int kmflag)
+{
+  ARGCHK(mp != NULL && prec > 0, MP_BADARG);
+
+  prec = MP_ROUNDUP(prec, s_mp_defprec);
+  if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit), kmflag)) == NULL)
+    return MP_MEM;
+
+  SIGN(mp) = ZPOS;
+  USED(mp) = 1;
+  ALLOC(mp) = prec;
+
+  return MP_OKAY;
+
+} /* end mp_init_size() */
+
+/* }}} */
+
+/* {{{ mp_init_copy(mp, from) */
+
+/*
+  mp_init_copy(mp, from)
+
+  Initialize mp as an exact copy of from.  Returns MP_OKAY if
+  successful, MP_MEM if memory could not be allocated for the new
+  structure.
+ */
+
+mp_err mp_init_copy(mp_int *mp, const mp_int *from)
+{
+  ARGCHK(mp != NULL && from != NULL, MP_BADARG);
+
+  if(mp == from)
+    return MP_OKAY;
+
+  if((DIGITS(mp) = s_mp_alloc(ALLOC(from), sizeof(mp_digit), FLAG(from))) == NULL)
+    return MP_MEM;
+
+  s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));
+  USED(mp) = USED(from);
+  ALLOC(mp) = ALLOC(from);
+  SIGN(mp) = SIGN(from);
+
+#ifndef _WIN32
+  FLAG(mp) = FLAG(from);
+#endif /* _WIN32 */
+
+  return MP_OKAY;
+
+} /* end mp_init_copy() */
+
+/* }}} */
+
+/* {{{ mp_copy(from, to) */
+
+/*
+  mp_copy(from, to)
+
+  Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that
+  'to' has already been initialized (if not, use mp_init_copy()
+  instead). If 'from' and 'to' are identical, nothing happens.
+ */
+
+mp_err mp_copy(const mp_int *from, mp_int *to)
+{
+  ARGCHK(from != NULL && to != NULL, MP_BADARG);
+
+  if(from == to)
+    return MP_OKAY;
+
+  ++mp_copies;
+  { /* copy */
+    mp_digit   *tmp;
+
+    /*
+      If the allocated buffer in 'to' already has enough space to hold
+      all the used digits of 'from', we'll re-use it to avoid hitting
+      the memory allocater more than necessary; otherwise, we'd have
+      to grow anyway, so we just allocate a hunk and make the copy as
+      usual
+     */
+    if(ALLOC(to) >= USED(from)) {
+      s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));
+      s_mp_copy(DIGITS(from), DIGITS(to), USED(from));
+
+    } else {
+      if((tmp = s_mp_alloc(ALLOC(from), sizeof(mp_digit), FLAG(from))) == NULL)
+        return MP_MEM;
+
+      s_mp_copy(DIGITS(from), tmp, USED(from));
+
+      if(DIGITS(to) != NULL) {
+#if MP_CRYPTO
+        s_mp_setz(DIGITS(to), ALLOC(to));
+#endif
+        s_mp_free(DIGITS(to), ALLOC(to));
+      }
+
+      DIGITS(to) = tmp;
+      ALLOC(to) = ALLOC(from);
+    }
+
+    /* Copy the precision and sign from the original */
+    USED(to) = USED(from);
+    SIGN(to) = SIGN(from);
+  } /* end copy */
+
+  return MP_OKAY;
+
+} /* end mp_copy() */
+
+/* }}} */
+
+/* {{{ mp_exch(mp1, mp2) */
+
+/*
+  mp_exch(mp1, mp2)
+
+  Exchange mp1 and mp2 without allocating any intermediate memory
+  (well, unless you count the stack space needed for this call and the
+  locals it creates...).  This cannot fail.
+ */
+
+void mp_exch(mp_int *mp1, mp_int *mp2)
+{
+#if MP_ARGCHK == 2
+  assert(mp1 != NULL && mp2 != NULL);
+#else
+  if(mp1 == NULL || mp2 == NULL)
+    return;
+#endif
+
+  s_mp_exch(mp1, mp2);
+
+} /* end mp_exch() */
+
+/* }}} */
+
+/* {{{ mp_clear(mp) */
+
+/*
+  mp_clear(mp)
+
+  Release the storage used by an mp_int, and void its fields so that
+  if someone calls mp_clear() again for the same int later, we won't
+  get tollchocked.
+ */
+
+void   mp_clear(mp_int *mp)
+{
+  if(mp == NULL)
+    return;
+
+  if(DIGITS(mp) != NULL) {
+#if MP_CRYPTO
+    s_mp_setz(DIGITS(mp), ALLOC(mp));
+#endif
+    s_mp_free(DIGITS(mp), ALLOC(mp));
+    DIGITS(mp) = NULL;
+  }
+
+  USED(mp) = 0;
+  ALLOC(mp) = 0;
+
+} /* end mp_clear() */
+
+/* }}} */
+
+/* {{{ mp_zero(mp) */
+
+/*
+  mp_zero(mp)
+
+  Set mp to zero.  Does not change the allocated size of the structure,
+  and therefore cannot fail (except on a bad argument, which we ignore)
+ */
+void   mp_zero(mp_int *mp)
+{
+  if(mp == NULL)
+    return;
+
+  s_mp_setz(DIGITS(mp), ALLOC(mp));
+  USED(mp) = 1;
+  SIGN(mp) = ZPOS;
+
+} /* end mp_zero() */
+
+/* }}} */
+
+/* {{{ mp_set(mp, d) */
+
+void   mp_set(mp_int *mp, mp_digit d)
+{
+  if(mp == NULL)
+    return;
+
+  mp_zero(mp);
+  DIGIT(mp, 0) = d;
+
+} /* end mp_set() */
+
+/* }}} */
+
+/* {{{ mp_set_int(mp, z) */
+
+mp_err mp_set_int(mp_int *mp, long z)
+{
+  int            ix;
+  unsigned long  v = labs(z);
+  mp_err         res;
+
+  ARGCHK(mp != NULL, MP_BADARG);
+
+  mp_zero(mp);
+  if(z == 0)
+    return MP_OKAY;  /* shortcut for zero */
+
+  if (sizeof v <= sizeof(mp_digit)) {
+    DIGIT(mp,0) = v;
+  } else {
+    for (ix = sizeof(long) - 1; ix >= 0; ix--) {
+      if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
+        return res;
+
+      res = s_mp_add_d(mp, (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));
+      if (res != MP_OKAY)
+        return res;
+    }
+  }
+  if(z < 0)
+    SIGN(mp) = NEG;
+
+  return MP_OKAY;
+
+} /* end mp_set_int() */
+
+/* }}} */
+
+/* {{{ mp_set_ulong(mp, z) */
+
+mp_err mp_set_ulong(mp_int *mp, unsigned long z)
+{
+  int            ix;
+  mp_err         res;
+
+  ARGCHK(mp != NULL, MP_BADARG);
+
+  mp_zero(mp);
+  if(z == 0)
+    return MP_OKAY;  /* shortcut for zero */
+
+  if (sizeof z <= sizeof(mp_digit)) {
+    DIGIT(mp,0) = z;
+  } else {
+    for (ix = sizeof(long) - 1; ix >= 0; ix--) {
+      if ((res = s_mp_mul_d(mp, (UCHAR_MAX + 1))) != MP_OKAY)
+        return res;
+
+      res = s_mp_add_d(mp, (mp_digit)((z >> (ix * CHAR_BIT)) & UCHAR_MAX));
+      if (res != MP_OKAY)
+        return res;
+    }
+  }
+  return MP_OKAY;
+} /* end mp_set_ulong() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Digit arithmetic */
+
+/* {{{ mp_add_d(a, d, b) */
+
+/*
+  mp_add_d(a, d, b)
+
+  Compute the sum b = a + d, for a single digit d.  Respects the sign of
+  its primary addend (single digits are unsigned anyway).
+ */
+
+mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b)
+{
+  mp_int   tmp;
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+    return res;
+
+  if(SIGN(&tmp) == ZPOS) {
+    if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
+      goto CLEANUP;
+  } else if(s_mp_cmp_d(&tmp, d) >= 0) {
+    if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
+      goto CLEANUP;
+  } else {
+    mp_neg(&tmp, &tmp);
+
+    DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
+  }
+
+  if(s_mp_cmp_d(&tmp, 0) == 0)
+    SIGN(&tmp) = ZPOS;
+
+  s_mp_exch(&tmp, b);
+
+CLEANUP:
+  mp_clear(&tmp);
+  return res;
+
+} /* end mp_add_d() */
+
+/* }}} */
+
+/* {{{ mp_sub_d(a, d, b) */
+
+/*
+  mp_sub_d(a, d, b)
+
+  Compute the difference b = a - d, for a single digit d.  Respects the
+  sign of its subtrahend (single digits are unsigned anyway).
+ */
+
+mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b)
+{
+  mp_int   tmp;
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+    return res;
+
+  if(SIGN(&tmp) == NEG) {
+    if((res = s_mp_add_d(&tmp, d)) != MP_OKAY)
+      goto CLEANUP;
+  } else if(s_mp_cmp_d(&tmp, d) >= 0) {
+    if((res = s_mp_sub_d(&tmp, d)) != MP_OKAY)
+      goto CLEANUP;
+  } else {
+    mp_neg(&tmp, &tmp);
+
+    DIGIT(&tmp, 0) = d - DIGIT(&tmp, 0);
+    SIGN(&tmp) = NEG;
+  }
+
+  if(s_mp_cmp_d(&tmp, 0) == 0)
+    SIGN(&tmp) = ZPOS;
+
+  s_mp_exch(&tmp, b);
+
+CLEANUP:
+  mp_clear(&tmp);
+  return res;
+
+} /* end mp_sub_d() */
+
+/* }}} */
+
+/* {{{ mp_mul_d(a, d, b) */
+
+/*
+  mp_mul_d(a, d, b)
+
+  Compute the product b = a * d, for a single digit d.  Respects the sign
+  of its multiplicand (single digits are unsigned anyway)
+ */
+
+mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if(d == 0) {
+    mp_zero(b);
+    return MP_OKAY;
+  }
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  res = s_mp_mul_d(b, d);
+
+  return res;
+
+} /* end mp_mul_d() */
+
+/* }}} */
+
+/* {{{ mp_mul_2(a, c) */
+
+mp_err mp_mul_2(const mp_int *a, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, c)) != MP_OKAY)
+    return res;
+
+  return s_mp_mul_2(c);
+
+} /* end mp_mul_2() */
+
+/* }}} */
+
+/* {{{ mp_div_d(a, d, q, r) */
+
+/*
+  mp_div_d(a, d, q, r)
+
+  Compute the quotient q = a / d and remainder r = a mod d, for a
+  single digit d.  Respects the sign of its divisor (single digits are
+  unsigned anyway).
+ */
+
+mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r)
+{
+  mp_err   res;
+  mp_int   qp;
+  mp_digit rem;
+  int      pow;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  if(d == 0)
+    return MP_RANGE;
+
+  /* Shortcut for powers of two ... */
+  if((pow = s_mp_ispow2d(d)) >= 0) {
+    mp_digit  mask;
+
+    mask = ((mp_digit)1 << pow) - 1;
+    rem = DIGIT(a, 0) & mask;
+
+    if(q) {
+      mp_copy(a, q);
+      s_mp_div_2d(q, pow);
+    }
+
+    if(r)
+      *r = rem;
+
+    return MP_OKAY;
+  }
+
+  if((res = mp_init_copy(&qp, a)) != MP_OKAY)
+    return res;
+
+  res = s_mp_div_d(&qp, d, &rem);
+
+  if(s_mp_cmp_d(&qp, 0) == 0)
+    SIGN(q) = ZPOS;
+
+  if(r)
+    *r = rem;
+
+  if(q)
+    s_mp_exch(&qp, q);
+
+  mp_clear(&qp);
+  return res;
+
+} /* end mp_div_d() */
+
+/* }}} */
+
+/* {{{ mp_div_2(a, c) */
+
+/*
+  mp_div_2(a, c)
+
+  Compute c = a / 2, disregarding the remainder.
+ */
+
+mp_err mp_div_2(const mp_int *a, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, c)) != MP_OKAY)
+    return res;
+
+  s_mp_div_2(c);
+
+  return MP_OKAY;
+
+} /* end mp_div_2() */
+
+/* }}} */
+
+/* {{{ mp_expt_d(a, d, b) */
+
+mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c)
+{
+  mp_int   s, x;
+  mp_err   res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  DIGIT(&s, 0) = 1;
+
+  while(d != 0) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+        goto CLEANUP;
+    }
+
+    d /= 2;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  s_mp_exch(&s, c);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_expt_d() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Full arithmetic */
+
+/* {{{ mp_abs(a, b) */
+
+/*
+  mp_abs(a, b)
+
+  Compute b = |a|.  'a' and 'b' may be identical.
+ */
+
+mp_err mp_abs(const mp_int *a, mp_int *b)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  SIGN(b) = ZPOS;
+
+  return MP_OKAY;
+
+} /* end mp_abs() */
+
+/* }}} */
+
+/* {{{ mp_neg(a, b) */
+
+/*
+  mp_neg(a, b)
+
+  Compute b = -a.  'a' and 'b' may be identical.
+ */
+
+mp_err mp_neg(const mp_int *a, mp_int *b)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  if(s_mp_cmp_d(b, 0) == MP_EQ)
+    SIGN(b) = ZPOS;
+  else
+    SIGN(b) = (SIGN(b) == NEG) ? ZPOS : NEG;
+
+  return MP_OKAY;
+
+} /* end mp_neg() */
+
+/* }}} */
+
+/* {{{ mp_add(a, b, c) */
+
+/*
+  mp_add(a, b, c)
+
+  Compute c = a + b.  All parameters may be identical.
+ */
+
+mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(SIGN(a) == SIGN(b)) { /* same sign:  add values, keep sign */
+    MP_CHECKOK( s_mp_add_3arg(a, b, c) );
+  } else if(s_mp_cmp(a, b) >= 0) {  /* different sign: |a| >= |b|   */
+    MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
+  } else {                          /* different sign: |a|  < |b|   */
+    MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
+  }
+
+  if (s_mp_cmp_d(c, 0) == MP_EQ)
+    SIGN(c) = ZPOS;
+
+CLEANUP:
+  return res;
+
+} /* end mp_add() */
+
+/* }}} */
+
+/* {{{ mp_sub(a, b, c) */
+
+/*
+  mp_sub(a, b, c)
+
+  Compute c = a - b.  All parameters may be identical.
+ */
+
+mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c)
+{
+  mp_err  res;
+  int     magDiff;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if (a == b) {
+    mp_zero(c);
+    return MP_OKAY;
+  }
+
+  if (MP_SIGN(a) != MP_SIGN(b)) {
+    MP_CHECKOK( s_mp_add_3arg(a, b, c) );
+  } else if (!(magDiff = s_mp_cmp(a, b))) {
+    mp_zero(c);
+    res = MP_OKAY;
+  } else if (magDiff > 0) {
+    MP_CHECKOK( s_mp_sub_3arg(a, b, c) );
+  } else {
+    MP_CHECKOK( s_mp_sub_3arg(b, a, c) );
+    MP_SIGN(c) = !MP_SIGN(a);
+  }
+
+  if (s_mp_cmp_d(c, 0) == MP_EQ)
+    MP_SIGN(c) = MP_ZPOS;
+
+CLEANUP:
+  return res;
+
+} /* end mp_sub() */
+
+/* }}} */
+
+/* {{{ mp_mul(a, b, c) */
+
+/*
+  mp_mul(a, b, c)
+
+  Compute c = a * b.  All parameters may be identical.
+ */
+mp_err   mp_mul(const mp_int *a, const mp_int *b, mp_int * c)
+{
+  mp_digit *pb;
+  mp_int   tmp;
+  mp_err   res;
+  mp_size  ib;
+  mp_size  useda, usedb;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if (a == c) {
+    if ((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+      return res;
+    if (a == b)
+      b = &tmp;
+    a = &tmp;
+  } else if (b == c) {
+    if ((res = mp_init_copy(&tmp, b)) != MP_OKAY)
+      return res;
+    b = &tmp;
+  } else {
+    MP_DIGITS(&tmp) = 0;
+  }
+
+  if (MP_USED(a) < MP_USED(b)) {
+    const mp_int *xch = b;      /* switch a and b, to do fewer outer loops */
+    b = a;
+    a = xch;
+  }
+
+  MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
+  if((res = s_mp_pad(c, USED(a) + USED(b))) != MP_OKAY)
+    goto CLEANUP;
+
+#ifdef NSS_USE_COMBA
+  if ((MP_USED(a) == MP_USED(b)) && IS_POWER_OF_2(MP_USED(b))) {
+      if (MP_USED(a) == 4) {
+          s_mp_mul_comba_4(a, b, c);
+          goto CLEANUP;
+      }
+      if (MP_USED(a) == 8) {
+          s_mp_mul_comba_8(a, b, c);
+          goto CLEANUP;
+      }
+      if (MP_USED(a) == 16) {
+          s_mp_mul_comba_16(a, b, c);
+          goto CLEANUP;
+      }
+      if (MP_USED(a) == 32) {
+          s_mp_mul_comba_32(a, b, c);
+          goto CLEANUP;
+      }
+  }
+#endif
+
+  pb = MP_DIGITS(b);
+  s_mpv_mul_d(MP_DIGITS(a), MP_USED(a), *pb++, MP_DIGITS(c));
+
+  /* Outer loop:  Digits of b */
+  useda = MP_USED(a);
+  usedb = MP_USED(b);
+  for (ib = 1; ib < usedb; ib++) {
+    mp_digit b_i    = *pb++;
+
+    /* Inner product:  Digits of a */
+    if (b_i)
+      s_mpv_mul_d_add(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
+    else
+      MP_DIGIT(c, ib + useda) = b_i;
+  }
+
+  s_mp_clamp(c);
+
+  if(SIGN(a) == SIGN(b) || s_mp_cmp_d(c, 0) == MP_EQ)
+    SIGN(c) = ZPOS;
+  else
+    SIGN(c) = NEG;
+
+CLEANUP:
+  mp_clear(&tmp);
+  return res;
+} /* end mp_mul() */
+
+/* }}} */
+
+/* {{{ mp_sqr(a, sqr) */
+
+#if MP_SQUARE
+/*
+  Computes the square of a.  This can be done more
+  efficiently than a general multiplication, because many of the
+  computation steps are redundant when squaring.  The inner product
+  step is a bit more complicated, but we save a fair number of
+  iterations of the multiplication loop.
+ */
+
+/* sqr = a^2;   Caller provides both a and tmp; */
+mp_err   mp_sqr(const mp_int *a, mp_int *sqr)
+{
+  mp_digit *pa;
+  mp_digit d;
+  mp_err   res;
+  mp_size  ix;
+  mp_int   tmp;
+  int      count;
+
+  ARGCHK(a != NULL && sqr != NULL, MP_BADARG);
+
+  if (a == sqr) {
+    if((res = mp_init_copy(&tmp, a)) != MP_OKAY)
+      return res;
+    a = &tmp;
+  } else {
+    DIGITS(&tmp) = 0;
+    res = MP_OKAY;
+  }
+
+  ix = 2 * MP_USED(a);
+  if (ix > MP_ALLOC(sqr)) {
+    MP_USED(sqr) = 1;
+    MP_CHECKOK( s_mp_grow(sqr, ix) );
+  }
+  MP_USED(sqr) = ix;
+  MP_DIGIT(sqr, 0) = 0;
+
+#ifdef NSS_USE_COMBA
+  if (IS_POWER_OF_2(MP_USED(a))) {
+      if (MP_USED(a) == 4) {
+          s_mp_sqr_comba_4(a, sqr);
+          goto CLEANUP;
+      }
+      if (MP_USED(a) == 8) {
+          s_mp_sqr_comba_8(a, sqr);
+          goto CLEANUP;
+      }
+      if (MP_USED(a) == 16) {
+          s_mp_sqr_comba_16(a, sqr);
+          goto CLEANUP;
+      }
+      if (MP_USED(a) == 32) {
+          s_mp_sqr_comba_32(a, sqr);
+          goto CLEANUP;
+      }
+  }
+#endif
+
+  pa = MP_DIGITS(a);
+  count = MP_USED(a) - 1;
+  if (count > 0) {
+    d = *pa++;
+    s_mpv_mul_d(pa, count, d, MP_DIGITS(sqr) + 1);
+    for (ix = 3; --count > 0; ix += 2) {
+      d = *pa++;
+      s_mpv_mul_d_add(pa, count, d, MP_DIGITS(sqr) + ix);
+    } /* for(ix ...) */
+    MP_DIGIT(sqr, MP_USED(sqr)-1) = 0; /* above loop stopped short of this. */
+
+    /* now sqr *= 2 */
+    s_mp_mul_2(sqr);
+  } else {
+    MP_DIGIT(sqr, 1) = 0;
+  }
+
+  /* now add the squares of the digits of a to sqr. */
+  s_mpv_sqr_add_prop(MP_DIGITS(a), MP_USED(a), MP_DIGITS(sqr));
+
+  SIGN(sqr) = ZPOS;
+  s_mp_clamp(sqr);
+
+CLEANUP:
+  mp_clear(&tmp);
+  return res;
+
+} /* end mp_sqr() */
+#endif
+
+/* }}} */
+
+/* {{{ mp_div(a, b, q, r) */
+
+/*
+  mp_div(a, b, q, r)
+
+  Compute q = a / b and r = a mod b.  Input parameters may be re-used
+  as output parameters.  If q or r is NULL, that portion of the
+  computation will be discarded (although it will still be computed)
+ */
+mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r)
+{
+  mp_err   res;
+  mp_int   *pQ, *pR;
+  mp_int   qtmp, rtmp, btmp;
+  int      cmp;
+  mp_sign  signA;
+  mp_sign  signB;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  signA = MP_SIGN(a);
+  signB = MP_SIGN(b);
+
+  if(mp_cmp_z(b) == MP_EQ)
+    return MP_RANGE;
+
+  DIGITS(&qtmp) = 0;
+  DIGITS(&rtmp) = 0;
+  DIGITS(&btmp) = 0;
+
+  /* Set up some temporaries... */
+  if (!r || r == a || r == b) {
+    MP_CHECKOK( mp_init_copy(&rtmp, a) );
+    pR = &rtmp;
+  } else {
+    MP_CHECKOK( mp_copy(a, r) );
+    pR = r;
+  }
+
+  if (!q || q == a || q == b) {
+    MP_CHECKOK( mp_init_size(&qtmp, MP_USED(a), FLAG(a)) );
+    pQ = &qtmp;
+  } else {
+    MP_CHECKOK( s_mp_pad(q, MP_USED(a)) );
+    pQ = q;
+    mp_zero(pQ);
+  }
+
+  /*
+    If |a| <= |b|, we can compute the solution without division;
+    otherwise, we actually do the work required.
+   */
+  if ((cmp = s_mp_cmp(a, b)) <= 0) {
+    if (cmp) {
+      /* r was set to a above. */
+      mp_zero(pQ);
+    } else {
+      mp_set(pQ, 1);
+      mp_zero(pR);
+    }
+  } else {
+    MP_CHECKOK( mp_init_copy(&btmp, b) );
+    MP_CHECKOK( s_mp_div(pR, &btmp, pQ) );
+  }
+
+  /* Compute the signs for the output  */
+  MP_SIGN(pR) = signA;   /* Sr = Sa              */
+  /* Sq = ZPOS if Sa == Sb */ /* Sq = NEG if Sa != Sb */
+  MP_SIGN(pQ) = (signA == signB) ? ZPOS : NEG;
+
+  if(s_mp_cmp_d(pQ, 0) == MP_EQ)
+    SIGN(pQ) = ZPOS;
+  if(s_mp_cmp_d(pR, 0) == MP_EQ)
+    SIGN(pR) = ZPOS;
+
+  /* Copy output, if it is needed      */
+  if(q && q != pQ)
+    s_mp_exch(pQ, q);
+
+  if(r && r != pR)
+    s_mp_exch(pR, r);
+
+CLEANUP:
+  mp_clear(&btmp);
+  mp_clear(&rtmp);
+  mp_clear(&qtmp);
+
+  return res;
+
+} /* end mp_div() */
+
+/* }}} */
+
+/* {{{ mp_div_2d(a, d, q, r) */
+
+mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  if(q) {
+    if((res = mp_copy(a, q)) != MP_OKAY)
+      return res;
+  }
+  if(r) {
+    if((res = mp_copy(a, r)) != MP_OKAY)
+      return res;
+  }
+  if(q) {
+    s_mp_div_2d(q, d);
+  }
+  if(r) {
+    s_mp_mod_2d(r, d);
+  }
+
+  return MP_OKAY;
+
+} /* end mp_div_2d() */
+
+/* }}} */
+
+/* {{{ mp_expt(a, b, c) */
+
+/*
+  mp_expt(a, b, c)
+
+  Compute c = a ** b, that is, raise a to the b power.  Uses a
+  standard iterative square-and-multiply technique.
+ */
+
+mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_int   s, x;
+  mp_err   res;
+  mp_digit d;
+  int      dig, bit;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(mp_cmp_z(b) < 0)
+    return MP_RANGE;
+
+  if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
+    return res;
+
+  mp_set(&s, 1);
+
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  /* Loop over low-order digits in ascending order */
+  for(dig = 0; dig < (USED(b) - 1); dig++) {
+    d = DIGIT(b, dig);
+
+    /* Loop over bits of each non-maximal digit */
+    for(bit = 0; bit < DIGIT_BIT; bit++) {
+      if(d & 1) {
+        if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+          goto CLEANUP;
+      }
+
+      d >>= 1;
+
+      if((res = s_mp_sqr(&x)) != MP_OKAY)
+        goto CLEANUP;
+    }
+  }
+
+  /* Consider now the last digit... */
+  d = DIGIT(b, dig);
+
+  while(d) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+        goto CLEANUP;
+    }
+
+    d >>= 1;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  if(mp_iseven(b))
+    SIGN(&s) = SIGN(a);
+
+  res = mp_copy(&s, c);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_expt() */
+
+/* }}} */
+
+/* {{{ mp_2expt(a, k) */
+
+/* Compute a = 2^k */
+
+mp_err mp_2expt(mp_int *a, mp_digit k)
+{
+  ARGCHK(a != NULL, MP_BADARG);
+
+  return s_mp_2expt(a, k);
+
+} /* end mp_2expt() */
+
+/* }}} */
+
+/* {{{ mp_mod(a, m, c) */
+
+/*
+  mp_mod(a, m, c)
+
+  Compute c = a (mod m).  Result will always be 0 <= c < m.
+ */
+
+mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c)
+{
+  mp_err  res;
+  int     mag;
+
+  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if(SIGN(m) == NEG)
+    return MP_RANGE;
+
+  /*
+     If |a| > m, we need to divide to get the remainder and take the
+     absolute value.
+
+     If |a| < m, we don't need to do any division, just copy and adjust
+     the sign (if a is negative).
+
+     If |a| == m, we can simply set the result to zero.
+
+     This order is intended to minimize the average path length of the
+     comparison chain on common workloads -- the most frequent cases are
+     that |a| != m, so we do those first.
+   */
+  if((mag = s_mp_cmp(a, m)) > 0) {
+    if((res = mp_div(a, m, NULL, c)) != MP_OKAY)
+      return res;
+
+    if(SIGN(c) == NEG) {
+      if((res = mp_add(c, m, c)) != MP_OKAY)
+        return res;
+    }
+
+  } else if(mag < 0) {
+    if((res = mp_copy(a, c)) != MP_OKAY)
+      return res;
+
+    if(mp_cmp_z(a) < 0) {
+      if((res = mp_add(c, m, c)) != MP_OKAY)
+        return res;
+
+    }
+
+  } else {
+    mp_zero(c);
+
+  }
+
+  return MP_OKAY;
+
+} /* end mp_mod() */
+
+/* }}} */
+
+/* {{{ mp_mod_d(a, d, c) */
+
+/*
+  mp_mod_d(a, d, c)
+
+  Compute c = a (mod d).  Result will always be 0 <= c < d
+ */
+mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c)
+{
+  mp_err   res;
+  mp_digit rem;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if(s_mp_cmp_d(a, d) > 0) {
+    if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)
+      return res;
+
+  } else {
+    if(SIGN(a) == NEG)
+      rem = d - DIGIT(a, 0);
+    else
+      rem = DIGIT(a, 0);
+  }
+
+  if(c)
+    *c = rem;
+
+  return MP_OKAY;
+
+} /* end mp_mod_d() */
+
+/* }}} */
+
+/* {{{ mp_sqrt(a, b) */
+
+/*
+  mp_sqrt(a, b)
+
+  Compute the integer square root of a, and store the result in b.
+  Uses an integer-arithmetic version of Newton's iterative linear
+  approximation technique to determine this value; the result has the
+  following two properties:
+
+     b^2 <= a
+     (b+1)^2 >= a
+
+  It is a range error to pass a negative value.
+ */
+mp_err mp_sqrt(const mp_int *a, mp_int *b)
+{
+  mp_int   x, t;
+  mp_err   res;
+  mp_size  used;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  /* Cannot take square root of a negative value */
+  if(SIGN(a) == NEG)
+    return MP_RANGE;
+
+  /* Special cases for zero and one, trivial     */
+  if(mp_cmp_d(a, 1) <= 0)
+    return mp_copy(a, b);
+
+  /* Initialize the temporaries we'll use below  */
+  if((res = mp_init_size(&t, USED(a), FLAG(a))) != MP_OKAY)
+    return res;
+
+  /* Compute an initial guess for the iteration as a itself */
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  used = MP_USED(&x);
+  if (used > 1) {
+    s_mp_rshd(&x, used / 2);
+  }
+
+  for(;;) {
+    /* t = (x * x) - a */
+    mp_copy(&x, &t);      /* can't fail, t is big enough for original x */
+    if((res = mp_sqr(&t, &t)) != MP_OKAY ||
+       (res = mp_sub(&t, a, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+    /* t = t / 2x       */
+    s_mp_mul_2(&x);
+    if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)
+      goto CLEANUP;
+    s_mp_div_2(&x);
+
+    /* Terminate the loop, if the quotient is zero */
+    if(mp_cmp_z(&t) == MP_EQ)
+      break;
+
+    /* x = x - t       */
+    if((res = mp_sub(&x, &t, &x)) != MP_OKAY)
+      goto CLEANUP;
+
+  }
+
+  /* Copy result to output parameter */
+  mp_sub_d(&x, 1, &x);
+  s_mp_exch(&x, b);
+
+ CLEANUP:
+  mp_clear(&x);
+ X:
+  mp_clear(&t);
+
+  return res;
+
+} /* end mp_sqrt() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Modular arithmetic */
+
+#if MP_MODARITH
+/* {{{ mp_addmod(a, b, m, c) */
+
+/*
+  mp_addmod(a, b, m, c)
+
+  Compute c = (a + b) mod m
+ */
+
+mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_add(a, b, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_submod(a, b, m, c) */
+
+/*
+  mp_submod(a, b, m, c)
+
+  Compute c = (a - b) mod m
+ */
+
+mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_sub(a, b, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_mulmod(a, b, m, c) */
+
+/*
+  mp_mulmod(a, b, m, c)
+
+  Compute c = (a * b) mod m
+ */
+
+mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_mul(a, b, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+}
+
+/* }}} */
+
+/* {{{ mp_sqrmod(a, m, c) */
+
+#if MP_SQUARE
+mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c)
+{
+  mp_err  res;
+
+  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_sqr(a, c)) != MP_OKAY)
+    return res;
+  if((res = mp_mod(c, m, c)) != MP_OKAY)
+    return res;
+
+  return MP_OKAY;
+
+} /* end mp_sqrmod() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_exptmod(a, b, m, c) */
+
+/*
+  s_mp_exptmod(a, b, m, c)
+
+  Compute c = (a ** b) mod m.  Uses a standard square-and-multiply
+  method with modular reductions at each step. (This is basically the
+  same code as mp_expt(), except for the addition of the reductions)
+
+  The modular reductions are done using Barrett's algorithm (see
+  s_mp_reduce() below for details)
+ */
+
+mp_err s_mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c)
+{
+  mp_int   s, x, mu;
+  mp_err   res;
+  mp_digit d;
+  int      dig, bit;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)
+    return MP_RANGE;
+
+  if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&x, a)) != MP_OKAY ||
+     (res = mp_mod(&x, m, &x)) != MP_OKAY)
+    goto X;
+  if((res = mp_init(&mu, FLAG(a))) != MP_OKAY)
+    goto MU;
+
+  mp_set(&s, 1);
+
+  /* mu = b^2k / m */
+  s_mp_add_d(&mu, 1);
+  s_mp_lshd(&mu, 2 * USED(m));
+  if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)
+    goto CLEANUP;
+
+  /* Loop over digits of b in ascending order, except highest order */
+  for(dig = 0; dig < (USED(b) - 1); dig++) {
+    d = DIGIT(b, dig);
+
+    /* Loop over the bits of the lower-order digits */
+    for(bit = 0; bit < DIGIT_BIT; bit++) {
+      if(d & 1) {
+        if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+          goto CLEANUP;
+        if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
+          goto CLEANUP;
+      }
+
+      d >>= 1;
+
+      if((res = s_mp_sqr(&x)) != MP_OKAY)
+        goto CLEANUP;
+      if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
+        goto CLEANUP;
+    }
+  }
+
+  /* Now do the last digit... */
+  d = DIGIT(b, dig);
+
+  while(d) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY)
+        goto CLEANUP;
+      if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)
+        goto CLEANUP;
+    }
+
+    d >>= 1;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY)
+      goto CLEANUP;
+    if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  s_mp_exch(&s, c);
+
+ CLEANUP:
+  mp_clear(&mu);
+ MU:
+  mp_clear(&x);
+ X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end s_mp_exptmod() */
+
+/* }}} */
+
+/* {{{ mp_exptmod_d(a, d, m, c) */
+
+mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c)
+{
+  mp_int   s, x;
+  mp_err   res;
+
+  ARGCHK(a != NULL && c != NULL, MP_BADARG);
+
+  if((res = mp_init(&s, FLAG(a))) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&x, a)) != MP_OKAY)
+    goto X;
+
+  mp_set(&s, 1);
+
+  while(d != 0) {
+    if(d & 1) {
+      if((res = s_mp_mul(&s, &x)) != MP_OKAY ||
+         (res = mp_mod(&s, m, &s)) != MP_OKAY)
+        goto CLEANUP;
+    }
+
+    d /= 2;
+
+    if((res = s_mp_sqr(&x)) != MP_OKAY ||
+       (res = mp_mod(&x, m, &x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  s_mp_exch(&s, c);
+
+CLEANUP:
+  mp_clear(&x);
+X:
+  mp_clear(&s);
+
+  return res;
+
+} /* end mp_exptmod_d() */
+
+/* }}} */
+#endif /* if MP_MODARITH */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Comparison functions */
+
+/* {{{ mp_cmp_z(a) */
+
+/*
+  mp_cmp_z(a)
+
+  Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0.
+ */
+
+int    mp_cmp_z(const mp_int *a)
+{
+  if(SIGN(a) == NEG)
+    return MP_LT;
+  else if(USED(a) == 1 && DIGIT(a, 0) == 0)
+    return MP_EQ;
+  else
+    return MP_GT;
+
+} /* end mp_cmp_z() */
+
+/* }}} */
+
+/* {{{ mp_cmp_d(a, d) */
+
+/*
+  mp_cmp_d(a, d)
+
+  Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d
+ */
+
+int    mp_cmp_d(const mp_int *a, mp_digit d)
+{
+  ARGCHK(a != NULL, MP_EQ);
+
+  if(SIGN(a) == NEG)
+    return MP_LT;
+
+  return s_mp_cmp_d(a, d);
+
+} /* end mp_cmp_d() */
+
+/* }}} */
+
+/* {{{ mp_cmp(a, b) */
+
+int    mp_cmp(const mp_int *a, const mp_int *b)
+{
+  ARGCHK(a != NULL && b != NULL, MP_EQ);
+
+  if(SIGN(a) == SIGN(b)) {
+    int  mag;
+
+    if((mag = s_mp_cmp(a, b)) == MP_EQ)
+      return MP_EQ;
+
+    if(SIGN(a) == ZPOS)
+      return mag;
+    else
+      return -mag;
+
+  } else if(SIGN(a) == ZPOS) {
+    return MP_GT;
+  } else {
+    return MP_LT;
+  }
+
+} /* end mp_cmp() */
+
+/* }}} */
+
+/* {{{ mp_cmp_mag(a, b) */
+
+/*
+  mp_cmp_mag(a, b)
+
+  Compares |a| <=> |b|, and returns an appropriate comparison result
+ */
+
+int    mp_cmp_mag(mp_int *a, mp_int *b)
+{
+  ARGCHK(a != NULL && b != NULL, MP_EQ);
+
+  return s_mp_cmp(a, b);
+
+} /* end mp_cmp_mag() */
+
+/* }}} */
+
+/* {{{ mp_cmp_int(a, z, kmflag) */
+
+/*
+  This just converts z to an mp_int, and uses the existing comparison
+  routines.  This is sort of inefficient, but it's not clear to me how
+  frequently this wil get used anyway.  For small positive constants,
+  you can always use mp_cmp_d(), and for zero, there is mp_cmp_z().
+ */
+int    mp_cmp_int(const mp_int *a, long z, int kmflag)
+{
+  mp_int  tmp;
+  int     out;
+
+  ARGCHK(a != NULL, MP_EQ);
+
+  mp_init(&tmp, kmflag); mp_set_int(&tmp, z);
+  out = mp_cmp(a, &tmp);
+  mp_clear(&tmp);
+
+  return out;
+
+} /* end mp_cmp_int() */
+
+/* }}} */
+
+/* {{{ mp_isodd(a) */
+
+/*
+  mp_isodd(a)
+
+  Returns a true (non-zero) value if a is odd, false (zero) otherwise.
+ */
+int    mp_isodd(const mp_int *a)
+{
+  ARGCHK(a != NULL, 0);
+
+  return (int)(DIGIT(a, 0) & 1);
+
+} /* end mp_isodd() */
+
+/* }}} */
+
+/* {{{ mp_iseven(a) */
+
+int    mp_iseven(const mp_int *a)
+{
+  return !mp_isodd(a);
+
+} /* end mp_iseven() */
+
+/* }}} */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ Number theoretic functions */
+
+#if MP_NUMTH
+/* {{{ mp_gcd(a, b, c) */
+
+/*
+  Like the old mp_gcd() function, except computes the GCD using the
+  binary algorithm due to Josef Stein in 1961 (via Knuth).
+ */
+mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_err   res;
+  mp_int   u, v, t;
+  mp_size  k = 0;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)
+      return MP_RANGE;
+  if(mp_cmp_z(a) == MP_EQ) {
+    return mp_copy(b, c);
+  } else if(mp_cmp_z(b) == MP_EQ) {
+    return mp_copy(a, c);
+  }
+
+  if((res = mp_init(&t, FLAG(a))) != MP_OKAY)
+    return res;
+  if((res = mp_init_copy(&u, a)) != MP_OKAY)
+    goto U;
+  if((res = mp_init_copy(&v, b)) != MP_OKAY)
+    goto V;
+
+  SIGN(&u) = ZPOS;
+  SIGN(&v) = ZPOS;
+
+  /* Divide out common factors of 2 until at least 1 of a, b is even */
+  while(mp_iseven(&u) && mp_iseven(&v)) {
+    s_mp_div_2(&u);
+    s_mp_div_2(&v);
+    ++k;
+  }
+
+  /* Initialize t */
+  if(mp_isodd(&u)) {
+    if((res = mp_copy(&v, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+    /* t = -v */
+    if(SIGN(&v) == ZPOS)
+      SIGN(&t) = NEG;
+    else
+      SIGN(&t) = ZPOS;
+
+  } else {
+    if((res = mp_copy(&u, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+  }
+
+  for(;;) {
+    while(mp_iseven(&t)) {
+      s_mp_div_2(&t);
+    }
+
+    if(mp_cmp_z(&t) == MP_GT) {
+      if((res = mp_copy(&t, &u)) != MP_OKAY)
+        goto CLEANUP;
+
+    } else {
+      if((res = mp_copy(&t, &v)) != MP_OKAY)
+        goto CLEANUP;
+
+      /* v = -t */
+      if(SIGN(&t) == ZPOS)
+        SIGN(&v) = NEG;
+      else
+        SIGN(&v) = ZPOS;
+    }
+
+    if((res = mp_sub(&u, &v, &t)) != MP_OKAY)
+      goto CLEANUP;
+
+    if(s_mp_cmp_d(&t, 0) == MP_EQ)
+      break;
+  }
+
+  s_mp_2expt(&v, k);       /* v = 2^k   */
+  res = mp_mul(&u, &v, c); /* c = u * v */
+
+ CLEANUP:
+  mp_clear(&v);
+ V:
+  mp_clear(&u);
+ U:
+  mp_clear(&t);
+
+  return res;
+
+} /* end mp_gcd() */
+
+/* }}} */
+
+/* {{{ mp_lcm(a, b, c) */
+
+/* We compute the least common multiple using the rule:
+
+   ab = [a, b](a, b)
+
+   ... by computing the product, and dividing out the gcd.
+ */
+
+mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c)
+{
+  mp_int  gcd, prod;
+  mp_err  res;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  /* Set up temporaries */
+  if((res = mp_init(&gcd, FLAG(a))) != MP_OKAY)
+    return res;
+  if((res = mp_init(&prod, FLAG(a))) != MP_OKAY)
+    goto GCD;
+
+  if((res = mp_mul(a, b, &prod)) != MP_OKAY)
+    goto CLEANUP;
+  if((res = mp_gcd(a, b, &gcd)) != MP_OKAY)
+    goto CLEANUP;
+
+  res = mp_div(&prod, &gcd, c, NULL);
+
+ CLEANUP:
+  mp_clear(&prod);
+ GCD:
+  mp_clear(&gcd);
+
+  return res;
+
+} /* end mp_lcm() */
+
+/* }}} */
+
+/* {{{ mp_xgcd(a, b, g, x, y) */
+
+/*
+  mp_xgcd(a, b, g, x, y)
+
+  Compute g = (a, b) and values x and y satisfying Bezout's identity
+  (that is, ax + by = g).  This uses the binary extended GCD algorithm
+  based on the Stein algorithm used for mp_gcd()
+  See algorithm 14.61 in Handbook of Applied Cryptogrpahy.
+ */
+
+mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y)
+{
+  mp_int   gx, xc, yc, u, v, A, B, C, D;
+  mp_int  *clean[9];
+  mp_err   res;
+  int      last = -1;
+
+  if(mp_cmp_z(b) == 0)
+    return MP_RANGE;
+
+  /* Initialize all these variables we need */
+  MP_CHECKOK( mp_init(&u, FLAG(a)) );
+  clean[++last] = &u;
+  MP_CHECKOK( mp_init(&v, FLAG(a)) );
+  clean[++last] = &v;
+  MP_CHECKOK( mp_init(&gx, FLAG(a)) );
+  clean[++last] = &gx;
+  MP_CHECKOK( mp_init(&A, FLAG(a)) );
+  clean[++last] = &A;
+  MP_CHECKOK( mp_init(&B, FLAG(a)) );
+  clean[++last] = &B;
+  MP_CHECKOK( mp_init(&C, FLAG(a)) );
+  clean[++last] = &C;
+  MP_CHECKOK( mp_init(&D, FLAG(a)) );
+  clean[++last] = &D;
+  MP_CHECKOK( mp_init_copy(&xc, a) );
+  clean[++last] = &xc;
+  mp_abs(&xc, &xc);
+  MP_CHECKOK( mp_init_copy(&yc, b) );
+  clean[++last] = &yc;
+  mp_abs(&yc, &yc);
+
+  mp_set(&gx, 1);
+
+  /* Divide by two until at least one of them is odd */
+  while(mp_iseven(&xc) && mp_iseven(&yc)) {
+    mp_size nx = mp_trailing_zeros(&xc);
+    mp_size ny = mp_trailing_zeros(&yc);
+    mp_size n  = MP_MIN(nx, ny);
+    s_mp_div_2d(&xc,n);
+    s_mp_div_2d(&yc,n);
+    MP_CHECKOK( s_mp_mul_2d(&gx,n) );
+  }
+
+  mp_copy(&xc, &u);
+  mp_copy(&yc, &v);
+  mp_set(&A, 1); mp_set(&D, 1);
+
+  /* Loop through binary GCD algorithm */
+  do {
+    while(mp_iseven(&u)) {
+      s_mp_div_2(&u);
+
+      if(mp_iseven(&A) && mp_iseven(&B)) {
+        s_mp_div_2(&A); s_mp_div_2(&B);
+      } else {
+        MP_CHECKOK( mp_add(&A, &yc, &A) );
+        s_mp_div_2(&A);
+        MP_CHECKOK( mp_sub(&B, &xc, &B) );
+        s_mp_div_2(&B);
+      }
+    }
+
+    while(mp_iseven(&v)) {
+      s_mp_div_2(&v);
+
+      if(mp_iseven(&C) && mp_iseven(&D)) {
+        s_mp_div_2(&C); s_mp_div_2(&D);
+      } else {
+        MP_CHECKOK( mp_add(&C, &yc, &C) );
+        s_mp_div_2(&C);
+        MP_CHECKOK( mp_sub(&D, &xc, &D) );
+        s_mp_div_2(&D);
+      }
+    }
+
+    if(mp_cmp(&u, &v) >= 0) {
+      MP_CHECKOK( mp_sub(&u, &v, &u) );
+      MP_CHECKOK( mp_sub(&A, &C, &A) );
+      MP_CHECKOK( mp_sub(&B, &D, &B) );
+    } else {
+      MP_CHECKOK( mp_sub(&v, &u, &v) );
+      MP_CHECKOK( mp_sub(&C, &A, &C) );
+      MP_CHECKOK( mp_sub(&D, &B, &D) );
+    }
+  } while (mp_cmp_z(&u) != 0);
+
+  /* copy results to output */
+  if(x)
+    MP_CHECKOK( mp_copy(&C, x) );
+
+  if(y)
+    MP_CHECKOK( mp_copy(&D, y) );
+
+  if(g)
+    MP_CHECKOK( mp_mul(&gx, &v, g) );
+
+ CLEANUP:
+  while(last >= 0)
+    mp_clear(clean[last--]);
+
+  return res;
+
+} /* end mp_xgcd() */
+
+/* }}} */
+
+mp_size mp_trailing_zeros(const mp_int *mp)
+{
+  mp_digit d;
+  mp_size  n = 0;
+  int      ix;
+
+  if (!mp || !MP_DIGITS(mp) || !mp_cmp_z(mp))
+    return n;
+
+  for (ix = 0; !(d = MP_DIGIT(mp,ix)) && (ix < MP_USED(mp)); ++ix)
+    n += MP_DIGIT_BIT;
+  if (!d)
+    return 0;   /* shouldn't happen, but ... */
+#if !defined(MP_USE_UINT_DIGIT)
+  if (!(d & 0xffffffffU)) {
+    d >>= 32;
+    n  += 32;
+  }
+#endif
+  if (!(d & 0xffffU)) {
+    d >>= 16;
+    n  += 16;
+  }
+  if (!(d & 0xffU)) {
+    d >>= 8;
+    n  += 8;
+  }
+  if (!(d & 0xfU)) {
+    d >>= 4;
+    n  += 4;
+  }
+  if (!(d & 0x3U)) {
+    d >>= 2;
+    n  += 2;
+  }
+  if (!(d & 0x1U)) {
+    d >>= 1;
+    n  += 1;
+  }
+#if MP_ARGCHK == 2
+  assert(0 != (d & 1));
+#endif
+  return n;
+}
+
+/* Given a and prime p, computes c and k such that a*c == 2**k (mod p).
+** Returns k (positive) or error (negative).
+** This technique from the paper "Fast Modular Reciprocals" (unpublished)
+** by Richard Schroeppel (a.k.a. Captain Nemo).
+*/
+mp_err s_mp_almost_inverse(const mp_int *a, const mp_int *p, mp_int *c)
+{
+  mp_err res;
+  mp_err k    = 0;
+  mp_int d, f, g;
+
+  ARGCHK(a && p && c, MP_BADARG);
+
+  MP_DIGITS(&d) = 0;
+  MP_DIGITS(&f) = 0;
+  MP_DIGITS(&g) = 0;
+  MP_CHECKOK( mp_init(&d, FLAG(a)) );
+  MP_CHECKOK( mp_init_copy(&f, a) );    /* f = a */
+  MP_CHECKOK( mp_init_copy(&g, p) );    /* g = p */
+
+  mp_set(c, 1);
+  mp_zero(&d);
+
+  if (mp_cmp_z(&f) == 0) {
+    res = MP_UNDEF;
+  } else
+  for (;;) {
+    int diff_sign;
+    while (mp_iseven(&f)) {
+      mp_size n = mp_trailing_zeros(&f);
+      if (!n) {
+        res = MP_UNDEF;
+        goto CLEANUP;
+      }
+      s_mp_div_2d(&f, n);
+      MP_CHECKOK( s_mp_mul_2d(&d, n) );
+      k += n;
+    }
+    if (mp_cmp_d(&f, 1) == MP_EQ) {     /* f == 1 */
+      res = k;
+      break;
+    }
+    diff_sign = mp_cmp(&f, &g);
+    if (diff_sign < 0) {                /* f < g */
+      s_mp_exch(&f, &g);
+      s_mp_exch(c, &d);
+    } else if (diff_sign == 0) {                /* f == g */
+      res = MP_UNDEF;           /* a and p are not relatively prime */
+      break;
+    }
+    if ((MP_DIGIT(&f,0) % 4) == (MP_DIGIT(&g,0) % 4)) {
+      MP_CHECKOK( mp_sub(&f, &g, &f) ); /* f = f - g */
+      MP_CHECKOK( mp_sub(c,  &d,  c) ); /* c = c - d */
+    } else {
+      MP_CHECKOK( mp_add(&f, &g, &f) ); /* f = f + g */
+      MP_CHECKOK( mp_add(c,  &d,  c) ); /* c = c + d */
+    }
+  }
+  if (res >= 0) {
+    while (MP_SIGN(c) != MP_ZPOS) {
+      MP_CHECKOK( mp_add(c, p, c) );
+    }
+    res = k;
+  }
+
+CLEANUP:
+  mp_clear(&d);
+  mp_clear(&f);
+  mp_clear(&g);
+  return res;
+}
+
+/* Compute T = (P ** -1) mod MP_RADIX.  Also works for 16-bit mp_digits.
+** This technique from the paper "Fast Modular Reciprocals" (unpublished)
+** by Richard Schroeppel (a.k.a. Captain Nemo).
+*/
+mp_digit  s_mp_invmod_radix(mp_digit P)
+{
+  mp_digit T = P;
+  T *= 2 - (P * T);
+  T *= 2 - (P * T);
+  T *= 2 - (P * T);
+  T *= 2 - (P * T);
+#if !defined(MP_USE_UINT_DIGIT)
+  T *= 2 - (P * T);
+  T *= 2 - (P * T);
+#endif
+  return T;
+}
+
+/* Given c, k, and prime p, where a*c == 2**k (mod p),
+** Compute x = (a ** -1) mod p.  This is similar to Montgomery reduction.
+** This technique from the paper "Fast Modular Reciprocals" (unpublished)
+** by Richard Schroeppel (a.k.a. Captain Nemo).
+*/
+mp_err  s_mp_fixup_reciprocal(const mp_int *c, const mp_int *p, int k, mp_int *x)
+{
+  int      k_orig = k;
+  mp_digit r;
+  mp_size  ix;
+  mp_err   res;
+
+  if (mp_cmp_z(c) < 0) {                /* c < 0 */
+    MP_CHECKOK( mp_add(c, p, x) );      /* x = c + p */
+  } else {
+    MP_CHECKOK( mp_copy(c, x) );        /* x = c */
+  }
+
+  /* make sure x is large enough */
+  ix = MP_HOWMANY(k, MP_DIGIT_BIT) + MP_USED(p) + 1;
+  ix = MP_MAX(ix, MP_USED(x));
+  MP_CHECKOK( s_mp_pad(x, ix) );
+
+  r = 0 - s_mp_invmod_radix(MP_DIGIT(p,0));
+
+  for (ix = 0; k > 0; ix++) {
+    int      j = MP_MIN(k, MP_DIGIT_BIT);
+    mp_digit v = r * MP_DIGIT(x, ix);
+    if (j < MP_DIGIT_BIT) {
+      v &= ((mp_digit)1 << j) - 1;      /* v = v mod (2 ** j) */
+    }
+    s_mp_mul_d_add_offset(p, v, x, ix); /* x += p * v * (RADIX ** ix) */
+    k -= j;
+  }
+  s_mp_clamp(x);
+  s_mp_div_2d(x, k_orig);
+  res = MP_OKAY;
+
+CLEANUP:
+  return res;
+}
+
+/* compute mod inverse using Schroeppel's method, only if m is odd */
+mp_err s_mp_invmod_odd_m(const mp_int *a, const mp_int *m, mp_int *c)
+{
+  int k;
+  mp_err  res;
+  mp_int  x;
+
+  ARGCHK(a && m && c, MP_BADARG);
+
+  if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
+    return MP_RANGE;
+  if (mp_iseven(m))
+    return MP_UNDEF;
+
+  MP_DIGITS(&x) = 0;
+
+  if (a == c) {
+    if ((res = mp_init_copy(&x, a)) != MP_OKAY)
+      return res;
+    if (a == m)
+      m = &x;
+    a = &x;
+  } else if (m == c) {
+    if ((res = mp_init_copy(&x, m)) != MP_OKAY)
+      return res;
+    m = &x;
+  } else {
+    MP_DIGITS(&x) = 0;
+  }
+
+  MP_CHECKOK( s_mp_almost_inverse(a, m, c) );
+  k = res;
+  MP_CHECKOK( s_mp_fixup_reciprocal(c, m, k, c) );
+CLEANUP:
+  mp_clear(&x);
+  return res;
+}
+
+/* Known good algorithm for computing modular inverse.  But slow. */
+mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c)
+{
+  mp_int  g, x;
+  mp_err  res;
+
+  ARGCHK(a && m && c, MP_BADARG);
+
+  if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
+    return MP_RANGE;
+
+  MP_DIGITS(&g) = 0;
+  MP_DIGITS(&x) = 0;
+  MP_CHECKOK( mp_init(&x, FLAG(a)) );
+  MP_CHECKOK( mp_init(&g, FLAG(a)) );
+
+  MP_CHECKOK( mp_xgcd(a, m, &g, &x, NULL) );
+
+  if (mp_cmp_d(&g, 1) != MP_EQ) {
+    res = MP_UNDEF;
+    goto CLEANUP;
+  }
+
+  res = mp_mod(&x, m, c);
+  SIGN(c) = SIGN(a);
+
+CLEANUP:
+  mp_clear(&x);
+  mp_clear(&g);
+
+  return res;
+}
+
+/* modular inverse where modulus is 2**k. */
+/* c = a**-1 mod 2**k */
+mp_err s_mp_invmod_2d(const mp_int *a, mp_size k, mp_int *c)
+{
+  mp_err res;
+  mp_size ix = k + 4;
+  mp_int t0, t1, val, tmp, two2k;
+
+  static const mp_digit d2 = 2;
+  static const mp_int two = { 0, MP_ZPOS, 1, 1, (mp_digit *)&d2 };
+
+  if (mp_iseven(a))
+    return MP_UNDEF;
+  if (k <= MP_DIGIT_BIT) {
+    mp_digit i = s_mp_invmod_radix(MP_DIGIT(a,0));
+    if (k < MP_DIGIT_BIT)
+      i &= ((mp_digit)1 << k) - (mp_digit)1;
+    mp_set(c, i);
+    return MP_OKAY;
+  }
+  MP_DIGITS(&t0) = 0;
+  MP_DIGITS(&t1) = 0;
+  MP_DIGITS(&val) = 0;
+  MP_DIGITS(&tmp) = 0;
+  MP_DIGITS(&two2k) = 0;
+  MP_CHECKOK( mp_init_copy(&val, a) );
+  s_mp_mod_2d(&val, k);
+  MP_CHECKOK( mp_init_copy(&t0, &val) );
+  MP_CHECKOK( mp_init_copy(&t1, &t0)  );
+  MP_CHECKOK( mp_init(&tmp, FLAG(a)) );
+  MP_CHECKOK( mp_init(&two2k, FLAG(a)) );
+  MP_CHECKOK( s_mp_2expt(&two2k, k) );
+  do {
+    MP_CHECKOK( mp_mul(&val, &t1, &tmp)  );
+    MP_CHECKOK( mp_sub(&two, &tmp, &tmp) );
+    MP_CHECKOK( mp_mul(&t1, &tmp, &t1)   );
+    s_mp_mod_2d(&t1, k);
+    while (MP_SIGN(&t1) != MP_ZPOS) {
+      MP_CHECKOK( mp_add(&t1, &two2k, &t1) );
+    }
+    if (mp_cmp(&t1, &t0) == MP_EQ)
+      break;
+    MP_CHECKOK( mp_copy(&t1, &t0) );
+  } while (--ix > 0);
+  if (!ix) {
+    res = MP_UNDEF;
+  } else {
+    mp_exch(c, &t1);
+  }
+
+CLEANUP:
+  mp_clear(&t0);
+  mp_clear(&t1);
+  mp_clear(&val);
+  mp_clear(&tmp);
+  mp_clear(&two2k);
+  return res;
+}
+
+mp_err s_mp_invmod_even_m(const mp_int *a, const mp_int *m, mp_int *c)
+{
+  mp_err res;
+  mp_size k;
+  mp_int oddFactor, evenFactor; /* factors of the modulus */
+  mp_int oddPart, evenPart;     /* parts to combine via CRT. */
+  mp_int C2, tmp1, tmp2;
+
+  /*static const mp_digit d1 = 1; */
+  /*static const mp_int one = { MP_ZPOS, 1, 1, (mp_digit *)&d1 }; */
+
+  if ((res = s_mp_ispow2(m)) >= 0) {
+    k = res;
+    return s_mp_invmod_2d(a, k, c);
+  }
+  MP_DIGITS(&oddFactor) = 0;
+  MP_DIGITS(&evenFactor) = 0;
+  MP_DIGITS(&oddPart) = 0;
+  MP_DIGITS(&evenPart) = 0;
+  MP_DIGITS(&C2)     = 0;
+  MP_DIGITS(&tmp1)   = 0;
+  MP_DIGITS(&tmp2)   = 0;
+
+  MP_CHECKOK( mp_init_copy(&oddFactor, m) );    /* oddFactor = m */
+  MP_CHECKOK( mp_init(&evenFactor, FLAG(m)) );
+  MP_CHECKOK( mp_init(&oddPart, FLAG(m)) );
+  MP_CHECKOK( mp_init(&evenPart, FLAG(m)) );
+  MP_CHECKOK( mp_init(&C2, FLAG(m))     );
+  MP_CHECKOK( mp_init(&tmp1, FLAG(m))   );
+  MP_CHECKOK( mp_init(&tmp2, FLAG(m))   );
+
+  k = mp_trailing_zeros(m);
+  s_mp_div_2d(&oddFactor, k);
+  MP_CHECKOK( s_mp_2expt(&evenFactor, k) );
+
+  /* compute a**-1 mod oddFactor. */
+  MP_CHECKOK( s_mp_invmod_odd_m(a, &oddFactor, &oddPart) );
+  /* compute a**-1 mod evenFactor, where evenFactor == 2**k. */
+  MP_CHECKOK( s_mp_invmod_2d(   a,       k,    &evenPart) );
+
+  /* Use Chinese Remainer theorem to compute a**-1 mod m. */
+  /* let m1 = oddFactor,  v1 = oddPart,
+   * let m2 = evenFactor, v2 = evenPart.
+   */
+
+  /* Compute C2 = m1**-1 mod m2. */
+  MP_CHECKOK( s_mp_invmod_2d(&oddFactor, k,    &C2) );
+
+  /* compute u = (v2 - v1)*C2 mod m2 */
+  MP_CHECKOK( mp_sub(&evenPart, &oddPart,   &tmp1) );
+  MP_CHECKOK( mp_mul(&tmp1,     &C2,        &tmp2) );
+  s_mp_mod_2d(&tmp2, k);
+  while (MP_SIGN(&tmp2) != MP_ZPOS) {
+    MP_CHECKOK( mp_add(&tmp2, &evenFactor, &tmp2) );
+  }
+
+  /* compute answer = v1 + u*m1 */
+  MP_CHECKOK( mp_mul(&tmp2,     &oddFactor, c) );
+  MP_CHECKOK( mp_add(&oddPart,  c,          c) );
+  /* not sure this is necessary, but it's low cost if not. */
+  MP_CHECKOK( mp_mod(c,         m,          c) );
+
+CLEANUP:
+  mp_clear(&oddFactor);
+  mp_clear(&evenFactor);
+  mp_clear(&oddPart);
+  mp_clear(&evenPart);
+  mp_clear(&C2);
+  mp_clear(&tmp1);
+  mp_clear(&tmp2);
+  return res;
+}
+
+
+/* {{{ mp_invmod(a, m, c) */
+
+/*
+  mp_invmod(a, m, c)
+
+  Compute c = a^-1 (mod m), if there is an inverse for a (mod m).
+  This is equivalent to the question of whether (a, m) = 1.  If not,
+  MP_UNDEF is returned, and there is no inverse.
+ */
+
+mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
+{
+
+  ARGCHK(a && m && c, MP_BADARG);
+
+  if(mp_cmp_z(a) == 0 || mp_cmp_z(m) == 0)
+    return MP_RANGE;
+
+  if (mp_isodd(m)) {
+    return s_mp_invmod_odd_m(a, m, c);
+  }
+  if (mp_iseven(a))
+    return MP_UNDEF;    /* not invertable */
+
+  return s_mp_invmod_even_m(a, m, c);
+
+} /* end mp_invmod() */
+
+/* }}} */
+#endif /* if MP_NUMTH */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ mp_print(mp, ofp) */
+
+#if MP_IOFUNC
+/*
+  mp_print(mp, ofp)
+
+  Print a textual representation of the given mp_int on the output
+  stream 'ofp'.  Output is generated using the internal radix.
+ */
+
+void   mp_print(mp_int *mp, FILE *ofp)
+{
+  int   ix;
+
+  if(mp == NULL || ofp == NULL)
+    return;
+
+  fputc((SIGN(mp) == NEG) ? '-' : '+', ofp);
+
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    fprintf(ofp, DIGIT_FMT, DIGIT(mp, ix));
+  }
+
+} /* end mp_print() */
+
+#endif /* if MP_IOFUNC */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/* {{{ More I/O Functions */
+
+/* {{{ mp_read_raw(mp, str, len) */
+
+/*
+   mp_read_raw(mp, str, len)
+
+   Read in a raw value (base 256) into the given mp_int
+ */
+
+mp_err  mp_read_raw(mp_int *mp, char *str, int len)
+{
+  int            ix;
+  mp_err         res;
+  unsigned char *ustr = (unsigned char *)str;
+
+  ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
+
+  mp_zero(mp);
+
+  /* Get sign from first byte */
+  if(ustr[0])
+    SIGN(mp) = NEG;
+  else
+    SIGN(mp) = ZPOS;
+
+  /* Read the rest of the digits */
+  for(ix = 1; ix < len; ix++) {
+    if((res = mp_mul_d(mp, 256, mp)) != MP_OKAY)
+      return res;
+    if((res = mp_add_d(mp, ustr[ix], mp)) != MP_OKAY)
+      return res;
+  }
+
+  return MP_OKAY;
+
+} /* end mp_read_raw() */
+
+/* }}} */
+
+/* {{{ mp_raw_size(mp) */
+
+int    mp_raw_size(mp_int *mp)
+{
+  ARGCHK(mp != NULL, 0);
+
+  return (USED(mp) * sizeof(mp_digit)) + 1;
+
+} /* end mp_raw_size() */
+
+/* }}} */
+
+/* {{{ mp_toraw(mp, str) */
+
+mp_err mp_toraw(mp_int *mp, char *str)
+{
+  int  ix, jx, pos = 1;
+
+  ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+
+  str[0] = (char)SIGN(mp);
+
+  /* Iterate over each digit... */
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    mp_digit  d = DIGIT(mp, ix);
+
+    /* Unpack digit bytes, high order first */
+    for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
+      str[pos++] = (char)(d >> (jx * CHAR_BIT));
+    }
+  }
+
+  return MP_OKAY;
+
+} /* end mp_toraw() */
+
+/* }}} */
+
+/* {{{ mp_read_radix(mp, str, radix) */
+
+/*
+  mp_read_radix(mp, str, radix)
+
+  Read an integer from the given string, and set mp to the resulting
+  value.  The input is presumed to be in base 10.  Leading non-digit
+  characters are ignored, and the function reads until a non-digit
+  character or the end of the string.
+ */
+
+mp_err  mp_read_radix(mp_int *mp, const char *str, int radix)
+{
+  int     ix = 0, val = 0;
+  mp_err  res;
+  mp_sign sig = ZPOS;
+
+  ARGCHK(mp != NULL && str != NULL && radix >= 2 && radix <= MAX_RADIX,
+         MP_BADARG);
+
+  mp_zero(mp);
+
+  /* Skip leading non-digit characters until a digit or '-' or '+' */
+  while(str[ix] &&
+        (s_mp_tovalue(str[ix], radix) < 0) &&
+        str[ix] != '-' &&
+        str[ix] != '+') {
+    ++ix;
+  }
+
+  if(str[ix] == '-') {
+    sig = NEG;
+    ++ix;
+  } else if(str[ix] == '+') {
+    sig = ZPOS; /* this is the default anyway... */
+    ++ix;
+  }
+
+  while((val = s_mp_tovalue(str[ix], radix)) >= 0) {
+    if((res = s_mp_mul_d(mp, radix)) != MP_OKAY)
+      return res;
+    if((res = s_mp_add_d(mp, val)) != MP_OKAY)
+      return res;
+    ++ix;
+  }
+
+  if(s_mp_cmp_d(mp, 0) == MP_EQ)
+    SIGN(mp) = ZPOS;
+  else
+    SIGN(mp) = sig;
+
+  return MP_OKAY;
+
+} /* end mp_read_radix() */
+
+mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix)
+{
+  int     radix = default_radix;
+  int     cx;
+  mp_sign sig   = ZPOS;
+  mp_err  res;
+
+  /* Skip leading non-digit characters until a digit or '-' or '+' */
+  while ((cx = *str) != 0 &&
+        (s_mp_tovalue(cx, radix) < 0) &&
+        cx != '-' &&
+        cx != '+') {
+    ++str;
+  }
+
+  if (cx == '-') {
+    sig = NEG;
+    ++str;
+  } else if (cx == '+') {
+    sig = ZPOS; /* this is the default anyway... */
+    ++str;
+  }
+
+  if (str[0] == '0') {
+    if ((str[1] | 0x20) == 'x') {
+      radix = 16;
+      str += 2;
+    } else {
+      radix = 8;
+      str++;
+    }
+  }
+  res = mp_read_radix(a, str, radix);
+  if (res == MP_OKAY) {
+    MP_SIGN(a) = (s_mp_cmp_d(a, 0) == MP_EQ) ? ZPOS : sig;
+  }
+  return res;
+}
+
+/* }}} */
+
+/* {{{ mp_radix_size(mp, radix) */
+
+int    mp_radix_size(mp_int *mp, int radix)
+{
+  int  bits;
+
+  if(!mp || radix < 2 || radix > MAX_RADIX)
+    return 0;
+
+  bits = USED(mp) * DIGIT_BIT - 1;
+
+  return s_mp_outlen(bits, radix);
+
+} /* end mp_radix_size() */
+
+/* }}} */
+
+/* {{{ mp_toradix(mp, str, radix) */
+
+mp_err mp_toradix(mp_int *mp, char *str, int radix)
+{
+  int  ix, pos = 0;
+
+  ARGCHK(mp != NULL && str != NULL, MP_BADARG);
+  ARGCHK(radix > 1 && radix <= MAX_RADIX, MP_RANGE);
+
+  if(mp_cmp_z(mp) == MP_EQ) {
+    str[0] = '0';
+    str[1] = '\0';
+  } else {
+    mp_err   res;
+    mp_int   tmp;
+    mp_sign  sgn;
+    mp_digit rem, rdx = (mp_digit)radix;
+    char     ch;
+
+    if((res = mp_init_copy(&tmp, mp)) != MP_OKAY)
+      return res;
+
+    /* Save sign for later, and take absolute value */
+    sgn = SIGN(&tmp); SIGN(&tmp) = ZPOS;
+
+    /* Generate output digits in reverse order      */
+    while(mp_cmp_z(&tmp) != 0) {
+      if((res = mp_div_d(&tmp, rdx, &tmp, &rem)) != MP_OKAY) {
+        mp_clear(&tmp);
+        return res;
+      }
+
+      /* Generate digits, use capital letters */
+      ch = s_mp_todigit(rem, radix, 0);
+
+      str[pos++] = ch;
+    }
+
+    /* Add - sign if original value was negative */
+    if(sgn == NEG)
+      str[pos++] = '-';
+
+    /* Add trailing NUL to end the string        */
+    str[pos--] = '\0';
+
+    /* Reverse the digits and sign indicator     */
+    ix = 0;
+    while(ix < pos) {
+      char tmp = str[ix];
+
+      str[ix] = str[pos];
+      str[pos] = tmp;
+      ++ix;
+      --pos;
+    }
+
+    mp_clear(&tmp);
+  }
+
+  return MP_OKAY;
+
+} /* end mp_toradix() */
+
+/* }}} */
+
+/* {{{ mp_tovalue(ch, r) */
+
+int    mp_tovalue(char ch, int r)
+{
+  return s_mp_tovalue(ch, r);
+
+} /* end mp_tovalue() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ mp_strerror(ec) */
+
+/*
+  mp_strerror(ec)
+
+  Return a string describing the meaning of error code 'ec'.  The
+  string returned is allocated in static memory, so the caller should
+  not attempt to modify or free the memory associated with this
+  string.
+ */
+const char  *mp_strerror(mp_err ec)
+{
+  int   aec = (ec < 0) ? -ec : ec;
+
+  /* Code values are negative, so the senses of these comparisons
+     are accurate */
+  if(ec < MP_LAST_CODE || ec > MP_OKAY) {
+    return mp_err_string[0];  /* unknown error code */
+  } else {
+    return mp_err_string[aec + 1];
+  }
+
+} /* end mp_strerror() */
+
+/* }}} */
+
+/*========================================================================*/
+/*------------------------------------------------------------------------*/
+/* Static function definitions (internal use only)                        */
+
+/* {{{ Memory management */
+
+/* {{{ s_mp_grow(mp, min) */
+
+/* Make sure there are at least 'min' digits allocated to mp              */
+mp_err   s_mp_grow(mp_int *mp, mp_size min)
+{
+  if(min > ALLOC(mp)) {
+    mp_digit   *tmp;
+
+    /* Set min to next nearest default precision block size */
+    min = MP_ROUNDUP(min, s_mp_defprec);
+
+    if((tmp = s_mp_alloc(min, sizeof(mp_digit), FLAG(mp))) == NULL)
+      return MP_MEM;
+
+    s_mp_copy(DIGITS(mp), tmp, USED(mp));
+
+#if MP_CRYPTO
+    s_mp_setz(DIGITS(mp), ALLOC(mp));
+#endif
+    s_mp_free(DIGITS(mp), ALLOC(mp));
+    DIGITS(mp) = tmp;
+    ALLOC(mp) = min;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_grow() */
+
+/* }}} */
+
+/* {{{ s_mp_pad(mp, min) */
+
+/* Make sure the used size of mp is at least 'min', growing if needed     */
+mp_err   s_mp_pad(mp_int *mp, mp_size min)
+{
+  if(min > USED(mp)) {
+    mp_err  res;
+
+    /* Make sure there is room to increase precision  */
+    if (min > ALLOC(mp)) {
+      if ((res = s_mp_grow(mp, min)) != MP_OKAY)
+        return res;
+    } else {
+      s_mp_setz(DIGITS(mp) + USED(mp), min - USED(mp));
+    }
+
+    /* Increase precision; should already be 0-filled */
+    USED(mp) = min;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_pad() */
+
+/* }}} */
+
+/* {{{ s_mp_setz(dp, count) */
+
+#if MP_MACRO == 0
+/* Set 'count' digits pointed to by dp to be zeroes                       */
+void s_mp_setz(mp_digit *dp, mp_size count)
+{
+#if MP_MEMSET == 0
+  int  ix;
+
+  for(ix = 0; ix < count; ix++)
+    dp[ix] = 0;
+#else
+  memset(dp, 0, count * sizeof(mp_digit));
+#endif
+
+} /* end s_mp_setz() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_copy(sp, dp, count) */
+
+#if MP_MACRO == 0
+/* Copy 'count' digits from sp to dp                                      */
+void s_mp_copy(const mp_digit *sp, mp_digit *dp, mp_size count)
+{
+#if MP_MEMCPY == 0
+  int  ix;
+
+  for(ix = 0; ix < count; ix++)
+    dp[ix] = sp[ix];
+#else
+  memcpy(dp, sp, count * sizeof(mp_digit));
+#endif
+
+} /* end s_mp_copy() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_alloc(nb, ni, kmflag) */
+
+#if MP_MACRO == 0
+/* Allocate ni records of nb bytes each, and return a pointer to that     */
+void    *s_mp_alloc(size_t nb, size_t ni, int kmflag)
+{
+  mp_int *mp;
+  ++mp_allocs;
+#ifdef _KERNEL
+  mp = kmem_zalloc(nb * ni, kmflag);
+  if (mp != NULL)
+    FLAG(mp) = kmflag;
+  return (mp);
+#else
+  return calloc(nb, ni);
+#endif
+
+} /* end s_mp_alloc() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_free(ptr) */
+
+#if MP_MACRO == 0
+/* Free the memory pointed to by ptr                                      */
+void     s_mp_free(void *ptr, mp_size alloc)
+{
+  if(ptr) {
+    ++mp_frees;
+#ifdef _KERNEL
+    kmem_free(ptr, alloc * sizeof (mp_digit));
+#else
+    free(ptr);
+#endif
+  }
+} /* end s_mp_free() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_clamp(mp) */
+
+#if MP_MACRO == 0
+/* Remove leading zeroes from the given value                             */
+void     s_mp_clamp(mp_int *mp)
+{
+  mp_size used = MP_USED(mp);
+  while (used > 1 && DIGIT(mp, used - 1) == 0)
+    --used;
+  MP_USED(mp) = used;
+} /* end s_mp_clamp() */
+#endif
+
+/* }}} */
+
+/* {{{ s_mp_exch(a, b) */
+
+/* Exchange the data for a and b; (b, a) = (a, b)                         */
+void     s_mp_exch(mp_int *a, mp_int *b)
+{
+  mp_int   tmp;
+
+  tmp = *a;
+  *a = *b;
+  *b = tmp;
+
+} /* end s_mp_exch() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Arithmetic helpers */
+
+/* {{{ s_mp_lshd(mp, p) */
+
+/*
+   Shift mp leftward by p digits, growing if needed, and zero-filling
+   the in-shifted digits at the right end.  This is a convenient
+   alternative to multiplication by powers of the radix
+   The value of USED(mp) must already have been set to the value for
+   the shifted result.
+ */
+
+mp_err   s_mp_lshd(mp_int *mp, mp_size p)
+{
+  mp_err  res;
+  mp_size pos;
+  int     ix;
+
+  if(p == 0)
+    return MP_OKAY;
+
+  if (MP_USED(mp) == 1 && MP_DIGIT(mp, 0) == 0)
+    return MP_OKAY;
+
+  if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)
+    return res;
+
+  pos = USED(mp) - 1;
+
+  /* Shift all the significant figures over as needed */
+  for(ix = pos - p; ix >= 0; ix--)
+    DIGIT(mp, ix + p) = DIGIT(mp, ix);
+
+  /* Fill the bottom digits with zeroes */
+  for(ix = 0; ix < p; ix++)
+    DIGIT(mp, ix) = 0;
+
+  return MP_OKAY;
+
+} /* end s_mp_lshd() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_2d(mp, d) */
+
+/*
+  Multiply the integer by 2^d, where d is a number of bits.  This
+  amounts to a bitwise shift of the value.
+ */
+mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d)
+{
+  mp_err   res;
+  mp_digit dshift, bshift;
+  mp_digit mask;
+
+  ARGCHK(mp != NULL,  MP_BADARG);
+
+  dshift = d / MP_DIGIT_BIT;
+  bshift = d % MP_DIGIT_BIT;
+  /* bits to be shifted out of the top word */
+  mask   = ((mp_digit)~0 << (MP_DIGIT_BIT - bshift));
+  mask  &= MP_DIGIT(mp, MP_USED(mp) - 1);
+
+  if (MP_OKAY != (res = s_mp_pad(mp, MP_USED(mp) + dshift + (mask != 0) )))
+    return res;
+
+  if (dshift && MP_OKAY != (res = s_mp_lshd(mp, dshift)))
+    return res;
+
+  if (bshift) {
+    mp_digit *pa = MP_DIGITS(mp);
+    mp_digit *alim = pa + MP_USED(mp);
+    mp_digit  prev = 0;
+
+    for (pa += dshift; pa < alim; ) {
+      mp_digit x = *pa;
+      *pa++ = (x << bshift) | prev;
+      prev = x >> (DIGIT_BIT - bshift);
+    }
+  }
+
+  s_mp_clamp(mp);
+  return MP_OKAY;
+} /* end s_mp_mul_2d() */
+
+/* {{{ s_mp_rshd(mp, p) */
+
+/*
+   Shift mp rightward by p digits.  Maintains the invariant that
+   digits above the precision are all zero.  Digits shifted off the
+   end are lost.  Cannot fail.
+ */
+
+void     s_mp_rshd(mp_int *mp, mp_size p)
+{
+  mp_size  ix;
+  mp_digit *src, *dst;
+
+  if(p == 0)
+    return;
+
+  /* Shortcut when all digits are to be shifted off */
+  if(p >= USED(mp)) {
+    s_mp_setz(DIGITS(mp), ALLOC(mp));
+    USED(mp) = 1;
+    SIGN(mp) = ZPOS;
+    return;
+  }
+
+  /* Shift all the significant figures over as needed */
+  dst = MP_DIGITS(mp);
+  src = dst + p;
+  for (ix = USED(mp) - p; ix > 0; ix--)
+    *dst++ = *src++;
+
+  MP_USED(mp) -= p;
+  /* Fill the top digits with zeroes */
+  while (p-- > 0)
+    *dst++ = 0;
+
+#if 0
+  /* Strip off any leading zeroes    */
+  s_mp_clamp(mp);
+#endif
+
+} /* end s_mp_rshd() */
+
+/* }}} */
+
+/* {{{ s_mp_div_2(mp) */
+
+/* Divide by two -- take advantage of radix properties to do it fast      */
+void     s_mp_div_2(mp_int *mp)
+{
+  s_mp_div_2d(mp, 1);
+
+} /* end s_mp_div_2() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_2(mp) */
+
+mp_err s_mp_mul_2(mp_int *mp)
+{
+  mp_digit *pd;
+  int      ix, used;
+  mp_digit kin = 0;
+
+  /* Shift digits leftward by 1 bit */
+  used = MP_USED(mp);
+  pd = MP_DIGITS(mp);
+  for (ix = 0; ix < used; ix++) {
+    mp_digit d = *pd;
+    *pd++ = (d << 1) | kin;
+    kin = (d >> (DIGIT_BIT - 1));
+  }
+
+  /* Deal with rollover from last digit */
+  if (kin) {
+    if (ix >= ALLOC(mp)) {
+      mp_err res;
+      if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)
+        return res;
+    }
+
+    DIGIT(mp, ix) = kin;
+    USED(mp) += 1;
+  }
+
+  return MP_OKAY;
+
+} /* end s_mp_mul_2() */
+
+/* }}} */
+
+/* {{{ s_mp_mod_2d(mp, d) */
+
+/*
+  Remainder the integer by 2^d, where d is a number of bits.  This
+  amounts to a bitwise AND of the value, and does not require the full
+  division code
+ */
+void     s_mp_mod_2d(mp_int *mp, mp_digit d)
+{
+  mp_size  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);
+  mp_size  ix;
+  mp_digit dmask;
+
+  if(ndig >= USED(mp))
+    return;
+
+  /* Flush all the bits above 2^d in its digit */
+  dmask = ((mp_digit)1 << nbit) - 1;
+  DIGIT(mp, ndig) &= dmask;
+
+  /* Flush all digits above the one with 2^d in it */
+  for(ix = ndig + 1; ix < USED(mp); ix++)
+    DIGIT(mp, ix) = 0;
+
+  s_mp_clamp(mp);
+
+} /* end s_mp_mod_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_div_2d(mp, d) */
+
+/*
+  Divide the integer by 2^d, where d is a number of bits.  This
+  amounts to a bitwise shift of the value, and does not require the
+  full division code (used in Barrett reduction, see below)
+ */
+void     s_mp_div_2d(mp_int *mp, mp_digit d)
+{
+  int       ix;
+  mp_digit  save, next, mask;
+
+  s_mp_rshd(mp, d / DIGIT_BIT);
+  d %= DIGIT_BIT;
+  if (d) {
+    mask = ((mp_digit)1 << d) - 1;
+    save = 0;
+    for(ix = USED(mp) - 1; ix >= 0; ix--) {
+      next = DIGIT(mp, ix) & mask;
+      DIGIT(mp, ix) = (DIGIT(mp, ix) >> d) | (save << (DIGIT_BIT - d));
+      save = next;
+    }
+  }
+  s_mp_clamp(mp);
+
+} /* end s_mp_div_2d() */
+
+/* }}} */
+
+/* {{{ s_mp_norm(a, b, *d) */
+
+/*
+  s_mp_norm(a, b, *d)
+
+  Normalize a and b for division, where b is the divisor.  In order
+  that we might make good guesses for quotient digits, we want the
+  leading digit of b to be at least half the radix, which we
+  accomplish by multiplying a and b by a power of 2.  The exponent
+  (shift count) is placed in *pd, so that the remainder can be shifted
+  back at the end of the division process.
+ */
+
+mp_err   s_mp_norm(mp_int *a, mp_int *b, mp_digit *pd)
+{
+  mp_digit  d;
+  mp_digit  mask;
+  mp_digit  b_msd;
+  mp_err    res    = MP_OKAY;
+
+  d = 0;
+  mask  = DIGIT_MAX & ~(DIGIT_MAX >> 1);        /* mask is msb of digit */
+  b_msd = DIGIT(b, USED(b) - 1);
+  while (!(b_msd & mask)) {
+    b_msd <<= 1;
+    ++d;
+  }
+
+  if (d) {
+    MP_CHECKOK( s_mp_mul_2d(a, d) );
+    MP_CHECKOK( s_mp_mul_2d(b, d) );
+  }
+
+  *pd = d;
+CLEANUP:
+  return res;
+
+} /* end s_mp_norm() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive digit arithmetic */
+
+/* {{{ s_mp_add_d(mp, d) */
+
+/* Add d to |mp| in place                                                 */
+mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  mp_word   w, k = 0;
+  mp_size   ix = 1;
+
+  w = (mp_word)DIGIT(mp, 0) + d;
+  DIGIT(mp, 0) = ACCUM(w);
+  k = CARRYOUT(w);
+
+  while(ix < USED(mp) && k) {
+    w = (mp_word)DIGIT(mp, ix) + k;
+    DIGIT(mp, ix) = ACCUM(w);
+    k = CARRYOUT(w);
+    ++ix;
+  }
+
+  if(k != 0) {
+    mp_err  res;
+
+    if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(mp, ix) = (mp_digit)k;
+  }
+
+  return MP_OKAY;
+#else
+  mp_digit * pmp = MP_DIGITS(mp);
+  mp_digit sum, mp_i, carry = 0;
+  mp_err   res = MP_OKAY;
+  int used = (int)MP_USED(mp);
+
+  mp_i = *pmp;
+  *pmp++ = sum = d + mp_i;
+  carry = (sum < d);
+  while (carry && --used > 0) {
+    mp_i = *pmp;
+    *pmp++ = sum = carry + mp_i;
+    carry = !sum;
+  }
+  if (carry && !used) {
+    /* mp is growing */
+    used = MP_USED(mp);
+    MP_CHECKOK( s_mp_pad(mp, used + 1) );
+    MP_DIGIT(mp, used) = carry;
+  }
+CLEANUP:
+  return res;
+#endif
+} /* end s_mp_add_d() */
+
+/* }}} */
+
+/* {{{ s_mp_sub_d(mp, d) */
+
+/* Subtract d from |mp| in place, assumes |mp| > d                        */
+mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+  mp_word   w, b = 0;
+  mp_size   ix = 1;
+
+  /* Compute initial subtraction    */
+  w = (RADIX + (mp_word)DIGIT(mp, 0)) - d;
+  b = CARRYOUT(w) ? 0 : 1;
+  DIGIT(mp, 0) = ACCUM(w);
+
+  /* Propagate borrows leftward     */
+  while(b && ix < USED(mp)) {
+    w = (RADIX + (mp_word)DIGIT(mp, ix)) - b;
+    b = CARRYOUT(w) ? 0 : 1;
+    DIGIT(mp, ix) = ACCUM(w);
+    ++ix;
+  }
+
+  /* Remove leading zeroes          */
+  s_mp_clamp(mp);
+
+  /* If we have a borrow out, it's a violation of the input invariant */
+  if(b)
+    return MP_RANGE;
+  else
+    return MP_OKAY;
+#else
+  mp_digit *pmp = MP_DIGITS(mp);
+  mp_digit mp_i, diff, borrow;
+  mp_size  used = MP_USED(mp);
+
+  mp_i = *pmp;
+  *pmp++ = diff = mp_i - d;
+  borrow = (diff > mp_i);
+  while (borrow && --used) {
+    mp_i = *pmp;
+    *pmp++ = diff = mp_i - borrow;
+    borrow = (diff > mp_i);
+  }
+  s_mp_clamp(mp);
+  return (borrow && !used) ? MP_RANGE : MP_OKAY;
+#endif
+} /* end s_mp_sub_d() */
+
+/* }}} */
+
+/* {{{ s_mp_mul_d(a, d) */
+
+/* Compute a = a * d, single digit multiplication                         */
+mp_err   s_mp_mul_d(mp_int *a, mp_digit d)
+{
+  mp_err  res;
+  mp_size used;
+  int     pow;
+
+  if (!d) {
+    mp_zero(a);
+    return MP_OKAY;
+  }
+  if (d == 1)
+    return MP_OKAY;
+  if (0 <= (pow = s_mp_ispow2d(d))) {
+    return s_mp_mul_2d(a, (mp_digit)pow);
+  }
+
+  used = MP_USED(a);
+  MP_CHECKOK( s_mp_pad(a, used + 1) );
+
+  s_mpv_mul_d(MP_DIGITS(a), used, d, MP_DIGITS(a));
+
+  s_mp_clamp(a);
+
+CLEANUP:
+  return res;
+
+} /* end s_mp_mul_d() */
+
+/* }}} */
+
+/* {{{ s_mp_div_d(mp, d, r) */
+
+/*
+  s_mp_div_d(mp, d, r)
+
+  Compute the quotient mp = mp / d and remainder r = mp mod d, for a
+  single digit d.  If r is null, the remainder will be discarded.
+ */
+
+mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r)
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
+  mp_word   w = 0, q;
+#else
+  mp_digit  w, q;
+#endif
+  int       ix;
+  mp_err    res;
+  mp_int    quot;
+  mp_int    rem;
+
+  if(d == 0)
+    return MP_RANGE;
+  if (d == 1) {
+    if (r)
+      *r = 0;
+    return MP_OKAY;
+  }
+  /* could check for power of 2 here, but mp_div_d does that. */
+  if (MP_USED(mp) == 1) {
+    mp_digit n   = MP_DIGIT(mp,0);
+    mp_digit rem;
+
+    q   = n / d;
+    rem = n % d;
+    MP_DIGIT(mp,0) = q;
+    if (r)
+      *r = rem;
+    return MP_OKAY;
+  }
+
+  MP_DIGITS(&rem)  = 0;
+  MP_DIGITS(&quot) = 0;
+  /* Make room for the quotient */
+  MP_CHECKOK( mp_init_size(&quot, USED(mp), FLAG(mp)) );
+
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    w = (w << DIGIT_BIT) | DIGIT(mp, ix);
+
+    if(w >= d) {
+      q = w / d;
+      w = w % d;
+    } else {
+      q = 0;
+    }
+
+    s_mp_lshd(&quot, 1);
+    DIGIT(&quot, 0) = (mp_digit)q;
+  }
+#else
+  {
+    mp_digit p;
+#if !defined(MP_ASSEMBLY_DIV_2DX1D)
+    mp_digit norm;
+#endif
+
+    MP_CHECKOK( mp_init_copy(&rem, mp) );
+
+#if !defined(MP_ASSEMBLY_DIV_2DX1D)
+    MP_DIGIT(&quot, 0) = d;
+    MP_CHECKOK( s_mp_norm(&rem, &quot, &norm) );
+    if (norm)
+      d <<= norm;
+    MP_DIGIT(&quot, 0) = 0;
+#endif
+
+    p = 0;
+    for (ix = USED(&rem) - 1; ix >= 0; ix--) {
+      w = DIGIT(&rem, ix);
+
+      if (p) {
+        MP_CHECKOK( s_mpv_div_2dx1d(p, w, d, &q, &w) );
+      } else if (w >= d) {
+        q = w / d;
+        w = w % d;
+      } else {
+        q = 0;
+      }
+
+      MP_CHECKOK( s_mp_lshd(&quot, 1) );
+      DIGIT(&quot, 0) = q;
+      p = w;
+    }
+#if !defined(MP_ASSEMBLY_DIV_2DX1D)
+    if (norm)
+      w >>= norm;
+#endif
+  }
+#endif
+
+  /* Deliver the remainder, if desired */
+  if(r)
+    *r = (mp_digit)w;
+
+  s_mp_clamp(&quot);
+  mp_exch(&quot, mp);
+CLEANUP:
+  mp_clear(&quot);
+  mp_clear(&rem);
+
+  return res;
+} /* end s_mp_div_d() */
+
+/* }}} */
+
+
+/* }}} */
+
+/* {{{ Primitive full arithmetic */
+
+/* {{{ s_mp_add(a, b) */
+
+/* Compute a = |a| + |b|                                                  */
+mp_err   s_mp_add(mp_int *a, const mp_int *b)  /* magnitude addition      */
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  mp_word   w = 0;
+#else
+  mp_digit  d, sum, carry = 0;
+#endif
+  mp_digit *pa, *pb;
+  mp_size   ix;
+  mp_size   used;
+  mp_err    res;
+
+  /* Make sure a has enough precision for the output value */
+  if((USED(b) > USED(a)) && (res = s_mp_pad(a, USED(b))) != MP_OKAY)
+    return res;
+
+  /*
+    Add up all digits up to the precision of b.  If b had initially
+    the same precision as a, or greater, we took care of it by the
+    padding step above, so there is no problem.  If b had initially
+    less precision, we'll have to make sure the carry out is duly
+    propagated upward among the higher-order digits of the sum.
+   */
+  pa = MP_DIGITS(a);
+  pb = MP_DIGITS(b);
+  used = MP_USED(b);
+  for(ix = 0; ix < used; ix++) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+    w = w + *pa + *pb++;
+    *pa++ = ACCUM(w);
+    w = CARRYOUT(w);
+#else
+    d = *pa;
+    sum = d + *pb++;
+    d = (sum < d);                      /* detect overflow */
+    *pa++ = sum += carry;
+    carry = d + (sum < carry);          /* detect overflow */
+#endif
+  }
+
+  /* If we run out of 'b' digits before we're actually done, make
+     sure the carries get propagated upward...
+   */
+  used = MP_USED(a);
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  while (w && ix < used) {
+    w = w + *pa;
+    *pa++ = ACCUM(w);
+    w = CARRYOUT(w);
+    ++ix;
+  }
+#else
+  while (carry && ix < used) {
+    sum = carry + *pa;
+    *pa++ = sum;
+    carry = !sum;
+    ++ix;
+  }
+#endif
+
+  /* If there's an overall carry out, increase precision and include
+     it.  We could have done this initially, but why touch the memory
+     allocator unless we're sure we have to?
+   */
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  if (w) {
+    if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(a, ix) = (mp_digit)w;
+  }
+#else
+  if (carry) {
+    if((res = s_mp_pad(a, used + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(a, used) = carry;
+  }
+#endif
+
+  return MP_OKAY;
+} /* end s_mp_add() */
+
+/* }}} */
+
+/* Compute c = |a| + |b|         */ /* magnitude addition      */
+mp_err   s_mp_add_3arg(const mp_int *a, const mp_int *b, mp_int *c)
+{
+  mp_digit *pa, *pb, *pc;
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  mp_word   w = 0;
+#else
+  mp_digit  sum, carry = 0, d;
+#endif
+  mp_size   ix;
+  mp_size   used;
+  mp_err    res;
+
+  MP_SIGN(c) = MP_SIGN(a);
+  if (MP_USED(a) < MP_USED(b)) {
+    const mp_int *xch = a;
+    a = b;
+    b = xch;
+  }
+
+  /* Make sure a has enough precision for the output value */
+  if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
+    return res;
+
+  /*
+    Add up all digits up to the precision of b.  If b had initially
+    the same precision as a, or greater, we took care of it by the
+    exchange step above, so there is no problem.  If b had initially
+    less precision, we'll have to make sure the carry out is duly
+    propagated upward among the higher-order digits of the sum.
+   */
+  pa = MP_DIGITS(a);
+  pb = MP_DIGITS(b);
+  pc = MP_DIGITS(c);
+  used = MP_USED(b);
+  for (ix = 0; ix < used; ix++) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+    w = w + *pa++ + *pb++;
+    *pc++ = ACCUM(w);
+    w = CARRYOUT(w);
+#else
+    d = *pa++;
+    sum = d + *pb++;
+    d = (sum < d);                      /* detect overflow */
+    *pc++ = sum += carry;
+    carry = d + (sum < carry);          /* detect overflow */
+#endif
+  }
+
+  /* If we run out of 'b' digits before we're actually done, make
+     sure the carries get propagated upward...
+   */
+  for (used = MP_USED(a); ix < used; ++ix) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+    w = w + *pa++;
+    *pc++ = ACCUM(w);
+    w = CARRYOUT(w);
+#else
+    *pc++ = sum = carry + *pa++;
+    carry = (sum < carry);
+#endif
+  }
+
+  /* If there's an overall carry out, increase precision and include
+     it.  We could have done this initially, but why touch the memory
+     allocator unless we're sure we have to?
+   */
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  if (w) {
+    if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(c, used) = (mp_digit)w;
+    ++used;
+  }
+#else
+  if (carry) {
+    if((res = s_mp_pad(c, used + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(c, used) = carry;
+    ++used;
+  }
+#endif
+  MP_USED(c) = used;
+  return MP_OKAY;
+}
+/* {{{ s_mp_add_offset(a, b, offset) */
+
+/* Compute a = |a| + ( |b| * (RADIX ** offset) )             */
+mp_err   s_mp_add_offset(mp_int *a, mp_int *b, mp_size offset)
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  mp_word   w, k = 0;
+#else
+  mp_digit  d, sum, carry = 0;
+#endif
+  mp_size   ib;
+  mp_size   ia;
+  mp_size   lim;
+  mp_err    res;
+
+  /* Make sure a has enough precision for the output value */
+  lim = MP_USED(b) + offset;
+  if((lim > USED(a)) && (res = s_mp_pad(a, lim)) != MP_OKAY)
+    return res;
+
+  /*
+    Add up all digits up to the precision of b.  If b had initially
+    the same precision as a, or greater, we took care of it by the
+    padding step above, so there is no problem.  If b had initially
+    less precision, we'll have to make sure the carry out is duly
+    propagated upward among the higher-order digits of the sum.
+   */
+  lim = USED(b);
+  for(ib = 0, ia = offset; ib < lim; ib++, ia++) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+    w = (mp_word)DIGIT(a, ia) + DIGIT(b, ib) + k;
+    DIGIT(a, ia) = ACCUM(w);
+    k = CARRYOUT(w);
+#else
+    d = MP_DIGIT(a, ia);
+    sum = d + MP_DIGIT(b, ib);
+    d = (sum < d);
+    MP_DIGIT(a,ia) = sum += carry;
+    carry = d + (sum < carry);
+#endif
+  }
+
+  /* If we run out of 'b' digits before we're actually done, make
+     sure the carries get propagated upward...
+   */
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  for (lim = MP_USED(a); k && (ia < lim); ++ia) {
+    w = (mp_word)DIGIT(a, ia) + k;
+    DIGIT(a, ia) = ACCUM(w);
+    k = CARRYOUT(w);
+  }
+#else
+  for (lim = MP_USED(a); carry && (ia < lim); ++ia) {
+    d = MP_DIGIT(a, ia);
+    MP_DIGIT(a,ia) = sum = d + carry;
+    carry = (sum < d);
+  }
+#endif
+
+  /* If there's an overall carry out, increase precision and include
+     it.  We could have done this initially, but why touch the memory
+     allocator unless we're sure we have to?
+   */
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_ADD_WORD)
+  if(k) {
+    if((res = s_mp_pad(a, USED(a) + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(a, ia) = (mp_digit)k;
+  }
+#else
+  if (carry) {
+    if((res = s_mp_pad(a, lim + 1)) != MP_OKAY)
+      return res;
+
+    DIGIT(a, lim) = carry;
+  }
+#endif
+  s_mp_clamp(a);
+
+  return MP_OKAY;
+
+} /* end s_mp_add_offset() */
+
+/* }}} */
+
+/* {{{ s_mp_sub(a, b) */
+
+/* Compute a = |a| - |b|, assumes |a| >= |b|                              */
+mp_err   s_mp_sub(mp_int *a, const mp_int *b)  /* magnitude subtract      */
+{
+  mp_digit *pa, *pb, *limit;
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+  mp_sword  w = 0;
+#else
+  mp_digit  d, diff, borrow = 0;
+#endif
+
+  /*
+    Subtract and propagate borrow.  Up to the precision of b, this
+    accounts for the digits of b; after that, we just make sure the
+    carries get to the right place.  This saves having to pad b out to
+    the precision of a just to make the loops work right...
+   */
+  pa = MP_DIGITS(a);
+  pb = MP_DIGITS(b);
+  limit = pb + MP_USED(b);
+  while (pb < limit) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+    w = w + *pa - *pb++;
+    *pa++ = ACCUM(w);
+    w >>= MP_DIGIT_BIT;
+#else
+    d = *pa;
+    diff = d - *pb++;
+    d = (diff > d);                             /* detect borrow */
+    if (borrow && --diff == MP_DIGIT_MAX)
+      ++d;
+    *pa++ = diff;
+    borrow = d;
+#endif
+  }
+  limit = MP_DIGITS(a) + MP_USED(a);
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+  while (w && pa < limit) {
+    w = w + *pa;
+    *pa++ = ACCUM(w);
+    w >>= MP_DIGIT_BIT;
+  }
+#else
+  while (borrow && pa < limit) {
+    d = *pa;
+    *pa++ = diff = d - borrow;
+    borrow = (diff > d);
+  }
+#endif
+
+  /* Clobber any leading zeroes we created    */
+  s_mp_clamp(a);
+
+  /*
+     If there was a borrow out, then |b| > |a| in violation
+     of our input invariant.  We've already done the work,
+     but we'll at least complain about it...
+   */
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+  return w ? MP_RANGE : MP_OKAY;
+#else
+  return borrow ? MP_RANGE : MP_OKAY;
+#endif
+} /* end s_mp_sub() */
+
+/* }}} */
+
+/* Compute c = |a| - |b|, assumes |a| >= |b| */ /* magnitude subtract      */
+mp_err   s_mp_sub_3arg(const mp_int *a, const mp_int *b, mp_int *c)
+{
+  mp_digit *pa, *pb, *pc;
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+  mp_sword  w = 0;
+#else
+  mp_digit  d, diff, borrow = 0;
+#endif
+  int       ix, limit;
+  mp_err    res;
+
+  MP_SIGN(c) = MP_SIGN(a);
+
+  /* Make sure a has enough precision for the output value */
+  if (MP_OKAY != (res = s_mp_pad(c, MP_USED(a))))
+    return res;
+
+  /*
+    Subtract and propagate borrow.  Up to the precision of b, this
+    accounts for the digits of b; after that, we just make sure the
+    carries get to the right place.  This saves having to pad b out to
+    the precision of a just to make the loops work right...
+   */
+  pa = MP_DIGITS(a);
+  pb = MP_DIGITS(b);
+  pc = MP_DIGITS(c);
+  limit = MP_USED(b);
+  for (ix = 0; ix < limit; ++ix) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+    w = w + *pa++ - *pb++;
+    *pc++ = ACCUM(w);
+    w >>= MP_DIGIT_BIT;
+#else
+    d = *pa++;
+    diff = d - *pb++;
+    d = (diff > d);
+    if (borrow && --diff == MP_DIGIT_MAX)
+      ++d;
+    *pc++ = diff;
+    borrow = d;
+#endif
+  }
+  for (limit = MP_USED(a); ix < limit; ++ix) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+    w = w + *pa++;
+    *pc++ = ACCUM(w);
+    w >>= MP_DIGIT_BIT;
+#else
+    d = *pa++;
+    *pc++ = diff = d - borrow;
+    borrow = (diff > d);
+#endif
+  }
+
+  /* Clobber any leading zeroes we created    */
+  MP_USED(c) = ix;
+  s_mp_clamp(c);
+
+  /*
+     If there was a borrow out, then |b| > |a| in violation
+     of our input invariant.  We've already done the work,
+     but we'll at least complain about it...
+   */
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_SUB_WORD)
+  return w ? MP_RANGE : MP_OKAY;
+#else
+  return borrow ? MP_RANGE : MP_OKAY;
+#endif
+}
+/* {{{ s_mp_mul(a, b) */
+
+/* Compute a = |a| * |b|                                                  */
+mp_err   s_mp_mul(mp_int *a, const mp_int *b)
+{
+  return mp_mul(a, b, a);
+} /* end s_mp_mul() */
+
+/* }}} */
+
+#if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
+/* This trick works on Sparc V8 CPUs with the Workshop compilers. */
+#define MP_MUL_DxD(a, b, Phi, Plo) \
+  { unsigned long long product = (unsigned long long)a * b; \
+    Plo = (mp_digit)product; \
+    Phi = (mp_digit)(product >> MP_DIGIT_BIT); }
+#elif defined(OSF1)
+#define MP_MUL_DxD(a, b, Phi, Plo) \
+  { Plo = asm ("mulq %a0, %a1, %v0", a, b);\
+    Phi = asm ("umulh %a0, %a1, %v0", a, b); }
+#else
+#define MP_MUL_DxD(a, b, Phi, Plo) \
+  { mp_digit a0b1, a1b0; \
+    Plo = (a & MP_HALF_DIGIT_MAX) * (b & MP_HALF_DIGIT_MAX); \
+    Phi = (a >> MP_HALF_DIGIT_BIT) * (b >> MP_HALF_DIGIT_BIT); \
+    a0b1 = (a & MP_HALF_DIGIT_MAX) * (b >> MP_HALF_DIGIT_BIT); \
+    a1b0 = (a >> MP_HALF_DIGIT_BIT) * (b & MP_HALF_DIGIT_MAX); \
+    a1b0 += a0b1; \
+    Phi += a1b0 >> MP_HALF_DIGIT_BIT; \
+    if (a1b0 < a0b1)  \
+      Phi += MP_HALF_RADIX; \
+    a1b0 <<= MP_HALF_DIGIT_BIT; \
+    Plo += a1b0; \
+    if (Plo < a1b0) \
+      ++Phi; \
+  }
+#endif
+
+#if !defined(MP_ASSEMBLY_MULTIPLY)
+/* c = a * b */
+void s_mpv_mul_d(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
+  mp_digit   d = 0;
+
+  /* Inner product:  Digits of a */
+  while (a_len--) {
+    mp_word w = ((mp_word)b * *a++) + d;
+    *c++ = ACCUM(w);
+    d = CARRYOUT(w);
+  }
+  *c = d;
+#else
+  mp_digit carry = 0;
+  while (a_len--) {
+    mp_digit a_i = *a++;
+    mp_digit a0b0, a1b1;
+
+    MP_MUL_DxD(a_i, b, a1b1, a0b0);
+
+    a0b0 += carry;
+    if (a0b0 < carry)
+      ++a1b1;
+    *c++ = a0b0;
+    carry = a1b1;
+  }
+  *c = carry;
+#endif
+}
+
+/* c += a * b */
+void s_mpv_mul_d_add(const mp_digit *a, mp_size a_len, mp_digit b,
+                              mp_digit *c)
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
+  mp_digit   d = 0;
+
+  /* Inner product:  Digits of a */
+  while (a_len--) {
+    mp_word w = ((mp_word)b * *a++) + *c + d;
+    *c++ = ACCUM(w);
+    d = CARRYOUT(w);
+  }
+  *c = d;
+#else
+  mp_digit carry = 0;
+  while (a_len--) {
+    mp_digit a_i = *a++;
+    mp_digit a0b0, a1b1;
+
+    MP_MUL_DxD(a_i, b, a1b1, a0b0);
+
+    a0b0 += carry;
+    if (a0b0 < carry)
+      ++a1b1;
+    a0b0 += a_i = *c;
+    if (a0b0 < a_i)
+      ++a1b1;
+    *c++ = a0b0;
+    carry = a1b1;
+  }
+  *c = carry;
+#endif
+}
+
+/* Presently, this is only used by the Montgomery arithmetic code. */
+/* c += a * b */
+void s_mpv_mul_d_add_prop(const mp_digit *a, mp_size a_len, mp_digit b, mp_digit *c)
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
+  mp_digit   d = 0;
+
+  /* Inner product:  Digits of a */
+  while (a_len--) {
+    mp_word w = ((mp_word)b * *a++) + *c + d;
+    *c++ = ACCUM(w);
+    d = CARRYOUT(w);
+  }
+
+  while (d) {
+    mp_word w = (mp_word)*c + d;
+    *c++ = ACCUM(w);
+    d = CARRYOUT(w);
+  }
+#else
+  mp_digit carry = 0;
+  while (a_len--) {
+    mp_digit a_i = *a++;
+    mp_digit a0b0, a1b1;
+
+    MP_MUL_DxD(a_i, b, a1b1, a0b0);
+
+    a0b0 += carry;
+    if (a0b0 < carry)
+      ++a1b1;
+
+    a0b0 += a_i = *c;
+    if (a0b0 < a_i)
+      ++a1b1;
+
+    *c++ = a0b0;
+    carry = a1b1;
+  }
+  while (carry) {
+    mp_digit c_i = *c;
+    carry += c_i;
+    *c++ = carry;
+    carry = carry < c_i;
+  }
+#endif
+}
+#endif
+
+#if defined(MP_USE_UINT_DIGIT) && defined(MP_USE_LONG_LONG_MULTIPLY)
+/* This trick works on Sparc V8 CPUs with the Workshop compilers. */
+#define MP_SQR_D(a, Phi, Plo) \
+  { unsigned long long square = (unsigned long long)a * a; \
+    Plo = (mp_digit)square; \
+    Phi = (mp_digit)(square >> MP_DIGIT_BIT); }
+#elif defined(OSF1)
+#define MP_SQR_D(a, Phi, Plo) \
+  { Plo = asm ("mulq  %a0, %a0, %v0", a);\
+    Phi = asm ("umulh %a0, %a0, %v0", a); }
+#else
+#define MP_SQR_D(a, Phi, Plo) \
+  { mp_digit Pmid; \
+    Plo  = (a  & MP_HALF_DIGIT_MAX) * (a  & MP_HALF_DIGIT_MAX); \
+    Phi  = (a >> MP_HALF_DIGIT_BIT) * (a >> MP_HALF_DIGIT_BIT); \
+    Pmid = (a  & MP_HALF_DIGIT_MAX) * (a >> MP_HALF_DIGIT_BIT); \
+    Phi += Pmid >> (MP_HALF_DIGIT_BIT - 1);  \
+    Pmid <<= (MP_HALF_DIGIT_BIT + 1);  \
+    Plo += Pmid;  \
+    if (Plo < Pmid)  \
+      ++Phi;  \
+  }
+#endif
+
+#if !defined(MP_ASSEMBLY_SQUARE)
+/* Add the squares of the digits of a to the digits of b. */
+void s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
+{
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_MUL_WORD)
+  mp_word  w;
+  mp_digit d;
+  mp_size  ix;
+
+  w  = 0;
+#define ADD_SQUARE(n) \
+    d = pa[n]; \
+    w += (d * (mp_word)d) + ps[2*n]; \
+    ps[2*n] = ACCUM(w); \
+    w = (w >> DIGIT_BIT) + ps[2*n+1]; \
+    ps[2*n+1] = ACCUM(w); \
+    w = (w >> DIGIT_BIT)
+
+  for (ix = a_len; ix >= 4; ix -= 4) {
+    ADD_SQUARE(0);
+    ADD_SQUARE(1);
+    ADD_SQUARE(2);
+    ADD_SQUARE(3);
+    pa += 4;
+    ps += 8;
+  }
+  if (ix) {
+    ps += 2*ix;
+    pa += ix;
+    switch (ix) {
+    case 3: ADD_SQUARE(-3); /* FALLTHRU */
+    case 2: ADD_SQUARE(-2); /* FALLTHRU */
+    case 1: ADD_SQUARE(-1); /* FALLTHRU */
+    case 0: break;
+    }
+  }
+  while (w) {
+    w += *ps;
+    *ps++ = ACCUM(w);
+    w = (w >> DIGIT_BIT);
+  }
+#else
+  mp_digit carry = 0;
+  while (a_len--) {
+    mp_digit a_i = *pa++;
+    mp_digit a0a0, a1a1;
+
+    MP_SQR_D(a_i, a1a1, a0a0);
+
+    /* here a1a1 and a0a0 constitute a_i ** 2 */
+    a0a0 += carry;
+    if (a0a0 < carry)
+      ++a1a1;
+
+    /* now add to ps */
+    a0a0 += a_i = *ps;
+    if (a0a0 < a_i)
+      ++a1a1;
+    *ps++ = a0a0;
+    a1a1 += a_i = *ps;
+    carry = (a1a1 < a_i);
+    *ps++ = a1a1;
+  }
+  while (carry) {
+    mp_digit s_i = *ps;
+    carry += s_i;
+    *ps++ = carry;
+    carry = carry < s_i;
+  }
+#endif
+}
+#endif
+
+#if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) \
+&& !defined(MP_ASSEMBLY_DIV_2DX1D)
+/*
+** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
+** so its high bit is 1.   This code is from NSPR.
+*/
+mp_err s_mpv_div_2dx1d(mp_digit Nhi, mp_digit Nlo, mp_digit divisor,
+                       mp_digit *qp, mp_digit *rp)
+{
+    mp_digit d1, d0, q1, q0;
+    mp_digit r1, r0, m;
+
+    d1 = divisor >> MP_HALF_DIGIT_BIT;
+    d0 = divisor & MP_HALF_DIGIT_MAX;
+    r1 = Nhi % d1;
+    q1 = Nhi / d1;
+    m = q1 * d0;
+    r1 = (r1 << MP_HALF_DIGIT_BIT) | (Nlo >> MP_HALF_DIGIT_BIT);
+    if (r1 < m) {
+        q1--, r1 += divisor;
+        if (r1 >= divisor && r1 < m) {
+            q1--, r1 += divisor;
+        }
+    }
+    r1 -= m;
+    r0 = r1 % d1;
+    q0 = r1 / d1;
+    m = q0 * d0;
+    r0 = (r0 << MP_HALF_DIGIT_BIT) | (Nlo & MP_HALF_DIGIT_MAX);
+    if (r0 < m) {
+        q0--, r0 += divisor;
+        if (r0 >= divisor && r0 < m) {
+            q0--, r0 += divisor;
+        }
+    }
+    if (qp)
+        *qp = (q1 << MP_HALF_DIGIT_BIT) | q0;
+    if (rp)
+        *rp = r0 - m;
+    return MP_OKAY;
+}
+#endif
+
+#if MP_SQUARE
+/* {{{ s_mp_sqr(a) */
+
+mp_err   s_mp_sqr(mp_int *a)
+{
+  mp_err   res;
+  mp_int   tmp;
+
+  if((res = mp_init_size(&tmp, 2 * USED(a), FLAG(a))) != MP_OKAY)
+    return res;
+  res = mp_sqr(a, &tmp);
+  if (res == MP_OKAY) {
+    s_mp_exch(&tmp, a);
+  }
+  mp_clear(&tmp);
+  return res;
+}
+
+/* }}} */
+#endif
+
+/* {{{ s_mp_div(a, b) */
+
+/*
+  s_mp_div(a, b)
+
+  Compute a = a / b and b = a mod b.  Assumes b > a.
+ */
+
+mp_err   s_mp_div(mp_int *rem,  /* i: dividend, o: remainder */
+                  mp_int *div,  /* i: divisor                */
+                  mp_int *quot) /* i: 0;        o: quotient  */
+{
+  mp_int   part, t;
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
+  mp_word  q_msd;
+#else
+  mp_digit q_msd;
+#endif
+  mp_err   res;
+  mp_digit d;
+  mp_digit div_msd;
+  int      ix;
+
+  if(mp_cmp_z(div) == 0)
+    return MP_RANGE;
+
+  /* Shortcut if divisor is power of two */
+  if((ix = s_mp_ispow2(div)) >= 0) {
+    MP_CHECKOK( mp_copy(rem, quot) );
+    s_mp_div_2d(quot, (mp_digit)ix);
+    s_mp_mod_2d(rem,  (mp_digit)ix);
+
+    return MP_OKAY;
+  }
+
+  DIGITS(&t) = 0;
+  MP_SIGN(rem) = ZPOS;
+  MP_SIGN(div) = ZPOS;
+
+  /* A working temporary for division     */
+  MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem), FLAG(rem)));
+
+  /* Normalize to optimize guessing       */
+  MP_CHECKOK( s_mp_norm(rem, div, &d) );
+
+  part = *rem;
+
+  /* Perform the division itself...woo!   */
+  MP_USED(quot) = MP_ALLOC(quot);
+
+  /* Find a partial substring of rem which is at least div */
+  /* If we didn't find one, we're finished dividing    */
+  while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) {
+    int i;
+    int unusedRem;
+
+    unusedRem = MP_USED(rem) - MP_USED(div);
+    MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem;
+    MP_ALLOC(&part)  = MP_ALLOC(rem)  - unusedRem;
+    MP_USED(&part)   = MP_USED(div);
+    if (s_mp_cmp(&part, div) < 0) {
+      -- unusedRem;
+#if MP_ARGCHK == 2
+      assert(unusedRem >= 0);
+#endif
+      -- MP_DIGITS(&part);
+      ++ MP_USED(&part);
+      ++ MP_ALLOC(&part);
+    }
+
+    /* Compute a guess for the next quotient digit       */
+    q_msd = MP_DIGIT(&part, MP_USED(&part) - 1);
+    div_msd = MP_DIGIT(div, MP_USED(div) - 1);
+    if (q_msd >= div_msd) {
+      q_msd = 1;
+    } else if (MP_USED(&part) > 1) {
+#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
+      q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
+      q_msd /= div_msd;
+      if (q_msd == RADIX)
+        --q_msd;
+#else
+      mp_digit r;
+      MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
+                                  div_msd, &q_msd, &r) );
+#endif
+    } else {
+      q_msd = 0;
+    }
+#if MP_ARGCHK == 2
+    assert(q_msd > 0); /* This case should never occur any more. */
+#endif
+    if (q_msd <= 0)
+      break;
+
+    /* See what that multiplies out to                   */
+    mp_copy(div, &t);
+    MP_CHECKOK( s_mp_mul_d(&t, (mp_digit)q_msd) );
+
+    /*
+       If it's too big, back it off.  We should not have to do this
+       more than once, or, in rare cases, twice.  Knuth describes a
+       method by which this could be reduced to a maximum of once, but
+       I didn't implement that here.
+     * When using s_mpv_div_2dx1d, we may have to do this 3 times.
+     */
+    for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) {
+      --q_msd;
+      s_mp_sub(&t, div);        /* t -= div */
+    }
+    if (i < 0) {
+      res = MP_RANGE;
+      goto CLEANUP;
+    }
+
+    /* At this point, q_msd should be the right next digit   */
+    MP_CHECKOK( s_mp_sub(&part, &t) );  /* part -= t */
+    s_mp_clamp(rem);
+
+    /*
+      Include the digit in the quotient.  We allocated enough memory
+      for any quotient we could ever possibly get, so we should not
+      have to check for failures here
+     */
+    MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd;
+  }
+
+  /* Denormalize remainder                */
+  if (d) {
+    s_mp_div_2d(rem, d);
+  }
+
+  s_mp_clamp(quot);
+
+CLEANUP:
+  mp_clear(&t);
+
+  return res;
+
+} /* end s_mp_div() */
+
+
+/* }}} */
+
+/* {{{ s_mp_2expt(a, k) */
+
+mp_err   s_mp_2expt(mp_int *a, mp_digit k)
+{
+  mp_err    res;
+  mp_size   dig, bit;
+
+  dig = k / DIGIT_BIT;
+  bit = k % DIGIT_BIT;
+
+  mp_zero(a);
+  if((res = s_mp_pad(a, dig + 1)) != MP_OKAY)
+    return res;
+
+  DIGIT(a, dig) |= ((mp_digit)1 << bit);
+
+  return MP_OKAY;
+
+} /* end s_mp_2expt() */
+
+/* }}} */
+
+/* {{{ s_mp_reduce(x, m, mu) */
+
+/*
+  Compute Barrett reduction, x (mod m), given a precomputed value for
+  mu = b^2k / m, where b = RADIX and k = #digits(m).  This should be
+  faster than straight division, when many reductions by the same
+  value of m are required (such as in modular exponentiation).  This
+  can nearly halve the time required to do modular exponentiation,
+  as compared to using the full integer divide to reduce.
+
+  This algorithm was derived from the _Handbook of Applied
+  Cryptography_ by Menezes, Oorschot and VanStone, Ch. 14,
+  pp. 603-604.
+ */
+
+mp_err   s_mp_reduce(mp_int *x, const mp_int *m, const mp_int *mu)
+{
+  mp_int   q;
+  mp_err   res;
+
+  if((res = mp_init_copy(&q, x)) != MP_OKAY)
+    return res;
+
+  s_mp_rshd(&q, USED(m) - 1);  /* q1 = x / b^(k-1)  */
+  s_mp_mul(&q, mu);            /* q2 = q1 * mu      */
+  s_mp_rshd(&q, USED(m) + 1);  /* q3 = q2 / b^(k+1) */
+
+  /* x = x mod b^(k+1), quick (no division) */
+  s_mp_mod_2d(x, DIGIT_BIT * (USED(m) + 1));
+
+  /* q = q * m mod b^(k+1), quick (no division) */
+  s_mp_mul(&q, m);
+  s_mp_mod_2d(&q, DIGIT_BIT * (USED(m) + 1));
+
+  /* x = x - q */
+  if((res = mp_sub(x, &q, x)) != MP_OKAY)
+    goto CLEANUP;
+
+  /* If x < 0, add b^(k+1) to it */
+  if(mp_cmp_z(x) < 0) {
+    mp_set(&q, 1);
+    if((res = s_mp_lshd(&q, USED(m) + 1)) != MP_OKAY)
+      goto CLEANUP;
+    if((res = mp_add(x, &q, x)) != MP_OKAY)
+      goto CLEANUP;
+  }
+
+  /* Back off if it's too big */
+  while(mp_cmp(x, m) >= 0) {
+    if((res = s_mp_sub(x, m)) != MP_OKAY)
+      break;
+  }
+
+ CLEANUP:
+  mp_clear(&q);
+
+  return res;
+
+} /* end s_mp_reduce() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive comparisons */
+
+/* {{{ s_mp_cmp(a, b) */
+
+/* Compare |a| <=> |b|, return 0 if equal, <0 if a<b, >0 if a>b           */
+int      s_mp_cmp(const mp_int *a, const mp_int *b)
+{
+  mp_size used_a = MP_USED(a);
+  {
+    mp_size used_b = MP_USED(b);
+
+    if (used_a > used_b)
+      goto IS_GT;
+    if (used_a < used_b)
+      goto IS_LT;
+  }
+  {
+    mp_digit *pa, *pb;
+    mp_digit da = 0, db = 0;
+
+#define CMP_AB(n) if ((da = pa[n]) != (db = pb[n])) goto done
+
+    pa = MP_DIGITS(a) + used_a;
+    pb = MP_DIGITS(b) + used_a;
+    while (used_a >= 4) {
+      pa     -= 4;
+      pb     -= 4;
+      used_a -= 4;
+      CMP_AB(3);
+      CMP_AB(2);
+      CMP_AB(1);
+      CMP_AB(0);
+    }
+    while (used_a-- > 0 && ((da = *--pa) == (db = *--pb)))
+      /* do nothing */;
+done:
+    if (da > db)
+      goto IS_GT;
+    if (da < db)
+      goto IS_LT;
+  }
+  return MP_EQ;
+IS_LT:
+  return MP_LT;
+IS_GT:
+  return MP_GT;
+} /* end s_mp_cmp() */
+
+/* }}} */
+
+/* {{{ s_mp_cmp_d(a, d) */
+
+/* Compare |a| <=> d, return 0 if equal, <0 if a<d, >0 if a>d             */
+int      s_mp_cmp_d(const mp_int *a, mp_digit d)
+{
+  if(USED(a) > 1)
+    return MP_GT;
+
+  if(DIGIT(a, 0) < d)
+    return MP_LT;
+  else if(DIGIT(a, 0) > d)
+    return MP_GT;
+  else
+    return MP_EQ;
+
+} /* end s_mp_cmp_d() */
+
+/* }}} */
+
+/* {{{ s_mp_ispow2(v) */
+
+/*
+  Returns -1 if the value is not a power of two; otherwise, it returns
+  k such that v = 2^k, i.e. lg(v).
+ */
+int      s_mp_ispow2(const mp_int *v)
+{
+  mp_digit d;
+  int      extra = 0, ix;
+
+  ix = MP_USED(v) - 1;
+  d = MP_DIGIT(v, ix); /* most significant digit of v */
+
+  extra = s_mp_ispow2d(d);
+  if (extra < 0 || ix == 0)
+    return extra;
+
+  while (--ix >= 0) {
+    if (DIGIT(v, ix) != 0)
+      return -1; /* not a power of two */
+    extra += MP_DIGIT_BIT;
+  }
+
+  return extra;
+
+} /* end s_mp_ispow2() */
+
+/* }}} */
+
+/* {{{ s_mp_ispow2d(d) */
+
+int      s_mp_ispow2d(mp_digit d)
+{
+  if ((d != 0) && ((d & (d-1)) == 0)) { /* d is a power of 2 */
+    int pow = 0;
+#if defined (MP_USE_UINT_DIGIT)
+    if (d & 0xffff0000U)
+      pow += 16;
+    if (d & 0xff00ff00U)
+      pow += 8;
+    if (d & 0xf0f0f0f0U)
+      pow += 4;
+    if (d & 0xccccccccU)
+      pow += 2;
+    if (d & 0xaaaaaaaaU)
+      pow += 1;
+#elif defined(MP_USE_LONG_LONG_DIGIT)
+    if (d & 0xffffffff00000000ULL)
+      pow += 32;
+    if (d & 0xffff0000ffff0000ULL)
+      pow += 16;
+    if (d & 0xff00ff00ff00ff00ULL)
+      pow += 8;
+    if (d & 0xf0f0f0f0f0f0f0f0ULL)
+      pow += 4;
+    if (d & 0xccccccccccccccccULL)
+      pow += 2;
+    if (d & 0xaaaaaaaaaaaaaaaaULL)
+      pow += 1;
+#elif defined(MP_USE_LONG_DIGIT)
+    if (d & 0xffffffff00000000UL)
+      pow += 32;
+    if (d & 0xffff0000ffff0000UL)
+      pow += 16;
+    if (d & 0xff00ff00ff00ff00UL)
+      pow += 8;
+    if (d & 0xf0f0f0f0f0f0f0f0UL)
+      pow += 4;
+    if (d & 0xccccccccccccccccUL)
+      pow += 2;
+    if (d & 0xaaaaaaaaaaaaaaaaUL)
+      pow += 1;
+#else
+#error "unknown type for mp_digit"
+#endif
+    return pow;
+  }
+  return -1;
+
+} /* end s_mp_ispow2d() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ Primitive I/O helpers */
+
+/* {{{ s_mp_tovalue(ch, r) */
+
+/*
+  Convert the given character to its digit value, in the given radix.
+  If the given character is not understood in the given radix, -1 is
+  returned.  Otherwise the digit's numeric value is returned.
+
+  The results will be odd if you use a radix < 2 or > 62, you are
+  expected to know what you're up to.
+ */
+int      s_mp_tovalue(char ch, int r)
+{
+  int    val, xch;
+
+  if(r > 36)
+    xch = ch;
+  else
+    xch = toupper(ch);
+
+  if(isdigit(xch))
+    val = xch - '0';
+  else if(isupper(xch))
+    val = xch - 'A' + 10;
+  else if(islower(xch))
+    val = xch - 'a' + 36;
+  else if(xch == '+')
+    val = 62;
+  else if(xch == '/')
+    val = 63;
+  else
+    return -1;
+
+  if(val < 0 || val >= r)
+    return -1;
+
+  return val;
+
+} /* end s_mp_tovalue() */
+
+/* }}} */
+
+/* {{{ s_mp_todigit(val, r, low) */
+
+/*
+  Convert val to a radix-r digit, if possible.  If val is out of range
+  for r, returns zero.  Otherwise, returns an ASCII character denoting
+  the value in the given radix.
+
+  The results may be odd if you use a radix < 2 or > 64, you are
+  expected to know what you're doing.
+ */
+
+char     s_mp_todigit(mp_digit val, int r, int low)
+{
+  char   ch;
+
+  if(val >= r)
+    return 0;
+
+  ch = s_dmap_1[val];
+
+  if(r <= 36 && low)
+    ch = tolower(ch);
+
+  return ch;
+
+} /* end s_mp_todigit() */
+
+/* }}} */
+
+/* {{{ s_mp_outlen(bits, radix) */
+
+/*
+   Return an estimate for how long a string is needed to hold a radix
+   r representation of a number with 'bits' significant bits, plus an
+   extra for a zero terminator (assuming C style strings here)
+ */
+int      s_mp_outlen(int bits, int r)
+{
+  return (int)((double)bits * LOG_V_2(r) + 1.5) + 1;
+
+} /* end s_mp_outlen() */
+
+/* }}} */
+
+/* }}} */
+
+/* {{{ mp_read_unsigned_octets(mp, str, len) */
+/* mp_read_unsigned_octets(mp, str, len)
+   Read in a raw value (base 256) into the given mp_int
+   No sign bit, number is positive.  Leading zeros ignored.
+ */
+
+mp_err
+mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len)
+{
+  int            count;
+  mp_err         res;
+  mp_digit       d;
+
+  ARGCHK(mp != NULL && str != NULL && len > 0, MP_BADARG);
+
+  mp_zero(mp);
+
+  count = len % sizeof(mp_digit);
+  if (count) {
+    for (d = 0; count-- > 0; --len) {
+      d = (d << 8) | *str++;
+    }
+    MP_DIGIT(mp, 0) = d;
+  }
+
+  /* Read the rest of the digits */
+  for(; len > 0; len -= sizeof(mp_digit)) {
+    for (d = 0, count = sizeof(mp_digit); count > 0; --count) {
+      d = (d << 8) | *str++;
+    }
+    if (MP_EQ == mp_cmp_z(mp)) {
+      if (!d)
+        continue;
+    } else {
+      if((res = s_mp_lshd(mp, 1)) != MP_OKAY)
+        return res;
+    }
+    MP_DIGIT(mp, 0) = d;
+  }
+  return MP_OKAY;
+} /* end mp_read_unsigned_octets() */
+/* }}} */
+
+/* {{{ mp_unsigned_octet_size(mp) */
+int
+mp_unsigned_octet_size(const mp_int *mp)
+{
+  int  bytes;
+  int  ix;
+  mp_digit  d = 0;
+
+  ARGCHK(mp != NULL, MP_BADARG);
+  ARGCHK(MP_ZPOS == SIGN(mp), MP_BADARG);
+
+  bytes = (USED(mp) * sizeof(mp_digit));
+
+  /* subtract leading zeros. */
+  /* Iterate over each digit... */
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    d = DIGIT(mp, ix);
+    if (d)
+        break;
+    bytes -= sizeof(d);
+  }
+  if (!bytes)
+    return 1;
+
+  /* Have MSD, check digit bytes, high order first */
+  for(ix = sizeof(mp_digit) - 1; ix >= 0; ix--) {
+    unsigned char x = (unsigned char)(d >> (ix * CHAR_BIT));
+    if (x)
+        break;
+    --bytes;
+  }
+  return bytes;
+} /* end mp_unsigned_octet_size() */
+/* }}} */
+
+/* {{{ mp_to_unsigned_octets(mp, str) */
+/* output a buffer of big endian octets no longer than specified. */
+mp_err
+mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
+{
+  int  ix, pos = 0;
+  int  bytes;
+
+  ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
+
+  bytes = mp_unsigned_octet_size(mp);
+  ARGCHK(bytes <= maxlen, MP_BADARG);
+
+  /* Iterate over each digit... */
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    mp_digit  d = DIGIT(mp, ix);
+    int       jx;
+
+    /* Unpack digit bytes, high order first */
+    for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
+      unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
+      if (!pos && !x)   /* suppress leading zeros */
+        continue;
+      str[pos++] = x;
+    }
+  }
+  if (!pos)
+    str[pos++] = 0;
+  return pos;
+} /* end mp_to_unsigned_octets() */
+/* }}} */
+
+/* {{{ mp_to_signed_octets(mp, str) */
+/* output a buffer of big endian octets no longer than specified. */
+mp_err
+mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen)
+{
+  int  ix, pos = 0;
+  int  bytes;
+
+  ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
+
+  bytes = mp_unsigned_octet_size(mp);
+  ARGCHK(bytes <= maxlen, MP_BADARG);
+
+  /* Iterate over each digit... */
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    mp_digit  d = DIGIT(mp, ix);
+    int       jx;
+
+    /* Unpack digit bytes, high order first */
+    for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
+      unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
+      if (!pos) {
+        if (!x)         /* suppress leading zeros */
+          continue;
+        if (x & 0x80) { /* add one leading zero to make output positive.  */
+          ARGCHK(bytes + 1 <= maxlen, MP_BADARG);
+          if (bytes + 1 > maxlen)
+            return MP_BADARG;
+          str[pos++] = 0;
+        }
+      }
+      str[pos++] = x;
+    }
+  }
+  if (!pos)
+    str[pos++] = 0;
+  return pos;
+} /* end mp_to_signed_octets() */
+/* }}} */
+
+/* {{{ mp_to_fixlen_octets(mp, str) */
+/* output a buffer of big endian octets exactly as long as requested. */
+mp_err
+mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size length)
+{
+  int  ix, pos = 0;
+  int  bytes;
+
+  ARGCHK(mp != NULL && str != NULL && !SIGN(mp), MP_BADARG);
+
+  bytes = mp_unsigned_octet_size(mp);
+  ARGCHK(bytes <= length, MP_BADARG);
+
+  /* place any needed leading zeros */
+  for (;length > bytes; --length) {
+        *str++ = 0;
+  }
+
+  /* Iterate over each digit... */
+  for(ix = USED(mp) - 1; ix >= 0; ix--) {
+    mp_digit  d = DIGIT(mp, ix);
+    int       jx;
+
+    /* Unpack digit bytes, high order first */
+    for(jx = sizeof(mp_digit) - 1; jx >= 0; jx--) {
+      unsigned char x = (unsigned char)(d >> (jx * CHAR_BIT));
+      if (!pos && !x)   /* suppress leading zeros */
+        continue;
+      str[pos++] = x;
+    }
+  }
+  if (!pos)
+    str[pos++] = 0;
+  return MP_OKAY;
+} /* end mp_to_fixlen_octets() */
+/* }}} */
+
+
+/*------------------------------------------------------------------------*/
+/* HERE THERE BE DRAGONS                                                  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mpi.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,409 @@
+/* *********************************************************************
+ *
+ * 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:
+ *
+ *
+ *  Arbitrary precision integer arithmetic library
+ *
+ * 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Netscape Communications Corporation
+ *
+ * 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 _MPI_H
+#define _MPI_H
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+/* $Id: mpi.h,v 1.22 2004/04/27 23:04:36 gerv%gerv.net Exp $ */
+
+#include "mpi-config.h"
+
+#ifndef _WIN32
+#include <sys/param.h>
+#endif /* _WIN32 */
+
+#ifdef _KERNEL
+#include <sys/debug.h>
+#include <sys/systm.h>
+#define assert ASSERT
+#define labs(a) (a >= 0 ? a : -a)
+#define UCHAR_MAX 255
+#define memset(s, c, n) bzero(s, n)
+#define memcpy(a,b,c) bcopy((caddr_t)b, (caddr_t)a, c)
+/*
+ * Generic #define's to cover missing things in the kernel
+ */
+#ifndef isdigit
+#define isdigit(x)      ((x) >= '0' && (x) <= '9')
+#endif
+#ifndef isupper
+#define isupper(x)      (((unsigned)(x) >= 'A') && ((unsigned)(x) <= 'Z'))
+#endif
+#ifndef islower
+#define islower(x)      (((unsigned)(x) >= 'a') && ((unsigned)(x) <= 'z'))
+#endif
+#ifndef isalpha
+#define isalpha(x)      (isupper(x) || islower(x))
+#endif
+#ifndef toupper
+#define toupper(x)      (islower(x) ? (x) - 'a' + 'A' : (x))
+#endif
+#ifndef tolower
+#define tolower(x)      (isupper(x) ? (x) + 'a' - 'A' : (x))
+#endif
+#ifndef isspace
+#define isspace(x)      (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \
+                         ((x) == '\t') || ((x) == '\b'))
+#endif
+#endif /* _KERNEL */
+
+#if MP_DEBUG
+#undef MP_IOFUNC
+#define MP_IOFUNC 1
+#endif
+
+#if MP_IOFUNC
+#include <stdio.h>
+#include <ctype.h>
+#endif
+
+#ifndef _KERNEL
+#include <limits.h>
+#endif
+
+#if defined(BSDI)
+#undef ULLONG_MAX
+#endif
+
+#if defined( macintosh )
+#include <Types.h>
+#elif defined( _WIN32_WCE)
+/* #include <sys/types.h> What do we need here ?? */
+#else
+#include <sys/types.h>
+#endif
+
+#define  MP_NEG    1
+#define  MP_ZPOS   0
+
+#define  MP_OKAY          0 /* no error, all is well */
+#define  MP_YES           0 /* yes (boolean result)  */
+#define  MP_NO           -1 /* no (boolean result)   */
+#define  MP_MEM          -2 /* out of memory         */
+#define  MP_RANGE        -3 /* argument out of range */
+#define  MP_BADARG       -4 /* invalid parameter     */
+#define  MP_UNDEF        -5 /* answer is undefined   */
+#define  MP_LAST_CODE    MP_UNDEF
+
+typedef unsigned int      mp_sign;
+typedef unsigned int      mp_size;
+typedef int               mp_err;
+typedef int               mp_flag;
+
+#define MP_32BIT_MAX 4294967295U
+
+#if !defined(ULONG_MAX)
+#error "ULONG_MAX not defined"
+#elif !defined(UINT_MAX)
+#error "UINT_MAX not defined"
+#elif !defined(USHRT_MAX)
+#error "USHRT_MAX not defined"
+#endif
+
+#if defined(ULONG_LONG_MAX)                     /* GCC, HPUX */
+#define MP_ULONG_LONG_MAX ULONG_LONG_MAX
+#elif defined(ULLONG_MAX)                       /* Solaris */
+#define MP_ULONG_LONG_MAX ULLONG_MAX
+/* MP_ULONG_LONG_MAX was defined to be ULLONG_MAX */
+#elif defined(ULONGLONG_MAX)                    /* IRIX, AIX */
+#define MP_ULONG_LONG_MAX ULONGLONG_MAX
+#endif
+
+/* We only use unsigned long for mp_digit iff long is more than 32 bits. */
+#if !defined(MP_USE_UINT_DIGIT) && ULONG_MAX > MP_32BIT_MAX
+typedef unsigned long     mp_digit;
+#define MP_DIGIT_MAX      ULONG_MAX
+#define MP_DIGIT_FMT      "%016lX"   /* printf() format for 1 digit */
+#define MP_HALF_DIGIT_MAX UINT_MAX
+#undef  MP_NO_MP_WORD
+#define MP_NO_MP_WORD 1
+#undef  MP_USE_LONG_DIGIT
+#define MP_USE_LONG_DIGIT 1
+#undef  MP_USE_LONG_LONG_DIGIT
+
+#elif !defined(MP_USE_UINT_DIGIT) && defined(MP_ULONG_LONG_MAX)
+typedef unsigned long long mp_digit;
+#define MP_DIGIT_MAX       MP_ULONG_LONG_MAX
+#define MP_DIGIT_FMT      "%016llX"  /* printf() format for 1 digit */
+#define MP_HALF_DIGIT_MAX  UINT_MAX
+#undef  MP_NO_MP_WORD
+#define MP_NO_MP_WORD 1
+#undef  MP_USE_LONG_LONG_DIGIT
+#define MP_USE_LONG_LONG_DIGIT 1
+#undef  MP_USE_LONG_DIGIT
+
+#else
+typedef unsigned int      mp_digit;
+#define MP_DIGIT_MAX      UINT_MAX
+#define MP_DIGIT_FMT      "%08X"     /* printf() format for 1 digit */
+#define MP_HALF_DIGIT_MAX USHRT_MAX
+#undef  MP_USE_UINT_DIGIT
+#define MP_USE_UINT_DIGIT 1
+#undef  MP_USE_LONG_LONG_DIGIT
+#undef  MP_USE_LONG_DIGIT
+#endif
+
+#if !defined(MP_NO_MP_WORD)
+#if  defined(MP_USE_UINT_DIGIT) && \
+    (defined(MP_ULONG_LONG_MAX) || (ULONG_MAX > UINT_MAX))
+
+#if (ULONG_MAX > UINT_MAX)
+typedef unsigned long     mp_word;
+typedef          long     mp_sword;
+#define MP_WORD_MAX       ULONG_MAX
+
+#else
+typedef unsigned long long mp_word;
+typedef          long long mp_sword;
+#define MP_WORD_MAX       MP_ULONG_LONG_MAX
+#endif
+
+#else
+#define MP_NO_MP_WORD 1
+#endif
+#endif /* !defined(MP_NO_MP_WORD) */
+
+#if !defined(MP_WORD_MAX) && defined(MP_DEFINE_SMALL_WORD)
+typedef unsigned int      mp_word;
+typedef          int      mp_sword;
+#define MP_WORD_MAX       UINT_MAX
+#endif
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#define MP_DIGIT_BIT      (CHAR_BIT*sizeof(mp_digit))
+#define MP_WORD_BIT       (CHAR_BIT*sizeof(mp_word))
+#define MP_RADIX          (1+(mp_word)MP_DIGIT_MAX)
+
+#define MP_HALF_DIGIT_BIT (MP_DIGIT_BIT/2)
+#define MP_HALF_RADIX     (1+(mp_digit)MP_HALF_DIGIT_MAX)
+/* MP_HALF_RADIX really ought to be called MP_SQRT_RADIX, but it's named
+** MP_HALF_RADIX because it's the radix for MP_HALF_DIGITs, and it's
+** consistent with the other _HALF_ names.
+*/
+
+
+/* Macros for accessing the mp_int internals           */
+#define  MP_FLAG(MP)     ((MP)->flag)
+#define  MP_SIGN(MP)     ((MP)->sign)
+#define  MP_USED(MP)     ((MP)->used)
+#define  MP_ALLOC(MP)    ((MP)->alloc)
+#define  MP_DIGITS(MP)   ((MP)->dp)
+#define  MP_DIGIT(MP,N)  (MP)->dp[(N)]
+
+/* This defines the maximum I/O base (minimum is 2)   */
+#define MP_MAX_RADIX         64
+
+typedef struct {
+  mp_sign       flag;    /* KM_SLEEP/KM_NOSLEEP        */
+  mp_sign       sign;    /* sign of this quantity      */
+  mp_size       alloc;   /* how many digits allocated  */
+  mp_size       used;    /* how many digits used       */
+  mp_digit     *dp;      /* the digits themselves      */
+} mp_int;
+
+/* Default precision       */
+mp_size mp_get_prec(void);
+void    mp_set_prec(mp_size prec);
+
+/* Memory management       */
+mp_err mp_init(mp_int *mp, int kmflag);
+mp_err mp_init_size(mp_int *mp, mp_size prec, int kmflag);
+mp_err mp_init_copy(mp_int *mp, const mp_int *from);
+mp_err mp_copy(const mp_int *from, mp_int *to);
+void   mp_exch(mp_int *mp1, mp_int *mp2);
+void   mp_clear(mp_int *mp);
+void   mp_zero(mp_int *mp);
+void   mp_set(mp_int *mp, mp_digit d);
+mp_err mp_set_int(mp_int *mp, long z);
+#define mp_set_long(mp,z) mp_set_int(mp,z)
+mp_err mp_set_ulong(mp_int *mp, unsigned long z);
+
+/* Single digit arithmetic */
+mp_err mp_add_d(const mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_sub_d(const mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_mul_d(const mp_int *a, mp_digit d, mp_int *b);
+mp_err mp_mul_2(const mp_int *a, mp_int *c);
+mp_err mp_div_d(const mp_int *a, mp_digit d, mp_int *q, mp_digit *r);
+mp_err mp_div_2(const mp_int *a, mp_int *c);
+mp_err mp_expt_d(const mp_int *a, mp_digit d, mp_int *c);
+
+/* Sign manipulations      */
+mp_err mp_abs(const mp_int *a, mp_int *b);
+mp_err mp_neg(const mp_int *a, mp_int *b);
+
+/* Full arithmetic         */
+mp_err mp_add(const mp_int *a, const mp_int *b, mp_int *c);
+mp_err mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
+mp_err mp_mul(const mp_int *a, const mp_int *b, mp_int *c);
+#if MP_SQUARE
+mp_err mp_sqr(const mp_int *a, mp_int *b);
+#else
+#define mp_sqr(a, b) mp_mul(a, a, b)
+#endif
+mp_err mp_div(const mp_int *a, const mp_int *b, mp_int *q, mp_int *r);
+mp_err mp_div_2d(const mp_int *a, mp_digit d, mp_int *q, mp_int *r);
+mp_err mp_expt(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_2expt(mp_int *a, mp_digit k);
+mp_err mp_sqrt(const mp_int *a, mp_int *b);
+
+/* Modular arithmetic      */
+#if MP_MODARITH
+mp_err mp_mod(const mp_int *a, const mp_int *m, mp_int *c);
+mp_err mp_mod_d(const mp_int *a, mp_digit d, mp_digit *c);
+mp_err mp_addmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
+mp_err mp_submod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
+mp_err mp_mulmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
+#if MP_SQUARE
+mp_err mp_sqrmod(const mp_int *a, const mp_int *m, mp_int *c);
+#else
+#define mp_sqrmod(a, m, c) mp_mulmod(a, a, m, c)
+#endif
+mp_err mp_exptmod(const mp_int *a, const mp_int *b, const mp_int *m, mp_int *c);
+mp_err mp_exptmod_d(const mp_int *a, mp_digit d, const mp_int *m, mp_int *c);
+#endif /* MP_MODARITH */
+
+/* Comparisons             */
+int    mp_cmp_z(const mp_int *a);
+int    mp_cmp_d(const mp_int *a, mp_digit d);
+int    mp_cmp(const mp_int *a, const mp_int *b);
+int    mp_cmp_mag(mp_int *a, mp_int *b);
+int    mp_cmp_int(const mp_int *a, long z, int kmflag);
+int    mp_isodd(const mp_int *a);
+int    mp_iseven(const mp_int *a);
+
+/* Number theoretic        */
+#if MP_NUMTH
+mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
+mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
+mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
+mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
+#endif /* end MP_NUMTH */
+
+/* Input and output        */
+#if MP_IOFUNC
+void   mp_print(mp_int *mp, FILE *ofp);
+#endif /* end MP_IOFUNC */
+
+/* Base conversion         */
+mp_err mp_read_raw(mp_int *mp, char *str, int len);
+int    mp_raw_size(mp_int *mp);
+mp_err mp_toraw(mp_int *mp, char *str);
+mp_err mp_read_radix(mp_int *mp, const char *str, int radix);
+mp_err mp_read_variable_radix(mp_int *a, const char * str, int default_radix);
+int    mp_radix_size(mp_int *mp, int radix);
+mp_err mp_toradix(mp_int *mp, char *str, int radix);
+int    mp_tovalue(char ch, int r);
+
+#define mp_tobinary(M, S)  mp_toradix((M), (S), 2)
+#define mp_tooctal(M, S)   mp_toradix((M), (S), 8)
+#define mp_todecimal(M, S) mp_toradix((M), (S), 10)
+#define mp_tohex(M, S)     mp_toradix((M), (S), 16)
+
+/* Error strings           */
+const  char  *mp_strerror(mp_err ec);
+
+/* Octet string conversion functions */
+mp_err mp_read_unsigned_octets(mp_int *mp, const unsigned char *str, mp_size len);
+int    mp_unsigned_octet_size(const mp_int *mp);
+mp_err mp_to_unsigned_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
+mp_err mp_to_signed_octets(const mp_int *mp, unsigned char *str, mp_size maxlen);
+mp_err mp_to_fixlen_octets(const mp_int *mp, unsigned char *str, mp_size len);
+
+/* Miscellaneous */
+mp_size mp_trailing_zeros(const mp_int *mp);
+
+#define MP_CHECKOK(x)  if (MP_OKAY > (res = (x))) goto CLEANUP
+#define MP_CHECKERR(x) if (MP_OKAY > (res = (x))) goto CLEANUP
+
+#if defined(MP_API_COMPATIBLE)
+#define NEG             MP_NEG
+#define ZPOS            MP_ZPOS
+#define DIGIT_MAX       MP_DIGIT_MAX
+#define DIGIT_BIT       MP_DIGIT_BIT
+#define DIGIT_FMT       MP_DIGIT_FMT
+#define RADIX           MP_RADIX
+#define MAX_RADIX       MP_MAX_RADIX
+#define FLAG(MP)        MP_FLAG(MP)
+#define SIGN(MP)        MP_SIGN(MP)
+#define USED(MP)        MP_USED(MP)
+#define ALLOC(MP)       MP_ALLOC(MP)
+#define DIGITS(MP)      MP_DIGITS(MP)
+#define DIGIT(MP,N)     MP_DIGIT(MP,N)
+
+#if MP_ARGCHK == 1
+#define  ARGCHK(X,Y)  {if(!(X)){return (Y);}}
+#elif MP_ARGCHK == 2
+#ifdef _KERNEL
+#define  ARGCHK(X,Y)  ASSERT(X)
+#else
+#include <assert.h>
+#define  ARGCHK(X,Y)  assert(X)
+#endif
+#else
+#define  ARGCHK(X,Y)  /*  */
+#endif
+#endif /* defined MP_API_COMPATIBLE */
+
+#endif /* _MPI_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mplogic.c	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,242 @@
+/* *********************************************************************
+ *
+ * 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:
+ *
+ *
+ *  Bitwise logical operations on MPI values
+ *
+ * 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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"
+
+/* $Id: mplogic.c,v 1.15 2004/04/27 23:04:36 gerv%gerv.net Exp $ */
+
+#include "mpi-priv.h"
+#include "mplogic.h"
+
+/* {{{ Lookup table for population count */
+
+static unsigned char bitc[] = {
+   0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+   1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+   1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+   2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+   1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+   2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+   2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+   3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+   1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+   2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+   2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+   3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+   2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+   3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+   3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+   4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+/* }}} */
+
+/*
+  mpl_rsh(a, b, d)     - b = a >> d
+  mpl_lsh(a, b, d)     - b = a << d
+ */
+
+/* {{{ mpl_rsh(a, b, d) */
+
+mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  s_mp_div_2d(b, d);
+
+  return MP_OKAY;
+
+} /* end mpl_rsh() */
+
+/* }}} */
+
+/* {{{ mpl_lsh(a, b, d) */
+
+mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d)
+{
+  mp_err   res;
+
+  ARGCHK(a != NULL && b != NULL, MP_BADARG);
+
+  if((res = mp_copy(a, b)) != MP_OKAY)
+    return res;
+
+  return s_mp_mul_2d(b, d);
+
+} /* end mpl_lsh() */
+
+/* }}} */
+
+/*------------------------------------------------------------------------*/
+/*
+  mpl_set_bit
+
+  Returns MP_OKAY or some error code.
+  Grows a if needed to set a bit to 1.
+ */
+mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value)
+{
+  mp_size      ix;
+  mp_err       rv;
+  mp_digit     mask;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  ix = bitNum / MP_DIGIT_BIT;
+  if (ix + 1 > MP_USED(a)) {
+    rv = s_mp_pad(a, ix + 1);
+    if (rv != MP_OKAY)
+      return rv;
+  }
+
+  bitNum = bitNum % MP_DIGIT_BIT;
+  mask = (mp_digit)1 << bitNum;
+  if (value)
+    MP_DIGIT(a,ix) |= mask;
+  else
+    MP_DIGIT(a,ix) &= ~mask;
+  s_mp_clamp(a);
+  return MP_OKAY;
+}
+
+/*
+  mpl_get_bit
+
+  returns 0 or 1 or some (negative) error code.
+ */
+mp_err mpl_get_bit(const mp_int *a, mp_size bitNum)
+{
+  mp_size      bit, ix;
+  mp_err       rv;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  ix = bitNum / MP_DIGIT_BIT;
+  ARGCHK(ix <= MP_USED(a) - 1, MP_RANGE);
+
+  bit   = bitNum % MP_DIGIT_BIT;
+  rv = (mp_err)(MP_DIGIT(a, ix) >> bit) & 1;
+  return rv;
+}
+
+/*
+  mpl_get_bits
+  - Extracts numBits bits from a, where the least significant extracted bit
+  is bit lsbNum.  Returns a negative value if error occurs.
+  - Because sign bit is used to indicate error, maximum number of bits to
+  be returned is the lesser of (a) the number of bits in an mp_digit, or
+  (b) one less than the number of bits in an mp_err.
+  - lsbNum + numbits can be greater than the number of significant bits in
+  integer a, as long as bit lsbNum is in the high order digit of a.
+ */
+mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits)
+{
+  mp_size    rshift = (lsbNum % MP_DIGIT_BIT);
+  mp_size    lsWndx = (lsbNum / MP_DIGIT_BIT);
+  mp_digit * digit  = MP_DIGITS(a) + lsWndx;
+  mp_digit   mask   = ((1 << numBits) - 1);
+
+  ARGCHK(numBits < CHAR_BIT * sizeof mask, MP_BADARG);
+  ARGCHK(MP_HOWMANY(lsbNum, MP_DIGIT_BIT) <= MP_USED(a), MP_RANGE);
+
+  if ((numBits + lsbNum % MP_DIGIT_BIT <= MP_DIGIT_BIT) ||
+      (lsWndx + 1 >= MP_USED(a))) {
+    mask &= (digit[0] >> rshift);
+  } else {
+    mask &= ((digit[0] >> rshift) | (digit[1] << (MP_DIGIT_BIT - rshift)));
+  }
+  return (mp_err)mask;
+}
+
+/*
+  mpl_significant_bits
+  returns number of significnant bits in abs(a).
+  returns 1 if value is zero.
+ */
+mp_err mpl_significant_bits(const mp_int *a)
+{
+  mp_err bits   = 0;
+  int    ix;
+
+  ARGCHK(a != NULL, MP_BADARG);
+
+  ix = MP_USED(a);
+  for (ix = MP_USED(a); ix > 0; ) {
+    mp_digit d;
+    d = MP_DIGIT(a, --ix);
+    if (d) {
+      while (d) {
+        ++bits;
+        d >>= 1;
+      }
+      break;
+    }
+  }
+  bits += ix * MP_DIGIT_BIT;
+  if (!bits)
+    bits = 1;
+  return bits;
+}
+
+/*------------------------------------------------------------------------*/
+/* HERE THERE BE DRAGONS                                                  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mplogic.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,105 @@
+/* *********************************************************************
+ *
+ * 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:
+ *
+ *
+ *  Bitwise logical operations on MPI values
+ *
+ * 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 _MPLOGIC_H
+#define _MPLOGIC_H
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+/* $Id: mplogic.h,v 1.7 2004/04/27 23:04:36 gerv%gerv.net Exp $ */
+
+#include "mpi.h"
+
+/*
+  The logical operations treat an mp_int as if it were a bit vector,
+  without regard to its sign (an mp_int is represented in a signed
+  magnitude format).  Values are treated as if they had an infinite
+  string of zeros left of the most-significant bit.
+ */
+
+/* Parity results                    */
+
+#define MP_EVEN       MP_YES
+#define MP_ODD        MP_NO
+
+/* Bitwise functions                 */
+
+mp_err mpl_not(mp_int *a, mp_int *b);            /* one's complement  */
+mp_err mpl_and(mp_int *a, mp_int *b, mp_int *c); /* bitwise AND       */
+mp_err mpl_or(mp_int *a, mp_int *b, mp_int *c);  /* bitwise OR        */
+mp_err mpl_xor(mp_int *a, mp_int *b, mp_int *c); /* bitwise XOR       */
+
+/* Shift functions                   */
+
+mp_err mpl_rsh(const mp_int *a, mp_int *b, mp_digit d);   /* right shift    */
+mp_err mpl_lsh(const mp_int *a, mp_int *b, mp_digit d);   /* left shift     */
+
+/* Bit count and parity              */
+
+mp_err mpl_num_set(mp_int *a, int *num);         /* count set bits    */
+mp_err mpl_num_clear(mp_int *a, int *num);       /* count clear bits  */
+mp_err mpl_parity(mp_int *a);                    /* determine parity  */
+
+/* Get & Set the value of a bit */
+
+mp_err mpl_set_bit(mp_int *a, mp_size bitNum, mp_size value);
+mp_err mpl_get_bit(const mp_int *a, mp_size bitNum);
+mp_err mpl_get_bits(const mp_int *a, mp_size lsbNum, mp_size numBits);
+mp_err mpl_significant_bits(const mp_int *a);
+
+#endif /* _MPLOGIC_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mpmontg.c	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,199 @@
+/* *********************************************************************
+ *
+ * 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) 2000
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Sheueling Chang Shantz <sheueling.chang@sun.com>,
+ *   Stephen Fung <stephen.fung@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"
+
+/* $Id: mpmontg.c,v 1.20 2006/08/29 02:41:38 nelson%bolyard.com Exp $ */
+
+/* This file implements moduluar exponentiation using Montgomery's
+ * method for modular reduction.  This file implements the method
+ * described as "Improvement 1" in the paper "A Cryptogrpahic Library for
+ * the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr.
+ * published in "Advances in Cryptology: Proceedings of EUROCRYPT '90"
+ * "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244,
+ * published by Springer Verlag.
+ */
+
+#define MP_USING_CACHE_SAFE_MOD_EXP 1
+#ifndef _KERNEL
+#include <string.h>
+#include <stddef.h> /* ptrdiff_t */
+#endif
+#include "mpi-priv.h"
+#include "mplogic.h"
+#include "mpprime.h"
+#ifdef MP_USING_MONT_MULF
+#include "montmulf.h"
+#endif
+
+/* if MP_CHAR_STORE_SLOW is defined, we  */
+/* need to know endianness of this platform. */
+#ifdef MP_CHAR_STORE_SLOW
+#if !defined(MP_IS_BIG_ENDIAN) && !defined(MP_IS_LITTLE_ENDIAN)
+#error "You must define MP_IS_BIG_ENDIAN or MP_IS_LITTLE_ENDIAN\n" \
+       "  if you define MP_CHAR_STORE_SLOW."
+#endif
+#endif
+
+#ifndef STATIC
+#define STATIC
+#endif
+
+#define MAX_ODD_INTS    32   /* 2 ** (WINDOW_BITS - 1) */
+
+#ifndef _KERNEL
+#if defined(_WIN32_WCE)
+#define ABORT  res = MP_UNDEF; goto CLEANUP
+#else
+#define ABORT abort()
+#endif
+#else
+#define ABORT  res = MP_UNDEF; goto CLEANUP
+#endif /* _KERNEL */
+
+/* computes T = REDC(T), 2^b == R */
+mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm)
+{
+  mp_err res;
+  mp_size i;
+
+  i = MP_USED(T) + MP_USED(&mmm->N) + 2;
+  MP_CHECKOK( s_mp_pad(T, i) );
+  for (i = 0; i < MP_USED(&mmm->N); ++i ) {
+    mp_digit m_i = MP_DIGIT(T, i) * mmm->n0prime;
+    /* T += N * m_i * (MP_RADIX ** i); */
+    MP_CHECKOK( s_mp_mul_d_add_offset(&mmm->N, m_i, T, i) );
+  }
+  s_mp_clamp(T);
+
+  /* T /= R */
+  s_mp_div_2d(T, mmm->b);
+
+  if ((res = s_mp_cmp(T, &mmm->N)) >= 0) {
+    /* T = T - N */
+    MP_CHECKOK( s_mp_sub(T, &mmm->N) );
+#ifdef DEBUG
+    if ((res = mp_cmp(T, &mmm->N)) >= 0) {
+      res = MP_UNDEF;
+      goto CLEANUP;
+    }
+#endif
+  }
+  res = MP_OKAY;
+CLEANUP:
+  return res;
+}
+
+#if !defined(MP_ASSEMBLY_MUL_MONT) && !defined(MP_MONT_USE_MP_MUL)
+mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
+                   mp_mont_modulus *mmm)
+{
+  mp_digit *pb;
+  mp_digit m_i;
+  mp_err   res;
+  mp_size  ib;
+  mp_size  useda, usedb;
+
+  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
+
+  if (MP_USED(a) < MP_USED(b)) {
+    const mp_int *xch = b;      /* switch a and b, to do fewer outer loops */
+    b = a;
+    a = xch;
+  }
+
+  MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
+  ib = MP_USED(a) + MP_MAX(MP_USED(b), MP_USED(&mmm->N)) + 2;
+  if((res = s_mp_pad(c, ib)) != MP_OKAY)
+    goto CLEANUP;
+
+  useda = MP_USED(a);
+  pb = MP_DIGITS(b);
+  s_mpv_mul_d(MP_DIGITS(a), useda, *pb++, MP_DIGITS(c));
+  s_mp_setz(MP_DIGITS(c) + useda + 1, ib - (useda + 1));
+  m_i = MP_DIGIT(c, 0) * mmm->n0prime;
+  s_mp_mul_d_add_offset(&mmm->N, m_i, c, 0);
+
+  /* Outer loop:  Digits of b */
+  usedb = MP_USED(b);
+  for (ib = 1; ib < usedb; ib++) {
+    mp_digit b_i    = *pb++;
+
+    /* Inner product:  Digits of a */
+    if (b_i)
+      s_mpv_mul_d_add_prop(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
+    m_i = MP_DIGIT(c, ib) * mmm->n0prime;
+    s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
+  }
+  if (usedb < MP_USED(&mmm->N)) {
+    for (usedb = MP_USED(&mmm->N); ib < usedb; ++ib ) {
+      m_i = MP_DIGIT(c, ib) * mmm->n0prime;
+      s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
+    }
+  }
+  s_mp_clamp(c);
+  s_mp_div_2d(c, mmm->b);
+  if (s_mp_cmp(c, &mmm->N) >= 0) {
+    MP_CHECKOK( s_mp_sub(c, &mmm->N) );
+  }
+  res = MP_OKAY;
+
+CLEANUP:
+  return res;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/mpprime.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,89 @@
+/* *********************************************************************
+ *
+ * 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:
+ *
+ *
+ *  Utilities for finding and working with prime and pseudo-prime
+ *  integers
+ *
+ * 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 MPI Arbitrary Precision Integer Arithmetic library.
+ *
+ * The Initial Developer of the Original Code is
+ * Michael J. Fromberger.
+ * Portions created by the Initial Developer are Copyright (C) 1997
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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_PRIME_H
+#define _MP_PRIME_H
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+#include "mpi.h"
+
+extern const int prime_tab_size;   /* number of primes available */
+extern const mp_digit prime_tab[];
+
+/* Tests for divisibility    */
+mp_err  mpp_divis(mp_int *a, mp_int *b);
+mp_err  mpp_divis_d(mp_int *a, mp_digit d);
+
+/* Random selection          */
+mp_err  mpp_random(mp_int *a);
+mp_err  mpp_random_size(mp_int *a, mp_size prec);
+
+/* Pseudo-primality testing  */
+mp_err  mpp_divis_vector(mp_int *a, const mp_digit *vec, int size, int *which);
+mp_err  mpp_divis_primes(mp_int *a, mp_digit *np);
+mp_err  mpp_fermat(mp_int *a, mp_digit w);
+mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes);
+mp_err  mpp_pprime(mp_int *a, int nt);
+mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
+                 unsigned char *sieve, mp_size nSieve);
+mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
+                      unsigned long * nTries);
+
+#endif /* _MP_PRIME_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/oid.c	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,473 @@
+/* *********************************************************************
+ *
+ * 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.
+ */
+
+#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"
+#include "secoidt.h"
+
+#define CERTICOM_OID            0x2b, 0x81, 0x04
+#define SECG_OID                CERTICOM_OID, 0x00
+
+#define ANSI_X962_OID           0x2a, 0x86, 0x48, 0xce, 0x3d
+#define ANSI_X962_CURVE_OID     ANSI_X962_OID, 0x03
+#define ANSI_X962_GF2m_OID      ANSI_X962_CURVE_OID, 0x00
+#define ANSI_X962_GFp_OID       ANSI_X962_CURVE_OID, 0x01
+
+#define CONST_OID static const unsigned char
+
+/* ANSI X9.62 prime curve OIDs */
+/* NOTE: prime192v1 is the same as secp192r1, prime256v1 is the
+ * same as secp256r1
+ */
+CONST_OID ansiX962prime192v1[] = { ANSI_X962_GFp_OID, 0x01 };
+CONST_OID ansiX962prime192v2[] = { ANSI_X962_GFp_OID, 0x02 };
+CONST_OID ansiX962prime192v3[] = { ANSI_X962_GFp_OID, 0x03 };
+CONST_OID ansiX962prime239v1[] = { ANSI_X962_GFp_OID, 0x04 };
+CONST_OID ansiX962prime239v2[] = { ANSI_X962_GFp_OID, 0x05 };
+CONST_OID ansiX962prime239v3[] = { ANSI_X962_GFp_OID, 0x06 };
+CONST_OID ansiX962prime256v1[] = { ANSI_X962_GFp_OID, 0x07 };
+
+/* SECG prime curve OIDs */
+CONST_OID secgECsecp112r1[] = { SECG_OID, 0x06 };
+CONST_OID secgECsecp112r2[] = { SECG_OID, 0x07 };
+CONST_OID secgECsecp128r1[] = { SECG_OID, 0x1c };
+CONST_OID secgECsecp128r2[] = { SECG_OID, 0x1d };
+CONST_OID secgECsecp160k1[] = { SECG_OID, 0x09 };
+CONST_OID secgECsecp160r1[] = { SECG_OID, 0x08 };
+CONST_OID secgECsecp160r2[] = { SECG_OID, 0x1e };
+CONST_OID secgECsecp192k1[] = { SECG_OID, 0x1f };
+CONST_OID secgECsecp224k1[] = { SECG_OID, 0x20 };
+CONST_OID secgECsecp224r1[] = { SECG_OID, 0x21 };
+CONST_OID secgECsecp256k1[] = { SECG_OID, 0x0a };
+CONST_OID secgECsecp384r1[] = { SECG_OID, 0x22 };
+CONST_OID secgECsecp521r1[] = { SECG_OID, 0x23 };
+
+/* SECG characterisitic two curve OIDs */
+CONST_OID secgECsect113r1[] = {SECG_OID, 0x04 };
+CONST_OID secgECsect113r2[] = {SECG_OID, 0x05 };
+CONST_OID secgECsect131r1[] = {SECG_OID, 0x16 };
+CONST_OID secgECsect131r2[] = {SECG_OID, 0x17 };
+CONST_OID secgECsect163k1[] = {SECG_OID, 0x01 };
+CONST_OID secgECsect163r1[] = {SECG_OID, 0x02 };
+CONST_OID secgECsect163r2[] = {SECG_OID, 0x0f };
+CONST_OID secgECsect193r1[] = {SECG_OID, 0x18 };
+CONST_OID secgECsect193r2[] = {SECG_OID, 0x19 };
+CONST_OID secgECsect233k1[] = {SECG_OID, 0x1a };
+CONST_OID secgECsect233r1[] = {SECG_OID, 0x1b };
+CONST_OID secgECsect239k1[] = {SECG_OID, 0x03 };
+CONST_OID secgECsect283k1[] = {SECG_OID, 0x10 };
+CONST_OID secgECsect283r1[] = {SECG_OID, 0x11 };
+CONST_OID secgECsect409k1[] = {SECG_OID, 0x24 };
+CONST_OID secgECsect409r1[] = {SECG_OID, 0x25 };
+CONST_OID secgECsect571k1[] = {SECG_OID, 0x26 };
+CONST_OID secgECsect571r1[] = {SECG_OID, 0x27 };
+
+/* ANSI X9.62 characteristic two curve OIDs */
+CONST_OID ansiX962c2pnb163v1[] = { ANSI_X962_GF2m_OID, 0x01 };
+CONST_OID ansiX962c2pnb163v2[] = { ANSI_X962_GF2m_OID, 0x02 };
+CONST_OID ansiX962c2pnb163v3[] = { ANSI_X962_GF2m_OID, 0x03 };
+CONST_OID ansiX962c2pnb176v1[] = { ANSI_X962_GF2m_OID, 0x04 };
+CONST_OID ansiX962c2tnb191v1[] = { ANSI_X962_GF2m_OID, 0x05 };
+CONST_OID ansiX962c2tnb191v2[] = { ANSI_X962_GF2m_OID, 0x06 };
+CONST_OID ansiX962c2tnb191v3[] = { ANSI_X962_GF2m_OID, 0x07 };
+CONST_OID ansiX962c2onb191v4[] = { ANSI_X962_GF2m_OID, 0x08 };
+CONST_OID ansiX962c2onb191v5[] = { ANSI_X962_GF2m_OID, 0x09 };
+CONST_OID ansiX962c2pnb208w1[] = { ANSI_X962_GF2m_OID, 0x0a };
+CONST_OID ansiX962c2tnb239v1[] = { ANSI_X962_GF2m_OID, 0x0b };
+CONST_OID ansiX962c2tnb239v2[] = { ANSI_X962_GF2m_OID, 0x0c };
+CONST_OID ansiX962c2tnb239v3[] = { ANSI_X962_GF2m_OID, 0x0d };
+CONST_OID ansiX962c2onb239v4[] = { ANSI_X962_GF2m_OID, 0x0e };
+CONST_OID ansiX962c2onb239v5[] = { ANSI_X962_GF2m_OID, 0x0f };
+CONST_OID ansiX962c2pnb272w1[] = { ANSI_X962_GF2m_OID, 0x10 };
+CONST_OID ansiX962c2pnb304w1[] = { ANSI_X962_GF2m_OID, 0x11 };
+CONST_OID ansiX962c2tnb359v1[] = { ANSI_X962_GF2m_OID, 0x12 };
+CONST_OID ansiX962c2pnb368w1[] = { ANSI_X962_GF2m_OID, 0x13 };
+CONST_OID ansiX962c2tnb431r1[] = { ANSI_X962_GF2m_OID, 0x14 };
+
+#define OI(x) { siDEROID, (unsigned char *)x, sizeof x }
+#ifndef SECOID_NO_STRINGS
+#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, desc, mech, ext }
+#else
+#define OD(oid,tag,desc,mech,ext) { OI(oid), tag, 0, mech, ext }
+#endif
+
+#define CKM_INVALID_MECHANISM 0xffffffffUL
+
+/* XXX this is incorrect */
+#define INVALID_CERT_EXTENSION 1
+
+#define CKM_ECDSA                      0x00001041
+#define CKM_ECDSA_SHA1                 0x00001042
+#define CKM_ECDH1_DERIVE               0x00001050
+
+static SECOidData ANSI_prime_oids[] = {
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+
+    OD( ansiX962prime192v1, ECCurve_NIST_P192,
+        "ANSI X9.62 elliptic curve prime192v1 (aka secp192r1, NIST P-192)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962prime192v2, ECCurve_X9_62_PRIME_192V2,
+        "ANSI X9.62 elliptic curve prime192v2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962prime192v3, ECCurve_X9_62_PRIME_192V3,
+        "ANSI X9.62 elliptic curve prime192v3",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962prime239v1, ECCurve_X9_62_PRIME_239V1,
+        "ANSI X9.62 elliptic curve prime239v1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962prime239v2, ECCurve_X9_62_PRIME_239V2,
+        "ANSI X9.62 elliptic curve prime239v2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962prime239v3, ECCurve_X9_62_PRIME_239V3,
+        "ANSI X9.62 elliptic curve prime239v3",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962prime256v1, ECCurve_NIST_P256,
+        "ANSI X9.62 elliptic curve prime256v1 (aka secp256r1, NIST P-256)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION )
+};
+
+static SECOidData SECG_oids[] = {
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+
+    OD( secgECsect163k1, ECCurve_NIST_K163,
+        "SECG elliptic curve sect163k1 (aka NIST K-163)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect163r1, ECCurve_SECG_CHAR2_163R1,
+        "SECG elliptic curve sect163r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect239k1, ECCurve_SECG_CHAR2_239K1,
+        "SECG elliptic curve sect239k1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect113r1, ECCurve_SECG_CHAR2_113R1,
+        "SECG elliptic curve sect113r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect113r2, ECCurve_SECG_CHAR2_113R2,
+        "SECG elliptic curve sect113r2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp112r1, ECCurve_SECG_PRIME_112R1,
+        "SECG elliptic curve secp112r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp112r2, ECCurve_SECG_PRIME_112R2,
+        "SECG elliptic curve secp112r2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp160r1, ECCurve_SECG_PRIME_160R1,
+        "SECG elliptic curve secp160r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp160k1, ECCurve_SECG_PRIME_160K1,
+        "SECG elliptic curve secp160k1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp256k1, ECCurve_SECG_PRIME_256K1,
+        "SECG elliptic curve secp256k1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( secgECsect163r2, ECCurve_NIST_B163,
+        "SECG elliptic curve sect163r2 (aka NIST B-163)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect283k1, ECCurve_NIST_K283,
+        "SECG elliptic curve sect283k1 (aka NIST K-283)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect283r1, ECCurve_NIST_B283,
+        "SECG elliptic curve sect283r1 (aka NIST B-283)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( secgECsect131r1, ECCurve_SECG_CHAR2_131R1,
+        "SECG elliptic curve sect131r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect131r2, ECCurve_SECG_CHAR2_131R2,
+        "SECG elliptic curve sect131r2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect193r1, ECCurve_SECG_CHAR2_193R1,
+        "SECG elliptic curve sect193r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect193r2, ECCurve_SECG_CHAR2_193R2,
+        "SECG elliptic curve sect193r2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect233k1, ECCurve_NIST_K233,
+        "SECG elliptic curve sect233k1 (aka NIST K-233)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect233r1, ECCurve_NIST_B233,
+        "SECG elliptic curve sect233r1 (aka NIST B-233)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp128r1, ECCurve_SECG_PRIME_128R1,
+        "SECG elliptic curve secp128r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp128r2, ECCurve_SECG_PRIME_128R2,
+        "SECG elliptic curve secp128r2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp160r2, ECCurve_SECG_PRIME_160R2,
+        "SECG elliptic curve secp160r2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp192k1, ECCurve_SECG_PRIME_192K1,
+        "SECG elliptic curve secp192k1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp224k1, ECCurve_SECG_PRIME_224K1,
+        "SECG elliptic curve secp224k1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp224r1, ECCurve_NIST_P224,
+        "SECG elliptic curve secp224r1 (aka NIST P-224)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp384r1, ECCurve_NIST_P384,
+        "SECG elliptic curve secp384r1 (aka NIST P-384)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsecp521r1, ECCurve_NIST_P521,
+        "SECG elliptic curve secp521r1 (aka NIST P-521)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect409k1, ECCurve_NIST_K409,
+        "SECG elliptic curve sect409k1 (aka NIST K-409)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect409r1, ECCurve_NIST_B409,
+        "SECG elliptic curve sect409r1 (aka NIST B-409)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect571k1, ECCurve_NIST_K571,
+        "SECG elliptic curve sect571k1 (aka NIST K-571)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( secgECsect571r1, ECCurve_NIST_B571,
+        "SECG elliptic curve sect571r1 (aka NIST B-571)",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION )
+};
+
+static SECOidData ANSI_oids[] = {
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+
+    /* ANSI X9.62 named elliptic curves (characteristic two field) */
+    OD( ansiX962c2pnb163v1, ECCurve_X9_62_CHAR2_PNB163V1,
+        "ANSI X9.62 elliptic curve c2pnb163v1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2pnb163v2, ECCurve_X9_62_CHAR2_PNB163V2,
+        "ANSI X9.62 elliptic curve c2pnb163v2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2pnb163v3, ECCurve_X9_62_CHAR2_PNB163V3,
+        "ANSI X9.62 elliptic curve c2pnb163v3",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2pnb176v1, ECCurve_X9_62_CHAR2_PNB176V1,
+        "ANSI X9.62 elliptic curve c2pnb176v1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb191v1, ECCurve_X9_62_CHAR2_TNB191V1,
+        "ANSI X9.62 elliptic curve c2tnb191v1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb191v2, ECCurve_X9_62_CHAR2_TNB191V2,
+        "ANSI X9.62 elliptic curve c2tnb191v2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb191v3, ECCurve_X9_62_CHAR2_TNB191V3,
+        "ANSI X9.62 elliptic curve c2tnb191v3",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( ansiX962c2pnb208w1, ECCurve_X9_62_CHAR2_PNB208W1,
+        "ANSI X9.62 elliptic curve c2pnb208w1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb239v1, ECCurve_X9_62_CHAR2_TNB239V1,
+        "ANSI X9.62 elliptic curve c2tnb239v1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb239v2, ECCurve_X9_62_CHAR2_TNB239V2,
+        "ANSI X9.62 elliptic curve c2tnb239v2",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb239v3, ECCurve_X9_62_CHAR2_TNB239V3,
+        "ANSI X9.62 elliptic curve c2tnb239v3",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    { { siDEROID, NULL, 0 }, ECCurve_noName,
+        "Unknown OID", CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION },
+    OD( ansiX962c2pnb272w1, ECCurve_X9_62_CHAR2_PNB272W1,
+        "ANSI X9.62 elliptic curve c2pnb272w1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2pnb304w1, ECCurve_X9_62_CHAR2_PNB304W1,
+        "ANSI X9.62 elliptic curve c2pnb304w1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb359v1, ECCurve_X9_62_CHAR2_TNB359V1,
+        "ANSI X9.62 elliptic curve c2tnb359v1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2pnb368w1, ECCurve_X9_62_CHAR2_PNB368W1,
+        "ANSI X9.62 elliptic curve c2pnb368w1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION ),
+    OD( ansiX962c2tnb431r1, ECCurve_X9_62_CHAR2_TNB431R1,
+        "ANSI X9.62 elliptic curve c2tnb431r1",
+        CKM_INVALID_MECHANISM,
+        INVALID_CERT_EXTENSION )
+};
+
+SECOidData *
+SECOID_FindOID(const SECItem *oid)
+{
+    SECOidData *po;
+    SECOidData *ret;
+    int i;
+
+    if (oid->len == 8) {
+        if (oid->data[6] == 0x00) {
+                /* XXX bounds check */
+                po = &ANSI_oids[oid->data[7]];
+                if (memcmp(oid->data, po->oid.data, 8) == 0)
+                        ret = po;
+        }
+        if (oid->data[6] == 0x01) {
+                /* XXX bounds check */
+                po = &ANSI_prime_oids[oid->data[7]];
+                if (memcmp(oid->data, po->oid.data, 8) == 0)
+                        ret = po;
+        }
+    } else if (oid->len == 5) {
+        /* XXX bounds check */
+        po = &SECG_oids[oid->data[4]];
+        if (memcmp(oid->data, po->oid.data, 5) == 0)
+                ret = po;
+    } else {
+        ret = NULL;
+    }
+    return(ret);
+}
+
+ECCurveName
+SECOID_FindOIDTag(const SECItem *oid)
+{
+    SECOidData *oiddata;
+
+    oiddata = SECOID_FindOID (oid);
+    if (oiddata == NULL)
+        return ECCurve_noName;
+
+    return oiddata->offset;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/secitem.c	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,199 @@
+/* *********************************************************************
+ *
+ * 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):
+ *
+ * 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"
+
+/*
+ * Support routines for SECItem data structure.
+ *
+ * $Id: secitem.c,v 1.14 2006/05/22 22:24:34 wtchang%redhat.com Exp $
+ */
+
+#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>
+
+#ifndef _WIN32
+#include <strings.h>
+#endif /* _WIN32 */
+
+#include <assert.h>
+#endif
+#include "ec.h"
+#include "ecl-curve.h"
+#include "ecc_impl.h"
+
+void SECITEM_FreeItem(SECItem *, PRBool);
+
+SECItem *
+SECITEM_AllocItem(PRArenaPool *arena, SECItem *item, unsigned int len,
+    int kmflag)
+{
+    SECItem *result = NULL;
+    void *mark = NULL;
+
+    if (arena != NULL) {
+        mark = PORT_ArenaMark(arena);
+    }
+
+    if (item == NULL) {
+        if (arena != NULL) {
+            result = PORT_ArenaZAlloc(arena, sizeof(SECItem), kmflag);
+        } else {
+            result = PORT_ZAlloc(sizeof(SECItem), kmflag);
+        }
+        if (result == NULL) {
+            goto loser;
+        }
+    } else {
+        PORT_Assert(item->data == NULL);
+        result = item;
+    }
+
+    result->len = len;
+    if (len) {
+        if (arena != NULL) {
+            result->data = PORT_ArenaAlloc(arena, len, kmflag);
+        } else {
+            result->data = PORT_Alloc(len, kmflag);
+        }
+        if (result->data == NULL) {
+            goto loser;
+        }
+    } else {
+        result->data = NULL;
+    }
+
+    if (mark) {
+        PORT_ArenaUnmark(arena, mark);
+    }
+    return(result);
+
+loser:
+    if ( arena != NULL ) {
+        if (mark) {
+            PORT_ArenaRelease(arena, mark);
+        }
+        if (item != NULL) {
+            item->data = NULL;
+            item->len = 0;
+        }
+    } else {
+        if (result != NULL) {
+            SECITEM_FreeItem(result, (item == NULL) ? PR_TRUE : PR_FALSE);
+        }
+        /*
+         * If item is not NULL, the above has set item->data and
+         * item->len to 0.
+         */
+    }
+    return(NULL);
+}
+
+SECStatus
+SECITEM_CopyItem(PRArenaPool *arena, SECItem *to, const SECItem *from,
+   int kmflag)
+{
+    to->type = from->type;
+    if (from->data && from->len) {
+        if ( arena ) {
+            to->data = (unsigned char*) PORT_ArenaAlloc(arena, from->len,
+                kmflag);
+        } else {
+            to->data = (unsigned char*) PORT_Alloc(from->len, kmflag);
+        }
+
+        if (!to->data) {
+            return SECFailure;
+        }
+        PORT_Memcpy(to->data, from->data, from->len);
+        to->len = from->len;
+    } else {
+        to->data = 0;
+        to->len = 0;
+    }
+    return SECSuccess;
+}
+
+void
+SECITEM_FreeItem(SECItem *zap, PRBool freeit)
+{
+    if (zap) {
+#ifdef _KERNEL
+        kmem_free(zap->data, zap->len);
+#else
+        free(zap->data);
+#endif
+        zap->data = 0;
+        zap->len = 0;
+        if (freeit) {
+#ifdef _KERNEL
+            kmem_free(zap, sizeof (SECItem));
+#else
+            free(zap);
+#endif
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/native/sun/security/ec/secoidt.h	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,103 @@
+/* *********************************************************************
+ *
+ * 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 _SECOIDT_H_
+#define _SECOIDT_H_
+
+#pragma ident   "%Z%%M% %I%     %E% SMI"
+
+/*
+ * secoidt.h - public data structures for ASN.1 OID functions
+ *
+ * $Id: secoidt.h,v 1.23 2007/05/05 22:45:16 nelson%bolyard.com Exp $
+ */
+
+typedef struct SECOidDataStr SECOidData;
+typedef struct SECAlgorithmIDStr SECAlgorithmID;
+
+/*
+** An X.500 algorithm identifier
+*/
+struct SECAlgorithmIDStr {
+    SECItem algorithm;
+    SECItem parameters;
+};
+
+#define SEC_OID_SECG_EC_SECP192R1 SEC_OID_ANSIX962_EC_PRIME192V1
+#define SEC_OID_SECG_EC_SECP256R1 SEC_OID_ANSIX962_EC_PRIME256V1
+#define SEC_OID_PKCS12_KEY_USAGE  SEC_OID_X509_KEY_USAGE
+
+/* fake OID for DSS sign/verify */
+#define SEC_OID_SHA SEC_OID_MISS_DSS
+
+typedef enum {
+    INVALID_CERT_EXTENSION = 0,
+    UNSUPPORTED_CERT_EXTENSION = 1,
+    SUPPORTED_CERT_EXTENSION = 2
+} SECSupportExtenTag;
+
+struct SECOidDataStr {
+    SECItem            oid;
+    ECCurveName        offset;
+    const char *       desc;
+    unsigned long      mechanism;
+    SECSupportExtenTag supportedExtension;
+                                /* only used for x.509 v3 extensions, so
+                                   that we can print the names of those
+                                   extensions that we don't even support */
+};
+
+#endif /* _SECOIDT_H_ */
--- a/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,12 +25,14 @@
 
 package sun.net.www.protocol.jar;
 
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.zip.ZipFile;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.jar.JarFile;
 import java.security.Permission;
+import sun.net.util.URLUtil;
 
 /* A factory for cached JAR file. This class is used to both retrieve
  * and cache Jar files.
@@ -41,13 +43,13 @@
 class JarFileFactory implements URLJarFile.URLJarFileCloseController {
 
     /* the url to file cache */
-    private static HashMap fileCache = new HashMap();
+    private static HashMap<String, JarFile> fileCache = new HashMap<String, JarFile>();
 
     /* the file to url cache */
-    private static HashMap urlCache = new HashMap();
+    private static HashMap<JarFile, URL> urlCache = new HashMap<JarFile, URL>();
 
     URLConnection getConnection(JarFile jarFile) throws IOException {
-        URL u = (URL)urlCache.get(jarFile);
+        URL u = urlCache.get(jarFile);
         if (u != null)
             return u.openConnection();
 
@@ -72,7 +74,7 @@
                 synchronized (this) {
                     result = getCachedJarFile(url);
                     if (result == null) {
-                        fileCache.put(url, local_result);
+                        fileCache.put(URLUtil.urlNoFragString(url), local_result);
                         urlCache.put(local_result, url);
                         result = local_result;
                     } else {
@@ -97,15 +99,15 @@
      * remove the JarFile from the cache
      */
     public void close(JarFile jarFile) {
-        URL urlRemoved = (URL) urlCache.remove(jarFile);
+        URL urlRemoved = urlCache.remove(jarFile);
         if( urlRemoved != null) {
-                fileCache.remove(urlRemoved);
+                fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
         }
     }
 
 
     private JarFile getCachedJarFile(URL url) {
-        JarFile result = (JarFile)fileCache.get(url);
+        JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
 
         /* if the JAR file is cached, the permission will always be there */
         if (result != null) {
--- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c	Tue Aug 18 19:53:43 2009 -0700
@@ -50,27 +50,72 @@
 #include <limits.h>
 
 /*
- * (Hopefully temporarily) disable the clone-exec feature pending
- * further investigation and bug-fixing.
- * 32-bit (but not 64-bit) Linux fails on the program
- *   Runtime.getRuntime().exec("/bin/true").waitFor();
- * with:
- * #  Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
- * #  Error: pthread_getattr_np failed with errno = 3 (ESRCH)
- * Linux kernel/pthread gurus are invited to figure this out.
+ * There are 3 possible strategies we might use to "fork":
+ *
+ * - fork(2).  Very portable and reliable but subject to
+ *   failure due to overcommit (see the documentation on
+ *   /proc/sys/vm/overcommit_memory in Linux proc(5)).
+ *   This is the ancient problem of spurious failure whenever a large
+ *   process starts a small subprocess.
+ *
+ * - vfork().  Using this is scary because all relevant man pages
+ *   contain dire warnings, e.g. Linux vfork(2).  But at least it's
+ *   documented in the glibc docs and is standardized by XPG4.
+ *   http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html
+ *   On Linux, one might think that vfork() would be implemented using
+ *   the clone system call with flag CLONE_VFORK, but in fact vfork is
+ *   a separate system call (which is a good sign, suggesting that
+ *   vfork will continue to be supported at least on Linux).
+ *   Another good sign is that glibc implements posix_spawn using
+ *   vfork whenever possible.  Note that we cannot use posix_spawn
+ *   ourselves because there's no reliable way to close all inherited
+ *   file descriptors.
+ *
+ * - clone() with flags CLONE_VM but not CLONE_THREAD.  clone() is
+ *   Linux-specific, but this ought to work - at least the glibc
+ *   sources contain code to handle different combinations of CLONE_VM
+ *   and CLONE_THREAD.  However, when this was implemented, it
+ *   appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with
+ *   the simple program
+ *     Runtime.getRuntime().exec("/bin/true").waitFor();
+ *   with:
+ *     #  Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536
+ *     #  Error: pthread_getattr_np failed with errno = 3 (ESRCH)
+ *   We believe this is a glibc bug, reported here:
+ *     http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311
+ *   but the glibc maintainers closed it as WONTFIX.
+ *
+ * Based on the above analysis, we are currently using vfork() on
+ * Linux and fork() on other Unix systems, but the code to use clone()
+ * remains.
  */
-#define USE_CLONE 0
+
+#define START_CHILD_USE_CLONE 0  /* clone() currently disabled; see above. */
 
-#ifndef USE_CLONE
-#ifdef __linux__
-#define USE_CLONE 1
-#else
-#define USE_CLONE 0
-#endif
+#ifndef START_CHILD_USE_CLONE
+  #ifdef __linux__
+    #define START_CHILD_USE_CLONE 1
+  #else
+    #define START_CHILD_USE_CLONE 0
+  #endif
 #endif
 
-#if USE_CLONE
+/* By default, use vfork() on Linux. */
+#ifndef START_CHILD_USE_VFORK
+  #ifdef __linux__
+    #define START_CHILD_USE_VFORK 1
+  #else
+    #define START_CHILD_USE_VFORK 0
+  #endif
+#endif
+
+#if START_CHILD_USE_CLONE
 #include <sched.h>
+#define START_CHILD_SYSTEM_CALL "clone"
+#elif START_CHILD_USE_VFORK
+#define START_CHILD_SYSTEM_CALL "vfork"
+#else
+#define START_CHILD_SYSTEM_CALL "fork"
 #endif
 
 #ifndef STDIN_FILENO
@@ -95,6 +140,27 @@
 
 #define FAIL_FILENO (STDERR_FILENO + 1)
 
+/* TODO: Refactor. */
+#define RESTARTABLE(_cmd, _result) do { \
+  do { \
+    _result = _cmd; \
+  } while((_result == -1) && (errno == EINTR)); \
+} while(0)
+
+/* This is one of the rare times it's more portable to declare an
+ * external symbol explicitly, rather than via a system header.
+ * The declaration is standardized as part of UNIX98, but there is
+ * no standard (not even de-facto) header file where the
+ * declaration is to be found.  See:
+ * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
+ * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
+ *
+ * "All identifiers in this volume of IEEE Std 1003.1-2001, except
+ * environ, are defined in at least one of the headers" (!)
+ */
+extern char **environ;
+
+
 static void
 setSIGCHLDHandler(JNIEnv *env)
 {
@@ -283,6 +349,36 @@
     }
 }
 
+static ssize_t
+restartableWrite(int fd, const void *buf, size_t count)
+{
+    ssize_t result;
+    RESTARTABLE(write(fd, buf, count), result);
+    return result;
+}
+
+static int
+restartableDup2(int fd_from, int fd_to)
+{
+    int err;
+    RESTARTABLE(dup2(fd_from, fd_to), err);
+    return err;
+}
+
+static int
+restartableClose(int fd)
+{
+    int err;
+    RESTARTABLE(close(fd), err);
+    return err;
+}
+
+static int
+closeSafely(int fd)
+{
+    return (fd == -1) ? 0 : restartableClose(fd);
+}
+
 static int
 isAsciiDigit(char c)
 {
@@ -303,8 +399,8 @@
      * the lowest numbered file descriptor, just like open().  So we
      * close a couple explicitly.  */
 
-    close(from_fd);             /* for possible use by opendir() */
-    close(from_fd + 1);         /* another one for good luck */
+    restartableClose(from_fd);          /* for possible use by opendir() */
+    restartableClose(from_fd + 1);      /* another one for good luck */
 
     if ((dp = opendir("/proc/self/fd")) == NULL)
         return 0;
@@ -316,7 +412,7 @@
         int fd;
         if (isAsciiDigit(dirp->d_name[0]) &&
             (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2)
-            close(fd);
+            restartableClose(fd);
     }
 
     closedir(dp);
@@ -324,13 +420,15 @@
     return 1;
 }
 
-static void
+static int
 moveDescriptor(int fd_from, int fd_to)
 {
     if (fd_from != fd_to) {
-        dup2(fd_from, fd_to);
-        close(fd_from);
+        if ((restartableDup2(fd_from, fd_to) == -1) ||
+            (restartableClose(fd_from) == -1))
+            return -1;
     }
+    return 0;
 }
 
 static const char *
@@ -434,41 +532,30 @@
                            const char *argv[],
                            const char *const envp[])
 {
-#if USE_CLONE
+#if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK
+    /* shared address space; be very careful. */
     execve(file, (char **) argv, (char **) envp);
     if (errno == ENOEXEC)
         execve_as_traditional_shell_script(file, argv, envp);
 #else
-    /* Our address space is unshared, so can mutate environ. */
-    extern char **environ;
+    /* unshared address space; we can mutate environ. */
     environ = (char **) envp;
     execvp(file, (char **) argv);
 #endif
 }
 
 /**
- * execvpe should have been included in the Unix standards.
- * execvpe is identical to execvp, except that the child environment is
+ * 'execvpe' should have been included in the Unix standards,
+ * and is a GNU extension in glibc 2.10.
+ *
+ * JDK_execvpe is identical to execvp, except that the child environment is
  * specified via the 3rd argument instead of being inherited from environ.
  */
 static void
-execvpe(const char *file,
-        const char *argv[],
-        const char *const envp[])
+JDK_execvpe(const char *file,
+            const char *argv[],
+            const char *const envp[])
 {
-    /* This is one of the rare times it's more portable to declare an
-     * external symbol explicitly, rather than via a system header.
-     * The declaration is standardized as part of UNIX98, but there is
-     * no standard (not even de-facto) header file where the
-     * declaration is to be found.  See:
-     * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html
-     * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html
-     *
-     * "All identifiers in this volume of IEEE Std 1003.1-2001, except
-     * environ, are defined in at least one of the headers" (!)
-     */
-    extern char **environ;
-
     if (envp == NULL || (char **) envp == environ) {
         execvp(file, (char **) argv);
         return;
@@ -538,13 +625,6 @@
     }
 }
 
-static void
-closeSafely(int fd)
-{
-    if (fd != -1)
-        close(fd);
-}
-
 /*
  * Reads nbyte bytes from file descriptor fd into buf,
  * The read operation is retried in case of EINTR or partial reads.
@@ -587,6 +667,9 @@
     const char **envv;
     const char *pdir;
     jboolean redirectErrorStream;
+#if START_CHILD_USE_CLONE
+    void *clone_stack;
+#endif
 } ChildStuff;
 
 static void
@@ -610,31 +693,40 @@
     /* Close the parent sides of the pipes.
        Closing pipe fds here is redundant, since closeDescriptors()
        would do it anyways, but a little paranoia is a good thing. */
-    closeSafely(p->in[1]);
-    closeSafely(p->out[0]);
-    closeSafely(p->err[0]);
-    closeSafely(p->fail[0]);
+    if ((closeSafely(p->in[1])   == -1) ||
+        (closeSafely(p->out[0])  == -1) ||
+        (closeSafely(p->err[0])  == -1) ||
+        (closeSafely(p->fail[0]) == -1))
+        goto WhyCantJohnnyExec;
 
     /* Give the child sides of the pipes the right fileno's. */
     /* Note: it is possible for in[0] == 0 */
-    moveDescriptor(p->in[0] != -1 ?  p->in[0] : p->fds[0], STDIN_FILENO);
-    moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1], STDOUT_FILENO);
+    if ((moveDescriptor(p->in[0] != -1 ?  p->in[0] : p->fds[0],
+                        STDIN_FILENO) == -1) ||
+        (moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1],
+                        STDOUT_FILENO) == -1))
+        goto WhyCantJohnnyExec;
 
     if (p->redirectErrorStream) {
-      closeSafely(p->err[1]);
-      dup2(STDOUT_FILENO, STDERR_FILENO);
+        if ((closeSafely(p->err[1]) == -1) ||
+            (restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1))
+            goto WhyCantJohnnyExec;
     } else {
-      moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2], STDERR_FILENO);
+        if (moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2],
+                           STDERR_FILENO) == -1)
+            goto WhyCantJohnnyExec;
     }
 
-    moveDescriptor(p->fail[1], FAIL_FILENO);
+    if (moveDescriptor(p->fail[1], FAIL_FILENO) == -1)
+        goto WhyCantJohnnyExec;
 
     /* close everything */
     if (closeDescriptors() == 0) { /* failed,  close the old way */
         int max_fd = (int)sysconf(_SC_OPEN_MAX);
-        int i;
-        for (i = FAIL_FILENO + 1; i < max_fd; i++)
-            close(i);
+        int fd;
+        for (fd = FAIL_FILENO + 1; fd < max_fd; fd++)
+            if (restartableClose(fd) == -1 && errno != EBADF)
+                goto WhyCantJohnnyExec;
     }
 
     /* change to the new working directory */
@@ -644,7 +736,7 @@
     if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1)
         goto WhyCantJohnnyExec;
 
-    execvpe(p->argv[0], p->argv, p->envv);
+    JDK_execvpe(p->argv[0], p->argv, p->envv);
 
  WhyCantJohnnyExec:
     /* We used to go to an awful lot of trouble to predict whether the
@@ -659,13 +751,62 @@
      */
     {
         int errnum = errno;
-        write(FAIL_FILENO, &errnum, sizeof(errnum));
+        restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum));
     }
-    close(FAIL_FILENO);
+    restartableClose(FAIL_FILENO);
     _exit(-1);
     return 0;  /* Suppress warning "no return value from function" */
 }
 
+/**
+ * Start a child process running function childProcess.
+ * This function only returns in the parent.
+ * We are unusually paranoid; use of clone/vfork is
+ * especially likely to tickle gcc/glibc bugs.
+ */
+#ifdef __attribute_noinline__  /* See: sys/cdefs.h */
+__attribute_noinline__
+#endif
+static pid_t
+startChild(ChildStuff *c) {
+#if START_CHILD_USE_CLONE
+#define START_CHILD_CLONE_STACK_SIZE (64 * 1024)
+    /*
+     * See clone(2).
+     * Instead of worrying about which direction the stack grows, just
+     * allocate twice as much and start the stack in the middle.
+     */
+    if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL)
+        /* errno will be set to ENOMEM */
+        return -1;
+    return clone(childProcess,
+                 c->clone_stack + START_CHILD_CLONE_STACK_SIZE,
+                 CLONE_VFORK | CLONE_VM | SIGCHLD, c);
+#else
+  #if START_CHILD_USE_VFORK
+    /*
+     * We separate the call to vfork into a separate function to make
+     * very sure to keep stack of child from corrupting stack of parent,
+     * as suggested by the scary gcc warning:
+     *  warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork'
+     */
+    volatile pid_t resultPid = vfork();
+  #else
+    /*
+     * From Solaris fork(2): In Solaris 10, a call to fork() is
+     * identical to a call to fork1(); only the calling thread is
+     * replicated in the child process. This is the POSIX-specified
+     * behavior for fork().
+     */
+    pid_t resultPid = fork();
+  #endif
+    if (resultPid == 0)
+        childProcess(c);
+    assert(resultPid != 0);  /* childProcess never returns */
+    return resultPid;
+#endif /* ! START_CHILD_USE_CLONE */
+}
+
 JNIEXPORT jint JNICALL
 Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
                                        jobject process,
@@ -678,9 +819,6 @@
 {
     int errnum;
     int resultPid = -1;
-#if USE_CLONE
-    void *clone_stack = NULL;
-#endif
     int in[2], out[2], err[2], fail[2];
     jint *fds = NULL;
     const char *pprog = NULL;
@@ -694,6 +832,9 @@
     c->argv = NULL;
     c->envv = NULL;
     c->pdir = NULL;
+#if START_CHILD_USE_CLONE
+    c->clone_stack = NULL;
+#endif
 
     /* Convert prog + argBlock into a char ** argv.
      * Add one word room for expansion of argv for use by
@@ -739,37 +880,15 @@
 
     c->redirectErrorStream = redirectErrorStream;
 
-    {
-#if USE_CLONE
-        /* See clone(2).
-         * Instead of worrying about which direction the stack grows, just
-         * allocate twice as much and start the stack in the middle. */
-        const int stack_size = 64 * 1024;
-        if ((clone_stack = NEW(char, 2 * stack_size)) == NULL) goto Catch;
-        resultPid = clone(childProcess, clone_stack + stack_size,
-                          /* CLONE_VFORK | // works, but unnecessary */
-                          CLONE_VM | SIGCHLD, c);
-#else
-        /* From fork(2): In Solaris 10, a call to fork() is identical
-         * to a call to fork1(); only the calling thread is replicated
-         * in the child process. This is the POSIX-specified behavior
-         * for fork(). */
-        resultPid = fork();
-        if (resultPid == 0) {
-          childProcess(c);
-          assert(0);  /* childProcess must not return */
-        }
-#endif
-    }
+    resultPid = startChild(c);
+    assert(resultPid != 0);
 
     if (resultPid < 0) {
-        throwIOException(env, errno, "Fork failed");
+        throwIOException(env, errno, START_CHILD_SYSTEM_CALL " failed");
         goto Catch;
     }
 
-    /* parent process */
-
-    close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */
+    restartableClose(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */
 
     switch (readFully(fail[0], &errnum, sizeof(errnum))) {
     case 0: break; /* Exec succeeded */
@@ -787,8 +906,8 @@
     fds[2] = (err[0] != -1) ? err[0] : -1;
 
  Finally:
-#if USE_CLONE
-    free(clone_stack);
+#if START_CHILD_USE_CLONE
+    free(c->clone_stack);
 #endif
 
     /* Always clean up the child's side of the pipes */
--- a/jdk/src/solaris/native/sun/nio/ch/Net.c	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/solaris/native/sun/nio/ch/Net.c	Tue Aug 18 19:53:43 2009 -0700
@@ -541,7 +541,7 @@
 {
     int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD :
         (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR;
-    if (shutdown(fdval(env, fdo), how) < 0)
+    if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN))
         handleSocketError(env, errno);
 }
 
--- a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,12 +25,14 @@
 
 package sun.net.www.protocol.jar;
 
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.jar.*;
-import java.util.zip.ZipFile;
+import java.io.IOException;
+import java.io.FileNotFoundException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.HashMap;
+import java.util.jar.JarFile;
 import java.security.Permission;
+import sun.net.util.URLUtil;
 
 /* A factory for cached JAR file. This class is used to both retrieve
  * and cache Jar files.
@@ -41,13 +43,13 @@
 class JarFileFactory implements URLJarFile.URLJarFileCloseController {
 
     /* the url to file cache */
-    private static HashMap fileCache = new HashMap();
+    private static HashMap<String, JarFile> fileCache = new HashMap<String, JarFile>();
 
     /* the file to url cache */
-    private static HashMap urlCache = new HashMap();
+    private static HashMap<JarFile, URL> urlCache = new HashMap<JarFile, URL>();
 
     URLConnection getConnection(JarFile jarFile) throws IOException {
-        URL u = (URL)urlCache.get(jarFile);
+        URL u = urlCache.get(jarFile);
         if (u != null)
             return u.openConnection();
 
@@ -82,7 +84,7 @@
                 synchronized (this) {
                     result = getCachedJarFile(url);
                     if (result == null) {
-                        fileCache.put(url, local_result);
+                        fileCache.put(URLUtil.urlNoFragString(url), local_result);
                         urlCache.put(local_result, url);
                         result = local_result;
                     } else {
@@ -107,14 +109,14 @@
      * remove the JarFile from the cache
      */
     public void close(JarFile jarFile) {
-        URL urlRemoved = (URL) urlCache.remove(jarFile);
+        URL urlRemoved = urlCache.remove(jarFile);
         if( urlRemoved != null) {
-                fileCache.remove(urlRemoved);
+                fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
         }
     }
 
     private JarFile getCachedJarFile(URL url) {
-        JarFile result = (JarFile)fileCache.get(url);
+        JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
 
         /* if the JAR file is cached, the permission will always be there */
         if (result != null) {
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java	Tue Aug 18 19:53:43 2009 -0700
@@ -92,6 +92,7 @@
     public static final int ERROR_INVALID_DATA          = 13;
     public static final int ERROR_NOT_SAME_DEVICE       = 17;
     public static final int ERROR_NOT_READY             = 21;
+    public static final int ERROR_SHARING_VIOLATION     = 32;
     public static final int ERROR_FILE_EXISTS           = 80;
     public static final int ERROR_INVALID_PARAMATER     = 87;
     public static final int ERROR_DISK_FULL             = 112;
--- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java	Tue Aug 18 19:53:43 2009 -0700
@@ -299,6 +299,9 @@
         throws WindowsException
     {
         if (!ensureAccurateMetadata) {
+            WindowsException firstException = null;
+
+            // GetFileAttributesEx is the fastest way to read the attributes
             NativeBuffer buffer =
                 NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA);
             try {
@@ -310,9 +313,39 @@
                     .getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES);
                 if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
                     return fromFileAttributeData(address, 0);
+            } catch (WindowsException x) {
+                if (x.lastError() != ERROR_SHARING_VIOLATION)
+                    throw x;
+                firstException = x;
             } finally {
                 buffer.release();
             }
+
+            // For sharing violations, fallback to FindFirstFile if the file
+            // is not a root directory.
+            if (firstException != null) {
+                String search = path.getPathForWin32Calls();
+                char last = search.charAt(search.length() -1);
+                if (last == ':' || last == '\\')
+                    throw firstException;
+                buffer = getBufferForFindData();
+                try {
+                    long handle = FindFirstFile(search, buffer.address());
+                    FindClose(handle);
+                    WindowsFileAttributes attrs = fromFindData(buffer.address());
+                    // FindFirstFile does not follow sym links. Even if
+                    // followLinks is false, there isn't sufficient information
+                    // in the WIN32_FIND_DATA structure to know if the reparse
+                    // point is a sym link.
+                    if (attrs.isReparsePoint())
+                        throw firstException;
+                    return attrs;
+                } catch (WindowsException ignore) {
+                    throw firstException;
+                } finally {
+                    buffer.release();
+                }
+            }
         }
 
         // file is reparse point so need to open file to get attributes
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp	Tue Aug 18 19:53:43 2009 -0700
@@ -501,7 +501,7 @@
 
     RegisterWarningWindowClass();
     warningWindow = ::CreateWindowEx(
-            WS_EX_NOACTIVATE | WS_EX_LAYERED,
+            WS_EX_NOACTIVATE,
             GetWarningWindowClassName(),
             warningString,
             WS_POPUP,
@@ -513,7 +513,7 @@
             NULL // lParam
             );
     if (warningWindow == NULL) {
-        //XXX: actually this is bad... We didn't manage to create the widow.
+        //XXX: actually this is bad... We didn't manage to create the window.
         return;
     }
 
@@ -684,31 +684,6 @@
 
     env->DeleteLocalRef(point2D);
 
-    //Make sure the warning is not far from the window bounds
-    x = max(x, windowBounds.left - (int)warningWindowWidth - 2);
-    x = min(x, windowBounds.right + (int)warningWindowWidth + 2);
-
-    y = max(y, windowBounds.top - (int)warningWindowHeight - 2);
-    y = min(y, windowBounds.bottom + (int)warningWindowHeight + 2);
-
-    // Now make sure the warning window is visible on the screen
-    HMONITOR hmon = MonitorFromWindow(GetHWnd(), MONITOR_DEFAULTTOPRIMARY);
-    DASSERT(hmon != NULL);
-
-    RECT monitorBounds;
-    RECT monitorInsets;
-
-    MonitorBounds(hmon, &monitorBounds);
-    if (!AwtToolkit::GetScreenInsets(m_screenNum, &monitorInsets)) {
-        ::ZeroMemory(&monitorInsets, sizeof(monitorInsets));
-    }
-
-    x = max(x, monitorBounds.left + monitorInsets.left);
-    x = min(x, monitorBounds.right - monitorInsets.right - (int)warningWindowWidth);
-
-    y = max(y, monitorBounds.top + monitorInsets.top);
-    y = min(y, monitorBounds.bottom - monitorInsets.bottom - (int)warningWindowHeight);
-
     rect->left = x;
     rect->top = y;
     rect->right = rect->left + warningWindowWidth;
@@ -813,6 +788,19 @@
     ::ReleaseDC(warningWindow, hdc);
 }
 
+void AwtWindow::SetLayered(HWND window, bool layered)
+{
+    const LONG ex_style = ::GetWindowLong(window, GWL_EXSTYLE);
+    ::SetWindowLong(window, GWL_EXSTYLE, layered ?
+            ex_style | WS_EX_LAYERED : ex_style & ~WS_EX_LAYERED);
+}
+
+bool AwtWindow::IsLayered(HWND window)
+{
+    const LONG ex_style = ::GetWindowLong(window, GWL_EXSTYLE);
+    return ex_style & WS_EX_LAYERED;
+}
+
 void AwtWindow::StartSecurityAnimation(AnimationKind kind)
 {
     if (!IsUntrusted()) {
@@ -835,8 +823,14 @@
 
         ::SetLayeredWindowAttributes(warningWindow, RGB(0, 0, 0),
                 0xFF, LWA_ALPHA);
+        AwtWindow::SetLayered(warningWindow, false);
         ::RedrawWindow(warningWindow, NULL, NULL,
                 RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
+    } else if (securityAnimationKind == akPreHide) {
+        // Pre-hiding means fading-out. We have to make the window layered.
+        // Note: Some VNC clients do not support layered windows, hence
+        // we dynamically turn it on and off. See 6805231.
+        AwtWindow::SetLayered(warningWindow, true);
     }
 }
 
@@ -2514,8 +2508,6 @@
 
     HWND hwnd = GetHWnd();
 
-    LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE);
-
     if (opaque != old_opaque) {
         ::EnterCriticalSection(&contentBitmapCS);
         if (hContentBitmap != NULL) {
@@ -2527,21 +2519,22 @@
 
     if (opaque && opacity == 0xff) {
         // Turn off all the effects
-        ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style & ~WS_EX_LAYERED);
+        AwtWindow::SetLayered(hwnd, false);
+
         // Ask the window to repaint itself and all the children
         RedrawWindow();
     } else {
         // We're going to enable some effects
-        if (!(ex_style & WS_EX_LAYERED)) {
-            ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED);
+        if (!AwtWindow::IsLayered(hwnd)) {
+            AwtWindow::SetLayered(hwnd, true);
         } else {
             if ((opaque && opacity < 0xff) ^ (old_opaque && old_opacity < 0xff)) {
                 // _One_ of the modes uses the SetLayeredWindowAttributes.
                 // Need to reset the style in this case.
                 // If both modes are simple (i.e. just changing the opacity level),
                 // no need to reset the style.
-                ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style & ~WS_EX_LAYERED);
-                ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED);
+                AwtWindow::SetLayered(hwnd, false);
+                AwtWindow::SetLayered(hwnd, true);
             }
         }
 
--- a/jdk/src/windows/native/sun/windows/awt_Window.h	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/src/windows/native/sun/windows/awt_Window.h	Tue Aug 18 19:53:43 2009 -0700
@@ -331,6 +331,9 @@
 
     void RepositionSecurityWarning(JNIEnv *env);
 
+    static void SetLayered(HWND window, bool layered);
+    static bool IsLayered(HWND window);
+
 public:
     void UpdateSecurityWarningVisibility();
     static bool IsWarningWindow(HWND hWnd);
--- a/jdk/test/com/sun/jdi/EnumTest.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/com/sun/jdi/EnumTest.java	Tue Aug 18 19:53:43 2009 -0700
@@ -29,7 +29,7 @@
  *  @author jjh
  *
  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
- *  @run compile -source 1.5 -target 1.5 -g EnumTest.java
+ *  @run compile -g EnumTest.java
  *  @run main EnumTest
  */
 import com.sun.jdi.*;
--- a/jdk/test/com/sun/jdi/GenericsTest.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/com/sun/jdi/GenericsTest.java	Tue Aug 18 19:53:43 2009 -0700
@@ -29,7 +29,7 @@
  *  @author jjh
  *
  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
- *  @run compile -source 1.5 -target 1.5 -g GenericsTest.java
+ *  @run compile -g GenericsTest.java
  *  @run main GenericsTest
  */
 import com.sun.jdi.*;
--- a/jdk/test/com/sun/jdi/JdbVarargsTest.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/com/sun/jdi/JdbVarargsTest.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -32,7 +32,6 @@
 #  @run shell JdbVarargsTest.sh
 
 classname=JdbVarargsTest
-compileOptions="-source 1.5 -target 1.5"
 createJavaFile()
 {
     cat <<EOF > $classname.java.1
--- a/jdk/test/com/sun/jdi/StepTest.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/com/sun/jdi/StepTest.java	Tue Aug 18 19:53:43 2009 -0700
@@ -27,7 +27,7 @@
  *  @author Gordon Hirsch
  *
  *  @run build TestScaffold VMConnection TargetAdapter TargetListener
- *  @run compile -g -target 1.5 MethodCalls.java
+ *  @run compile -g MethodCalls.java
  *  @run compile -g MethodCallsReflection.java
  *  @run compile -g ControlFlow.java
  *  @run build StepTest
--- a/jdk/test/com/sun/jdi/UTF8Test.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/com/sun/jdi/UTF8Test.java	Tue Aug 18 19:53:43 2009 -0700
@@ -29,7 +29,7 @@
  *  @author jjh
  *
  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
- *  @run compile -g -source 1.5 UTF8Test.java
+ *  @run compile -g UTF8Test.java
  *  @run main UTF8Test
  */
 
--- a/jdk/test/com/sun/jdi/VarargsTest.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/com/sun/jdi/VarargsTest.java	Tue Aug 18 19:53:43 2009 -0700
@@ -29,7 +29,7 @@
  *  @author jjh
  *
  *  @run build TestScaffold VMConnection TargetListener TargetAdapter
- *  @run compile -g -source 1.5 -target 1.5 VarargsTest.java
+ *  @run compile -g VarargsTest.java
  *  @run main VarargsTest
  */
 import com.sun.jdi.*;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jndi/dns/CheckAccess.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6657619
+ * @summary DnsContext.debug is public static mutable (findbugs)
+ * @author Vincent Ryan
+ */
+
+import java.lang.reflect.*;
+
+/*
+ * Check that the 'debug' class member is no longer publicly accessible.
+ */
+public class CheckAccess {
+    public static final void main(String[] args) throws Exception {
+        try {
+            Class clazz = Class.forName("com.sun.jndi.dns.DnsContext");
+            Field field = clazz.getField("debug");
+            if (Modifier.isPublic(field.getModifiers())) {
+                throw new Exception(
+                    "class member 'debug' must not be publicly accessible");
+            }
+        } catch (NoSuchFieldException e) {
+            // 'debug' is not publicly accessible, ignore exception
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test %I% %E%
+ * @bug 6824440 6858484
+ * @summary Check that Apache XMLSec APIs will not accept HMAC truncation
+ *    lengths less than minimum bound
+ * @compile -XDignore.symbol.file TruncateHMAC.java
+ * @run main TruncateHMAC
+ */
+
+import java.io.File;
+import javax.crypto.SecretKey;
+import javax.xml.parsers.DocumentBuilderFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.sun.org.apache.xml.internal.security.Init;
+import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
+import com.sun.org.apache.xml.internal.security.signature.XMLSignature;
+import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException;
+import com.sun.org.apache.xml.internal.security.utils.Constants;
+
+
+public class TruncateHMAC {
+
+    private final static String DIR = System.getProperty("test.src", ".");
+    private static DocumentBuilderFactory dbf = null;
+    private static boolean atLeastOneFailed = false;
+
+    public static void main(String[] args) throws Exception {
+
+        Init.init();
+        dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        dbf.setValidating(false);
+        validate("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", false);
+        validate("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", false);
+        // this one should pass
+        validate("signature-enveloping-hmac-sha1.xml", true);
+        generate_hmac_sha1_40();
+
+        if (atLeastOneFailed) {
+            throw new Exception
+                ("At least one signature did not validate as expected");
+        }
+    }
+
+    private static void validate(String data, boolean pass) throws Exception {
+        System.out.println("Validating " + data);
+        File file = new File(DIR, data);
+
+        Document doc = dbf.newDocumentBuilder().parse(file);
+        NodeList nl =
+            doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature");
+        if (nl.getLength() == 0) {
+            throw new Exception("Couldn't find signature Element");
+        }
+        Element sigElement = (Element) nl.item(0);
+        XMLSignature signature = new XMLSignature
+            (sigElement, file.toURI().toString());
+        SecretKey sk = signature.createSecretKey("secret".getBytes("ASCII"));
+        try {
+            System.out.println
+                ("Validation status: " + signature.checkSignatureValue(sk));
+            if (!pass) {
+                System.out.println("FAILED");
+                atLeastOneFailed = true;
+            } else {
+                System.out.println("PASSED");
+            }
+        } catch (XMLSignatureException xse) {
+            System.out.println(xse.getMessage());
+            if (!pass) {
+                System.out.println("PASSED");
+            } else {
+                System.out.println("FAILED");
+            }
+        }
+    }
+
+    private static void generate_hmac_sha1_40() throws Exception {
+        System.out.println("Generating ");
+
+        Document doc = dbf.newDocumentBuilder().newDocument();
+        XMLSignature sig = new XMLSignature
+            (doc, null, XMLSignature.ALGO_ID_MAC_HMAC_SHA1, 40,
+             Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS);
+        try {
+            sig.sign(getSecretKey("secret".getBytes("ASCII")));
+            System.out.println("FAILED");
+            atLeastOneFailed = true;
+        } catch (XMLSignatureException xse) {
+            System.out.println(xse.getMessage());
+            System.out.println("PASSED");
+        }
+    }
+
+    private static SecretKey getSecretKey(final byte[] secret) {
+        return new SecretKey() {
+            public String getFormat()   { return "RAW"; }
+            public byte[] getEncoded()  { return secret; }
+            public String getAlgorithm(){ return "SECRET"; }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-0-attack.xml	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+  <SignedInfo>
+    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+      <HMACOutputLength>0</HMACOutputLength>
+    </SignatureMethod>
+    <Reference URI="#object">
+      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+      <DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue>
+    </Reference>
+  </SignedInfo>
+  <SignatureValue>
+  </SignatureValue>
+  <Object Id="object">some other text</Object>
+</Signature>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-8-attack.xml	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+  <SignedInfo>
+    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+      <HMACOutputLength>8</HMACOutputLength>
+    </SignatureMethod>
+    <Reference URI="#object">
+      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+      <DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue>
+    </Reference>
+  </SignedInfo>
+  <SignatureValue>
+    Qw==
+  </SignatureValue>
+  <Object Id="object">some other text</Object>
+</Signature>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1.xml	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+  <SignedInfo>
+    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
+    <Reference URI="#object">
+      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+      <DigestValue>7/XTsHaBSOnJ/jXD5v0zL6VKYsk=</DigestValue>
+    </Reference>
+  </SignedInfo>
+  <SignatureValue>
+    JElPttIT4Am7Q+MNoMyv+WDfAZw=
+  </SignatureValue>
+  <Object Id="object">some text</Object>
+</Signature>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6710360
+ * @summary export Kerberos session key to applications
+ */
+
+import com.sun.security.jgss.InquireSecContextPermission;
+
+public class InquireSecContextPermissionCheck {
+
+    public static void main(String[] args) throws Exception {
+
+        InquireSecContextPermission p0, p1;
+        p0 = new InquireSecContextPermission(
+                "KRB5_GET_SESSION_KEY");
+        p1 = new InquireSecContextPermission("*");
+
+        if (!p1.implies(p0) || !p1.implies(p1) || !p0.implies(p0)) {
+            throw new Exception("Check failed");
+        }
+
+        if (p0.implies(p1)) {
+            throw new Exception("This is bad");
+        }
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/security/sasl/util/CheckAccess.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6657695
+ * @summary AbstractSaslImpl.logger is a static mutable (findbugs)
+ * @author Vincent Ryan
+ */
+
+import java.lang.reflect.*;
+
+/*
+ * Check that the 'logger' class member is immutable.
+ */
+public class CheckAccess {
+    public static final void main(String[] args) throws Exception {
+            Class clazz =
+                Class.forName("com.sun.security.sasl.util.AbstractSaslImpl");
+            Field field = clazz.getDeclaredField("logger");
+            if (! Modifier.isFinal(field.getModifiers())) {
+                throw new Exception(
+                    "class member 'logger' must be immutable");
+            }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Cursor/PredefinedPrivate/PredefinedPrivate.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6656586
+ * @summary Test that Cursor.predefined array is not used in
+Cursor.getPredefinedCursor() method
+ * @author Artem Ananiev
+ * @run main PredefinedPrivate
+ */
+
+import java.awt.*;
+
+public class PredefinedPrivate {
+    public static void main(String args[]) {
+        new MyCursor();
+        if (Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR) instanceof MyCursor) {
+            throw new RuntimeException("Test FAILED: getPredefinedCursor() returned modified cursor");
+        }
+    }
+}
+
+class MyCursor extends Cursor {
+    public MyCursor() {
+        super(DEFAULT_CURSOR);
+        Cursor.predefined[DEFAULT_CURSOR] = this;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/Introspector/Test6660539.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6660539
+ * @summary Tests changeable BeanInfo cache in different application contexts
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+
+public class Test6660539 implements Runnable {
+    private static final String NAME = "$$$";
+
+    public static void main(String[] args) throws Exception {
+        for (PropertyDescriptor pd : getPropertyDescriptors()) {
+            pd.setDisplayName(NAME);
+        }
+        ThreadGroup group = new ThreadGroup(NAME);
+        Thread thread = new Thread(group, new Test6660539());
+        thread.start();
+        thread.join();
+    }
+
+    public void run() {
+        SunToolkit.createNewAppContext();
+        for (PropertyDescriptor pd : getPropertyDescriptors()) {
+            if (pd.getDisplayName().equals(NAME))
+                throw new Error("shared BeanInfo cache");
+        }
+    }
+
+    private static PropertyDescriptor[] getPropertyDescriptors() {
+        try {
+            BeanInfo info = Introspector.getBeanInfo(Test6660539.class);
+            return info.getPropertyDescriptors();
+        }
+        catch (IntrospectionException exception) {
+            throw new Error("unexpected", exception);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestBox.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for BoxLayout
+ * @author Sergey Malenkov
+ */
+
+import java.awt.FlowLayout;
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+
+public final class TestBox {
+    private static final Integer OBJECT = Integer.valueOf(-123);
+
+    public static void main(String[] args) {
+        TestEncoder.test(
+                new Box(BoxLayout.LINE_AXIS),
+                new Box(BoxLayout.PAGE_AXIS) {
+                    @Override
+                    public FlowLayout getLayout() {
+                        return new FlowLayout() {
+                            private final Object axis = OBJECT;
+                        };
+                    }
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedCollection.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedCollection
+ * @author Sergey Malenkov
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class TestCheckedCollection {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        List<String> list = Collections.emptyList();
+        TestEncoder.test(
+                Collections.checkedCollection(list, String.class),
+                new ArrayList() {
+                    private final Object type = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedList.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedList
+ * @author Sergey Malenkov
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class TestCheckedList {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        List<String> list = Collections.emptyList();
+        TestEncoder.test(
+                Collections.checkedList(list, String.class),
+                new ArrayList() {
+                    private final Object type = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedMap.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedMap
+ * @author Sergey Malenkov
+ */
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class TestCheckedMap {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        Map<String, String> map = Collections.emptyMap();
+        TestEncoder.test(
+                Collections.checkedMap(map, String.class, String.class),
+                new HashMap() {
+                    private final Object keyType = OBJECT;
+                    private final Object valueType = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedRandomAccessList.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedRandomAccessList
+ * @author Sergey Malenkov
+ */
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public final class TestCheckedRandomAccessList {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        List<String> list = new ArrayList<String>();
+        TestEncoder.test(
+                Collections.checkedList(list, String.class),
+                new ArrayList() {
+                    private final Object type = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSet.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedSet
+ * @author Sergey Malenkov
+ */
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class TestCheckedSet {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        Set<String> set = Collections.emptySet();
+        TestEncoder.test(
+                Collections.checkedSet(set, String.class),
+                new HashSet() {
+                    private final Object type = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedMap.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedSortedMap
+ * @author Sergey Malenkov
+ */
+
+import java.util.Collections;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+public final class TestCheckedSortedMap {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        SortedMap<String, String> map = new TreeMap<String, String>();
+        TestEncoder.test(
+                Collections.checkedSortedMap(map, String.class, String.class),
+                new TreeMap() {
+                    private final Object keyType = OBJECT;
+                    private final Object valueType = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedSet.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for CheckedSortedSet
+ * @author Sergey Malenkov
+ */
+
+import java.util.Collections;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+public final class TestCheckedSortedSet {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        SortedSet<String> set = new TreeSet<String>();
+        TestEncoder.test(
+                Collections.checkedSortedSet(set, String.class),
+                new TreeSet() {
+                    private final Object type = OBJECT;
+                },
+                OBJECT
+        );
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestEncoder.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+import java.beans.Expression;
+import java.beans.XMLEncoder;
+
+final class TestEncoder extends XMLEncoder {
+    private Expression expression;
+
+    private TestEncoder() {
+        super(System.out);
+    }
+
+    @Override
+    public void writeExpression(Expression expression) {
+        if (this.expression == null) {
+            this.expression = expression;
+        }
+        super.writeExpression(expression);
+    }
+
+    public static void test(Object provider, Object object, Object value) {
+        System.setSecurityManager(new SecurityManager());
+
+        TestEncoder encoder = new TestEncoder();
+        encoder.setPersistenceDelegate(
+                object.getClass(),
+                encoder.getPersistenceDelegate(provider.getClass()));
+        encoder.writeObject(object);
+        encoder.close();
+
+        if (encoder.expression != null) {
+            for (Object argument : encoder.expression.getArguments()) {
+                if (value.equals(argument)) {
+                    throw new Error("Found private value!");
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestEnumMap.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for EnumMap
+ * @author Sergey Malenkov
+ */
+
+import java.util.EnumMap;
+import java.util.HashMap;
+
+public final class TestEnumMap {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        TestEncoder.test(
+                new EnumMap<Point, String>(Point.class),
+                new HashMap() {
+                    private final Object keyType = OBJECT;
+                },
+                OBJECT);
+    }
+
+    public enum Point { X, Y, Z }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/beans/XMLEncoder/6777487/TestEnumSet.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6777487
+ * @summary Tests private field access for EnumSet
+ * @author Sergey Malenkov
+ */
+
+import java.util.EnumSet;
+import java.util.HashSet;
+
+public final class TestEnumSet {
+    private static final Object OBJECT = new Object();
+
+    public static void main(String[] args) {
+        TestEncoder.test(
+                EnumSet.noneOf(Point.class),
+                new HashSet() {
+                    private final Object elementType = OBJECT;
+                },
+                OBJECT);
+    }
+
+    public enum Point { X, Y, Z }
+}
--- a/jdk/test/java/net/Authenticator/B4933582.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/Authenticator/B4933582.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -30,6 +30,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
@@ -39,7 +43,7 @@
     exit 1;
     ;;
 esac
-${TESTJAVA}${FS}bin${FS}javac -d . -classpath ${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest ${TESTSRC}${FS}B4933582.java
+${TESTJAVA}${FS}bin${FS}javac -d . -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest" ${TESTSRC}${FS}B4933582.java
 rm -f cache.ser auth.save
-${TESTJAVA}${FS}bin${FS}java -classpath ${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}. B4933582 first
-${TESTJAVA}${FS}bin${FS}java -classpath ${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}. B4933582 second
+${TESTJAVA}${FS}bin${FS}java -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 first
+${TESTJAVA}${FS}bin${FS}java -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 second
--- a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -35,6 +35,10 @@
     PATHSEP=":"
     FILESEP="/"
     ;;
+  CYGWIN* )
+    PATHSEP=";"
+    FILESEP="/"
+    ;;
   Windows* )
     PATHSEP=";"
     FILESEP="\\"
--- a/jdk/test/java/net/Socket/OldSocketImpl.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/Socket/OldSocketImpl.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -32,6 +32,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/java/net/URL/B5086147.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/URL/B5086147.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -29,6 +29,10 @@
   SunOS | Linux )
     exit 0
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/java/net/URL/runconstructor.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/URL/runconstructor.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -31,6 +31,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/java/net/URLClassLoader/B5077773.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/URLClassLoader/B5077773.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -42,6 +42,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/java/net/URLClassLoader/sealing/checksealed.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/URLClassLoader/sealing/checksealed.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -35,6 +35,10 @@
     PS=":"
     FS="/"            
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
@@ -49,10 +53,10 @@
 if [ x"$TESTJAVA" = x ]; then TESTJAVA=$1; fi
 if [ x"$TESTSRC" = x ]; then TESTSRC=.; fi
 
-CLASSPATH=.${PS}${TESTSRC}${FS}a${PS}${TESTSRC}${FS}b.jar
+CLASSPATH=".${PS}${TESTSRC}${FS}a${PS}${TESTSRC}${FS}b.jar"
 
-${TESTJAVA}${FS}bin${FS}javac -classpath ${CLASSPATH} -d . ${TESTSRC}${FS}CheckSealed.java
-${TESTJAVA}${FS}bin${FS}java -cp ${CLASSPATH} CheckSealed 1
+${TESTJAVA}${FS}bin${FS}javac -classpath "${CLASSPATH}" -d . ${TESTSRC}${FS}CheckSealed.java
+${TESTJAVA}${FS}bin${FS}java -cp "${CLASSPATH}" CheckSealed 1
 if [ $? != 0 ]; then exit 1; fi
-${TESTJAVA}${FS}bin${FS}java -cp ${CLASSPATH} CheckSealed 2
+${TESTJAVA}${FS}bin${FS}java -cp "${CLASSPATH}" CheckSealed 2
 if [ $? != 0 ]; then exit 1; fi
--- a/jdk/test/java/net/URLConnection/6212146/test.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/net/URLConnection/6212146/test.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -41,6 +41,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,6 +25,7 @@
  * @bug 4527345
  * @summary Unit test for DatagramChannel's multicast support
  * @build BasicMulticastTests NetworkConfiguration
+ * @run main BasicMulticastTests
  */
 
 import java.nio.ByteBuffer;
--- a/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,6 +25,7 @@
  * @bug 4527345
  * @summary Unit test for DatagramChannel's multicast support
  * @build MulticastSendReceiveTests NetworkConfiguration
+ * @run main MulticastSendReceiveTests
  */
 
 import java.nio.ByteBuffer;
--- a/jdk/test/java/nio/channels/SocketChannel/Shutdown.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/nio/channels/SocketChannel/Shutdown.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2002-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
@@ -22,26 +22,65 @@
  */
 
 /* @test
- * @bug 4618960
- * @summary Test isInputShutdown
- * @library ..
+ * @bug 4618960 4516760
+ * @summary Test shutdownXXX and isInputShutdown
  */
 
+import java.io.IOException;
 import java.net.*;
-import java.nio.*;
+import java.nio.ByteBuffer;
 import java.nio.channels.*;
 
 public class Shutdown {
 
-    public static void main(String args[]) throws Exception {
-        InetSocketAddress sa = new InetSocketAddress(
-                                InetAddress.getByName(TestUtil.HOST), 23);
-        SocketChannel sc = SocketChannel.open(sa);
-        boolean before = sc.socket().isInputShutdown();
-        sc.socket().shutdownInput();
-        boolean after = sc.socket().isInputShutdown();
-        sc.close();
-        if (before || !after)
-            throw new Exception("Test failed");
+    /**
+     * Accept a connection, and close it immediately causing a hard reset.
+     */
+    static void acceptAndReset(ServerSocketChannel ssc) throws IOException {
+        SocketChannel peer = ssc.accept();
+        try {
+            peer.setOption(StandardSocketOption.SO_LINGER, 0);
+            peer.configureBlocking(false);
+            peer.write(ByteBuffer.wrap(new byte[128*1024]));
+        } finally {
+            peer.close();
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        ServerSocketChannel ssc = ServerSocketChannel.open()
+            .bind(new InetSocketAddress(0));
+        try {
+            InetAddress lh = InetAddress.getLocalHost();
+            int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
+            SocketAddress remote = new InetSocketAddress(lh, port);
+
+            // Test SocketChannel shutdownXXX
+            SocketChannel sc;
+            sc = SocketChannel.open(remote);
+            try {
+                acceptAndReset(ssc);
+                sc.shutdownInput();
+                sc.shutdownOutput();
+            } finally {
+                sc.close();
+            }
+
+            // Test Socket adapter shutdownXXX and isShutdownInput
+            sc = SocketChannel.open(remote);
+            try {
+                acceptAndReset(ssc);
+                boolean before = sc.socket().isInputShutdown();
+                sc.socket().shutdownInput();
+                boolean after = sc.socket().isInputShutdown();
+                if (before || !after)
+                    throw new RuntimeException("Before and after test failed");
+                sc.socket().shutdownOutput();
+            } finally {
+                sc.close();
+            }
+        } finally {
+            ssc.close();
+        }
     }
 }
--- a/jdk/test/java/nio/file/Files/ContentType.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/nio/file/Files/ContentType.java	Tue Aug 18 19:53:43 2009 -0700
@@ -26,6 +26,7 @@
  * @summary Unit test for probeContentType method
  * @library ..
  * @build ContentType SimpleFileTypeDetector
+ * @run main ContentType
  */
 
 import java.nio.file.*;
--- a/jdk/test/java/nio/file/Files/Misc.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/nio/file/Files/Misc.java	Tue Aug 18 19:53:43 2009 -0700
@@ -22,13 +22,14 @@
  */
 
 /* @test
- * @bug 4313887 6838333
+ * @bug 4313887 6838333 6865748
  * @summary Unit test for java.nio.file.Files for miscellenous cases not
  *   covered by other tests
  * @library ..
  */
 
 import java.nio.file.*;
+import java.nio.file.attribute.Attributes;
 import java.io.IOException;
 import java.util.*;
 
@@ -113,5 +114,29 @@
             npeExpected();
         } catch (NullPointerException e) {
         }
+
+        SimpleFileVisitor<Path> visitor = new SimpleFileVisitor<Path>() { };
+        boolean ranTheGauntlet = false;
+        try { visitor.preVisitDirectory(null);
+        } catch (NullPointerException x0) {
+        try { visitor.preVisitDirectoryFailed(null, new IOException());
+        } catch (NullPointerException x1) {
+        try { visitor.preVisitDirectoryFailed(dir, null);
+        } catch (NullPointerException x2) {
+        try { visitor.visitFile(null, Attributes.readBasicFileAttributes(Paths.get(".")));
+        } catch (NullPointerException x3) {
+        try {  visitor.visitFile(dir, null);
+        } catch (NullPointerException x4) {
+        try { visitor.visitFileFailed(null, new IOException());
+        } catch (NullPointerException x5) {
+        try { visitor.visitFileFailed(dir, null);
+        } catch (NullPointerException x6) {
+        try { visitor.postVisitDirectory(null, new IOException());
+        } catch (NullPointerException x7) {
+            // if we get here then all visit* methods threw NPE as expected
+            ranTheGauntlet = true;
+        }}}}}}}}
+        if (!ranTheGauntlet)
+            throw new RuntimeException("A visit method did not throw NPE");
     }
 }
--- a/jdk/test/java/nio/file/Path/Misc.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/nio/file/Path/Misc.java	Tue Aug 18 19:53:43 2009 -0700
@@ -22,7 +22,7 @@
  */
 
 /* @test
- * @bug 4313887 6838333
+ * @bug 4313887 6838333 6866804
  * @summary Unit test for java.nio.file.Path for miscellenous methods not
  *   covered by other tests
  * @library ..
@@ -107,6 +107,28 @@
         dir.checkAccess(AccessMode.READ, AccessMode.WRITE);
 
         /**
+         * Test: Check access to all files in all root directories.
+         * (A useful test on Windows for special files such as pagefile.sys)
+         */
+        for (Path root: FileSystems.getDefault().getRootDirectories()) {
+            DirectoryStream<Path> stream;
+            try {
+                stream = root.newDirectoryStream();
+            } catch (IOException x) {
+                continue; // skip root directories that aren't accessible
+            }
+            try {
+                for (Path entry: stream) {
+                    try {
+                        entry.checkAccess();
+                    } catch (AccessDeniedException ignore) { }
+                }
+            } finally {
+                stream.close();
+            }
+        }
+
+        /**
          * Test: File does not exist
          */
         Path doesNotExist = dir.resolve("thisDoesNotExists");
--- a/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -54,6 +54,10 @@
     PATHSEP=":"
     FILESEP="/"
     ;;
+  CYGWIN* )
+    PATHSEP=";"
+    FILESEP="/"
+    ;;
   Windows* )
     PATHSEP=";"
     FILESEP="\\"
@@ -81,7 +85,7 @@
 
 # run the test
 ${TESTJAVA}${FILESEP}bin${FILESEP}java \
-	-classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar \
+	-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" \
 	ClassLoaderDeadlock
 
 exit $?
--- a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -42,6 +42,10 @@
     PATHSEP=":"
     FILESEP="/"
     ;;
+  CYGWIN* )
+    PATHSEP=";"
+    FILESEP="/"
+    ;;
   Windows* )
     PATHSEP=";"
     FILESEP="\\"
@@ -54,5 +58,5 @@
 
 JAVA="${TESTJAVA}${FILESEP}bin${FILESEP}java"
 
-${JAVA} -cp ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar Deadlock
+${JAVA} -cp "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" Deadlock
 
--- a/jdk/test/java/security/Security/signedfirst/Dyn.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/security/Security/signedfirst/Dyn.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -54,6 +54,10 @@
     PATHSEP=":"
     FILESEP="/"
     ;;
+  CYGWIN* )
+    PATHSEP=";"
+    FILESEP="/"
+    ;;
   Windows* )
     PATHSEP=";"
     FILESEP="\\"
@@ -76,7 +80,7 @@
 
 # run the test
 ${TESTJAVA}${FILESEP}bin${FILESEP}java \
-	-classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar \
+	-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \
 	DynSignedProvFirst
 
 exit $?
--- a/jdk/test/java/security/Security/signedfirst/Static.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/security/Security/signedfirst/Static.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -54,6 +54,10 @@
     PATHSEP=":"
     FILESEP="/"
     ;;
+  CYGWIN* )
+    PATHSEP=";"
+    FILESEP="/"
+    ;;
   Windows* )
     PATHSEP=";"
     FILESEP="\\"
@@ -70,14 +74,14 @@
 
 # compile the test program
 ${TESTJAVA}${FILESEP}bin${FILESEP}javac \
-	-classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar \
+	-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \
 	-d ${TESTCLASSES}${FILESEP} \
 	${TESTSRC}${FILESEP}StaticSignedProvFirst.java
 
 # run the test
 cd ${TESTSRC}${FILESEP}
 ${TESTJAVA}${FILESEP}bin${FILESEP}java \
-	-classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar \
+	-classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \
 	-Djava.security.properties=file:${TESTSRC}${FILESEP}Static.props \
 	StaticSignedProvFirst
 
--- a/jdk/test/java/util/Collection/MOAT.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Collection/MOAT.java	Tue Aug 18 19:53:43 2009 -0700
@@ -426,6 +426,36 @@
         q.poll();
         equal(q.size(), 4);
         checkFunctionalInvariants(q);
+        if ((q instanceof LinkedBlockingQueue) ||
+            (q instanceof LinkedBlockingDeque) ||
+            (q instanceof ConcurrentLinkedQueue)) {
+            testQueueIteratorRemove(q);
+        }
+    }
+
+    private static void testQueueIteratorRemove(Queue<Integer> q) {
+        System.err.printf("testQueueIteratorRemove %s%n",
+                          q.getClass().getSimpleName());
+        q.clear();
+        for (int i = 0; i < 5; i++)
+            q.add(i);
+        Iterator<Integer> it = q.iterator();
+        check(it.hasNext());
+        for (int i = 3; i >= 0; i--)
+            q.remove(i);
+        equal(it.next(), 0);
+        equal(it.next(), 4);
+
+        q.clear();
+        for (int i = 0; i < 5; i++)
+            q.add(i);
+        it = q.iterator();
+        equal(it.next(), 0);
+        check(it.hasNext());
+        for (int i = 1; i < 4; i++)
+            q.remove(i);
+        equal(it.next(), 1);
+        equal(it.next(), 4);
     }
 
     private static void testList(final List<Integer> l) {
@@ -451,6 +481,11 @@
     }
 
     private static void testCollection(Collection<Integer> c) {
+        try { testCollection1(c); }
+        catch (Throwable t) { unexpected(t); }
+    }
+
+    private static void testCollection1(Collection<Integer> c) {
 
         System.out.println("\n==> " + c.getClass().getName());
 
--- a/jdk/test/java/util/Formatter/Basic-X.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/Basic-X.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/Basic.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/Basic.java	Tue Aug 18 19:53:43 2009 -0700
@@ -25,7 +25,7 @@
  * @summary Unit test for formatter
  * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937
  *      5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122
- *      6344623 6369500 6534606 6282094 6286592 6476425
+ *      6344623 6369500 6534606 6282094 6286592 6476425 5063507
  *
  * @run shell/timeout=240 Basic.sh
  */
--- a/jdk/test/java/util/Formatter/BasicBigDecimal.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicBigInteger.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicBigInteger.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicBoolean.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicBoolean.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicBooleanObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicBooleanObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicByte.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicByte.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicByteObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicByteObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicChar.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicChar.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicCharObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicCharObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicDateTime.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicDateTime.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicDouble.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicDouble.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicDoubleObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicDoubleObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicFloat.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicFloat.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicFloatObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicFloatObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicInt.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicInt.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicIntObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicIntObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicLong.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicLong.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicLongObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicLongObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicShort.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicShort.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- a/jdk/test/java/util/Formatter/BasicShortObject.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/Formatter/BasicShortObject.java	Tue Aug 18 19:53:43 2009 -0700
@@ -486,6 +486,10 @@
         //---------------------------------------------------------------------
         tryCatch("%-s", MissingFormatWidthException.class);
         tryCatch("%--s", DuplicateFormatFlagsException.class);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f);
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello");
+        tryCatch("%#s", FormatFlagsConversionMismatchException.class, null);
 
         //---------------------------------------------------------------------
         // %h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimSort/ArrayBuilder.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2009 Google 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.
+ *
+ * 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.
+ */
+
+import java.util.Random;
+import java.math.BigInteger;
+
+public enum ArrayBuilder {
+
+    // These seven are from  Tim's paper (listsort.txt)
+
+    RANDOM_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = rnd.nextInt();
+            return result;
+        }
+    },
+
+    DESCENDING_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = len - i;
+            return result;
+        }
+    },
+
+    ASCENDING_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = i;
+            return result;
+        }
+    },
+
+    ASCENDING_3_RND_EXCH_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = i;
+            for (int i = 0; i < 3; i++)
+                swap(result, rnd.nextInt(result.length),
+                             rnd.nextInt(result.length));
+            return result;
+        }
+    },
+
+    ASCENDING_10_RND_AT_END_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            int endStart = len - 10;
+            for (int i = 0; i < endStart; i++)
+                result[i] = i;
+            for (int i = endStart; i < len; i++)
+                result[i] = rnd.nextInt(endStart + 10);
+            return result;
+        }
+    },
+
+    ALL_EQUAL_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = 666;
+            return result;
+        }
+    },
+
+    DUPS_GALORE_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = rnd.nextInt(4);
+            return result;
+        }
+    },
+
+    RANDOM_WITH_DUPS_INT {
+        public Object[] build(int len) {
+            Integer[] result = new Integer[len];
+            for (int i = 0; i < len; i++)
+                result[i] = rnd.nextInt(len);
+            return result;
+        }
+    },
+
+    PSEUDO_ASCENDING_STRING {
+        public String[] build(int len) {
+            String[] result = new String[len];
+            for (int i = 0; i < len; i++)
+                result[i] = Integer.toString(i);
+            return result;
+        }
+    },
+
+    RANDOM_BIGINT {
+        public BigInteger[] build(int len) {
+            BigInteger[] result = new BigInteger[len];
+            for (int i = 0; i < len; i++)
+                result[i] = HUGE.add(BigInteger.valueOf(rnd.nextInt(len)));
+            return result;
+        }
+    };
+
+    public abstract Object[] build(int len);
+
+    public void resetRandom() {
+        rnd = new Random(666);
+    }
+
+    private static Random rnd = new Random(666);
+
+    private static void swap(Object[] a, int i, int j) {
+        Object t = a[i];
+        a[i] = a[j];
+        a[j] = t;
+    }
+
+    private static BigInteger HUGE = BigInteger.ONE.shiftLeft(100);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimSort/README	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,4 @@
+This directory contains benchmark programs used to compare the
+performance of the TimSort algorithm against the historic 1997
+implementation of Arrays.sort.  Any future benchmarking will require
+minor modifications.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimSort/SortPerf.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009 Google 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.
+ *
+ * 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.
+ */
+
+import java.util.Arrays;
+
+public class SortPerf {
+    private static final int NUM_SETS = 5;
+    private static final int[] lengths = { 10, 100, 1000, 10000, 1000000 };
+
+    // Returns the number of repetitions as a function of the list length
+    private static int reps(int n) {
+        return (int) (12000000 / (n * Math.log10(n)));
+    }
+
+    public static void main(String[] args) {
+        Sorter.warmup();
+
+        System.out.print("Strategy,Length");
+        for (Sorter sorter : Sorter.values())
+            System.out.print("," + sorter);
+        System.out.println();
+
+        for (ArrayBuilder ab : ArrayBuilder.values()) {
+            for (int n : lengths) {
+                System.out.printf("%s,%d", ab, n);
+                int reps = reps(n);
+                Object[] proto = ab.build(n);
+                for (Sorter sorter : Sorter.values()) {
+                    double minTime = Double.POSITIVE_INFINITY;
+                    for (int set = 0; set < NUM_SETS; set++) {
+                        long startTime = System.nanoTime();
+                        for (int k = 0; k < reps; k++) {
+                            Object[] a = proto.clone();
+                            sorter.sort(a);
+                        }
+                        long endTime = System.nanoTime();
+                        double time = (endTime - startTime) / (1000000. * reps);
+                        minTime = Math.min(minTime, time);
+                    }
+                    System.out.printf(",%5f", minTime);
+                }
+                System.out.println();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimSort/Sorter.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009 Google 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.
+ *
+ * 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.
+ */
+
+import java.util.*;
+
+public enum Sorter {
+    TIMSORT {
+        public void sort(Object[] array) {
+            ComparableTimSort.sort(array);
+        }
+    },
+    MERGESORT {
+        public void sort(Object[] array) {
+            Arrays.sort(array);
+        }
+    };
+
+    public abstract void sort(Object[] array);
+
+    public static void warmup() {
+        System.out.println("start warm up");
+        Integer[] gold = new Integer[10000];
+        Random random = new java.util.Random();
+        for (int i=0; i < gold.length; i++)
+            gold[i] = random.nextInt();
+
+        for (int i=0; i < 10000; i++) {
+            for (Sorter s : values()) {
+                Integer[] test= gold.clone();
+                s.sort(test);
+            }
+        }
+        System.out.println("  end warm up");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6805775 6815766
+ * @summary Test concurrent offer vs. drainTo
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class OfferDrainToLoops {
+    void checkNotContainsNull(Iterable it) {
+        for (Object x : it)
+            check(x != null);
+    }
+
+    abstract class CheckedThread extends Thread {
+        abstract protected void realRun();
+        public void run() {
+            try { realRun(); } catch (Throwable t) { unexpected(t); }
+        }
+        {
+            setDaemon(true);
+            start();
+        }
+    }
+
+    void test(String[] args) throws Throwable {
+        test(new LinkedBlockingQueue());
+        test(new LinkedBlockingQueue(2000));
+        test(new LinkedBlockingDeque());
+        test(new LinkedBlockingDeque(2000));
+        test(new ArrayBlockingQueue(2000));
+    }
+
+    void test(final BlockingQueue q) throws Throwable {
+        System.out.println(q.getClass().getSimpleName());
+        final long testDurationSeconds = 1L;
+        final long testDurationMillis = testDurationSeconds * 1000L;
+        final long quittingTimeNanos
+            = System.nanoTime() + testDurationSeconds * 1000L * 1000L * 1000L;
+
+        Thread offerer = new CheckedThread() {
+            protected void realRun() {
+                for (long i = 0; ; i++) {
+                    if ((i % 1024) == 0 &&
+                        System.nanoTime() - quittingTimeNanos > 0)
+                        break;
+                    while (! q.offer(i))
+                        Thread.yield();
+                }}};
+
+        Thread drainer = new CheckedThread() {
+            protected void realRun() {
+                for (long i = 0; ; i++) {
+                    if (System.nanoTime() - quittingTimeNanos > 0)
+                        break;
+                    List list = new ArrayList();
+                    int n = q.drainTo(list);
+                    equal(list.size(), n);
+                    for (int j = 0; j < n - 1; j++)
+                        equal((Long) list.get(j) + 1L, list.get(j + 1));
+                    Thread.yield();
+                }}};
+
+        Thread scanner = new CheckedThread() {
+            protected void realRun() {
+                for (long i = 0; ; i++) {
+                    if (System.nanoTime() - quittingTimeNanos > 0)
+                        break;
+                    checkNotContainsNull(q);
+                    Thread.yield();
+                }}};
+
+        offerer.join(10 * testDurationMillis);
+        drainer.join(10 * testDurationMillis);
+        check(! offerer.isAlive());
+        check(! drainer.isAlive());
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new OfferDrainToLoops().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/ConcurrentQueueLoops.java	Tue Aug 18 19:50:12 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * 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.
- *
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/licenses/publicdomain
- */
-
-/*
- * @test
- * @bug 4486658
- * @compile -source 1.5 ConcurrentQueueLoops.java
- * @run main/timeout=230 ConcurrentQueueLoops
- * @summary Checks that a set of threads can repeatedly get and modify items
- */
-
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-public class ConcurrentQueueLoops {
-    static final ExecutorService pool = Executors.newCachedThreadPool();
-    static AtomicInteger totalItems;
-    static boolean print = false;
-
-    public static void main(String[] args) throws Exception {
-        int maxStages = 8;
-        int items = 100000;
-
-        if (args.length > 0)
-            maxStages = Integer.parseInt(args[0]);
-
-        print = false;
-        System.out.println("Warmup...");
-        oneRun(1, items);
-        Thread.sleep(100);
-        oneRun(1, items);
-        Thread.sleep(100);
-        print = true;
-
-        for (int i = 1; i <= maxStages; i += (i+1) >>> 1) {
-            oneRun(i, items);
-        }
-        pool.shutdown();
-        if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS))
-            throw new Error();
-   }
-
-    static class Stage implements Callable<Integer> {
-        final Queue<Integer> queue;
-        final CyclicBarrier barrier;
-        int items;
-        Stage (Queue<Integer> q, CyclicBarrier b, int items) {
-            queue = q;
-            barrier = b;
-            this.items = items;
-        }
-
-        public Integer call() {
-            // Repeatedly take something from queue if possible,
-            // transform it, and put back in.
-            try {
-                barrier.await();
-                int l = 4321;
-                int takes = 0;
-                for (;;) {
-                    Integer item = queue.poll();
-                    if (item != null) {
-                        ++takes;
-                        l = LoopHelpers.compute2(item.intValue());
-                    }
-                    else if (takes != 0) {
-                        totalItems.getAndAdd(-takes);
-                        takes = 0;
-                    }
-                    else if (totalItems.get() <= 0)
-                        break;
-                    l = LoopHelpers.compute1(l);
-                    if (items > 0) {
-                        --items;
-                        queue.offer(new Integer(l));
-                    }
-                    else if ( (l & (3 << 5)) == 0) // spinwait
-                        Thread.sleep(1);
-                }
-                return new Integer(l);
-            }
-            catch (Exception ie) {
-                ie.printStackTrace();
-                throw new Error("Call loop failed");
-            }
-        }
-    }
-
-    static void oneRun(int n, int items) throws Exception {
-        Queue<Integer> q = new ConcurrentLinkedQueue<Integer>();
-        LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
-        CyclicBarrier barrier = new CyclicBarrier(n + 1, timer);
-        totalItems = new AtomicInteger(n * items);
-        ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(n);
-        for (int i = 0; i < n; ++i)
-            results.add(pool.submit(new Stage(q, barrier, items)));
-
-        if (print)
-            System.out.print("Threads: " + n + "\t:");
-        barrier.await();
-        int total = 0;
-        for (int i = 0; i < n; ++i) {
-            Future<Integer> f = results.get(i);
-            Integer r = f.get();
-            total += r.intValue();
-        }
-        long endTime = System.nanoTime();
-        long time = endTime - timer.startTime;
-        if (print)
-            System.out.println(LoopHelpers.rightJustify(time / (items * n)) + " ns per item");
-        if (total == 0) // avoid overoptimization
-            System.out.println("useless result: " + total);
-
-    }
-}
--- a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/LoopHelpers.java	Tue Aug 18 19:50:12 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,129 +0,0 @@
-/*
- * 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.
- *
- * 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.
- */
-
-/*
- * This file is available under and governed by the GNU General Public
- * License version 2 only, as published by the Free Software Foundation.
- * However, the following notice accompanied the original version of this
- * file:
- *
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/licenses/publicdomain
- */
-
-/**
- * Misc utilities in JSR166 performance tests
- */
-
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-
-class LoopHelpers {
-
-    // Some mindless computation to do between synchronizations...
-
-    /**
-     * generates 32 bit pseudo-random numbers.
-     * Adapted from http://www.snippets.org
-     */
-    public static int compute1(int x) {
-        int lo = 16807 * (x & 0xFFFF);
-        int hi = 16807 * (x >>> 16);
-        lo += (hi & 0x7FFF) << 16;
-        if ((lo & 0x80000000) != 0) {
-            lo &= 0x7fffffff;
-            ++lo;
-        }
-        lo += hi >>> 15;
-        if (lo == 0 || (lo & 0x80000000) != 0) {
-            lo &= 0x7fffffff;
-            ++lo;
-        }
-        return lo;
-    }
-
-    /**
-     *  Computes a linear congruential random number a random number
-     *  of times.
-     */
-    public static int compute2(int x) {
-        int loops = (x >>> 4) & 7;
-        while (loops-- > 0) {
-            x = (x * 2147483647) % 16807;
-        }
-        return x;
-    }
-
-    /**
-     * An actually useful random number generator, but unsynchronized.
-     * Basically same as java.util.Random.
-     */
-    public static class SimpleRandom {
-        private final static long multiplier = 0x5DEECE66DL;
-        private final static long addend = 0xBL;
-        private final static long mask = (1L << 48) - 1;
-        static final AtomicLong seq = new AtomicLong(1);
-        private long seed = System.nanoTime() + seq.getAndIncrement();
-
-        public void setSeed(long s) {
-            seed = s;
-        }
-
-        public int next() {
-            long nextseed = (seed * multiplier + addend) & mask;
-            seed = nextseed;
-            return ((int)(nextseed >>> 17)) & 0x7FFFFFFF;
-        }
-    }
-
-    public static class BarrierTimer implements Runnable {
-        public volatile long startTime;
-        public volatile long endTime;
-        public void run() {
-            long t = System.nanoTime();
-            if (startTime == 0)
-                startTime = t;
-            else
-                endTime = t;
-        }
-        public void clear() {
-            startTime = 0;
-            endTime = 0;
-        }
-        public long getTime() {
-            return endTime - startTime;
-        }
-    }
-
-    public static String rightJustify(long n) {
-        // There's probably a better way to do this...
-        String field = "         ";
-        String num = Long.toString(n);
-        if (num.length() >= field.length())
-            return num;
-        StringBuffer b = new StringBuffer(field);
-        b.replace(b.length()-num.length(), b.length(), num);
-        return b.toString();
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,198 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 4486658 6785442
+ * @run main ConcurrentQueueLoops 8 123456
+ * @summary Checks that a set of threads can repeatedly get and modify items
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+public class ConcurrentQueueLoops {
+    ExecutorService pool;
+    AtomicInteger totalItems;
+    boolean print;
+
+    // Suitable for benchmarking.  Overriden by args[0] for testing.
+    int maxStages = 20;
+
+    // Suitable for benchmarking.  Overriden by args[1] for testing.
+    int items = 1024 * 1024;
+
+    Collection<Queue<Integer>> concurrentQueues() {
+        List<Queue<Integer>> queues = new ArrayList<Queue<Integer>>();
+        queues.add(new ConcurrentLinkedQueue<Integer>());
+        queues.add(new ArrayBlockingQueue<Integer>(items, false));
+        //queues.add(new ArrayBlockingQueue<Integer>(count, true));
+        queues.add(new LinkedBlockingQueue<Integer>());
+        queues.add(new LinkedBlockingDeque<Integer>());
+
+        try {
+            queues.add((Queue<Integer>)
+                       Class.forName("java.util.concurrent.LinkedTransferQueue")
+                       .newInstance());
+        } catch (IllegalAccessException e) {
+        } catch (InstantiationException e) {
+        } catch (ClassNotFoundException e) {
+            // OK; not yet added to JDK
+        }
+
+        // Following additional implementations are available from:
+        // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
+        // queues.add(new LinkedTransferQueue<Integer>());
+        // queues.add(new SynchronizedLinkedListQueue<Integer>());
+
+        // Avoid "first fast, second slow" benchmark effect.
+        Collections.shuffle(queues);
+        return queues;
+    }
+
+    void test(String[] args) throws Throwable {
+        if (args.length > 0)
+            maxStages = Integer.parseInt(args[0]);
+        if (args.length > 1)
+            items = Integer.parseInt(args[1]);
+
+        for (Queue<Integer> queue : concurrentQueues())
+            test(queue);
+    }
+
+    void test(final Queue<Integer> q) throws Throwable {
+        System.out.println(q.getClass().getSimpleName());
+        pool = Executors.newCachedThreadPool();
+        print = false;
+
+        print = false;
+        System.out.println("Warmup...");
+        oneRun(1, items, q);
+        //Thread.sleep(100);
+        oneRun(3, items, q);
+        Thread.sleep(100);
+        print = true;
+
+        for (int i = 1; i <= maxStages; i += (i+1) >>> 1) {
+            oneRun(i, items, q);
+        }
+        pool.shutdown();
+        check(pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS));
+   }
+
+    class Stage implements Callable<Integer> {
+        final Queue<Integer> queue;
+        final CyclicBarrier barrier;
+        int items;
+        Stage (Queue<Integer> q, CyclicBarrier b, int items) {
+            queue = q;
+            barrier = b;
+            this.items = items;
+        }
+
+        public Integer call() {
+            // Repeatedly take something from queue if possible,
+            // transform it, and put back in.
+            try {
+                barrier.await();
+                int l = 4321;
+                int takes = 0;
+                for (;;) {
+                    Integer item = queue.poll();
+                    if (item != null) {
+                        ++takes;
+                        l = LoopHelpers.compute2(item.intValue());
+                    }
+                    else if (takes != 0) {
+                        totalItems.getAndAdd(-takes);
+                        takes = 0;
+                    }
+                    else if (totalItems.get() <= 0)
+                        break;
+                    l = LoopHelpers.compute1(l);
+                    if (items > 0) {
+                        --items;
+                        queue.offer(new Integer(l));
+                    }
+                    else if ( (l & (3 << 5)) == 0) // spinwait
+                        Thread.sleep(1);
+                }
+                return new Integer(l);
+            }
+            catch (Throwable t) { unexpected(t); return null; }
+        }
+    }
+
+    void oneRun(int n, int items, final Queue<Integer> q) throws Exception {
+        LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer();
+        CyclicBarrier barrier = new CyclicBarrier(n + 1, timer);
+        totalItems = new AtomicInteger(n * items);
+        ArrayList<Future<Integer>> results = new ArrayList<Future<Integer>>(n);
+        for (int i = 0; i < n; ++i)
+            results.add(pool.submit(new Stage(q, barrier, items)));
+
+        if (print)
+            System.out.print("Threads: " + n + "\t:");
+        barrier.await();
+        int total = 0;
+        for (int i = 0; i < n; ++i) {
+            Future<Integer> f = results.get(i);
+            Integer r = f.get();
+            total += r.intValue();
+        }
+        long endTime = System.nanoTime();
+        long time = endTime - timer.startTime;
+        if (print)
+            System.out.println(LoopHelpers.rightJustify(time / (items * n)) + " ns per item");
+        if (total == 0) // avoid overoptimization
+            System.out.println("useless result: " + total);
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new ConcurrentQueueLoops().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+/*
+ * @test
+ * @bug 6785442
+ * @summary Benchmark that tries to GC-tenure head, followed by
+ * many add/remove operations.
+ * @run main GCRetention 12345
+ */
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.LinkedList;
+import java.util.PriorityQueue;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Queue;
+import java.util.Map;
+
+public class GCRetention {
+    // Suitable for benchmarking.  Overriden by args[0] for testing.
+    int count = 1024 * 1024;
+
+    final Map<String,String> results = new ConcurrentHashMap<String,String>();
+
+    Collection<Queue<Boolean>> queues() {
+        List<Queue<Boolean>> queues = new ArrayList<Queue<Boolean>>();
+        queues.add(new ConcurrentLinkedQueue<Boolean>());
+        queues.add(new ArrayBlockingQueue<Boolean>(count, false));
+        queues.add(new ArrayBlockingQueue<Boolean>(count, true));
+        queues.add(new LinkedBlockingQueue<Boolean>());
+        queues.add(new LinkedBlockingDeque<Boolean>());
+        queues.add(new PriorityBlockingQueue<Boolean>());
+        queues.add(new PriorityQueue<Boolean>());
+        queues.add(new LinkedList<Boolean>());
+
+        try {
+            queues.add((Queue<Boolean>)
+                       Class.forName("java.util.concurrent.LinkedTransferQueue")
+                       .newInstance());
+        } catch (IllegalAccessException e) {
+        } catch (InstantiationException e) {
+        } catch (ClassNotFoundException e) {
+            // OK; not yet added to JDK
+        }
+
+        // Following additional implementations are available from:
+        // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
+        // queues.add(new LinkedTransferQueue<Boolean>());
+        // queues.add(new SynchronizedLinkedListQueue<Boolean>());
+
+        // Avoid "first fast, second slow" benchmark effect.
+        Collections.shuffle(queues);
+        return queues;
+    }
+
+    void prettyPrintResults() {
+        List<String> classNames = new ArrayList<String>(results.keySet());
+        Collections.sort(classNames);
+        int maxClassNameLength = 0;
+        int maxNanosLength = 0;
+        for (String name : classNames) {
+            if (maxClassNameLength < name.length())
+                maxClassNameLength = name.length();
+            if (maxNanosLength < results.get(name).length())
+                maxNanosLength = results.get(name).length();
+        }
+        String format = String.format("%%%ds %%%ds nanos/item%%n",
+                                      maxClassNameLength, maxNanosLength);
+        for (String name : classNames)
+            System.out.printf(format, name, results.get(name));
+    }
+
+    void test(String[] args) {
+        if (args.length > 0)
+            count = Integer.valueOf(args[0]);
+        // Warmup
+        for (Queue<Boolean> queue : queues())
+            test(queue);
+        results.clear();
+        for (Queue<Boolean> queue : queues())
+            test(queue);
+
+        prettyPrintResults();
+    }
+
+    void test(Queue<Boolean> q) {
+        long t0 = System.nanoTime();
+        for (int i = 0; i < count; i++)
+            check(q.add(Boolean.TRUE));
+        System.gc();
+        System.gc();
+        Boolean x;
+        while ((x = q.poll()) != null)
+            equal(x, Boolean.TRUE);
+        check(q.isEmpty());
+
+        for (int i = 0; i < 10 * count; i++) {
+            for (int k = 0; k < 3; k++)
+                check(q.add(Boolean.TRUE));
+            for (int k = 0; k < 3; k++)
+                if (q.poll() != Boolean.TRUE)
+                    fail();
+        }
+        check(q.isEmpty());
+
+        String className = q.getClass().getSimpleName();
+        long elapsed = System.nanoTime() - t0;
+        int nanos = (int) ((double) elapsed / (10 * 3 * count));
+        results.put(className, String.valueOf(nanos));
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new GCRetention().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+
+/*
+ * @test
+ * @bug 6805775 6815766
+ * @summary Check weak consistency of concurrent queue iterators
+ */
+
+@SuppressWarnings({"unchecked", "rawtypes"})
+public class IteratorWeakConsistency {
+
+    void test(String[] args) throws Throwable {
+        test(new LinkedBlockingQueue());
+        test(new LinkedBlockingQueue(20));
+        test(new LinkedBlockingDeque());
+        test(new LinkedBlockingDeque(20));
+        test(new ConcurrentLinkedQueue());
+        // Other concurrent queues (e.g. ArrayBlockingQueue) do not
+        // currently have weakly consistent iterators.
+        // test(new ArrayBlockingQueue(20));
+    }
+
+    void test(Queue q) throws Throwable {
+        // TODO: make this more general
+        for (int i = 0; i < 10; i++)
+            q.add(i);
+        Iterator it = q.iterator();
+        q.poll();
+        q.poll();
+        q.poll();
+        q.remove(7);
+        List list = new ArrayList();
+        while (it.hasNext())
+            list.add(it.next());
+        equal(list, Arrays.asList(0, 3, 4, 5, 6, 8, 9));
+        check(! list.contains(null));
+        System.out.printf("%s: %s%n",
+                          q.getClass().getSimpleName(),
+                          list);
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    static Class<?> thisClass = new Object(){}.getClass().getEnclosingClass();
+    public static void main(String[] args) throws Throwable {
+        new IteratorWeakConsistency().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/**
+ * Misc utilities in JSR166 performance tests
+ */
+
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
+
+class LoopHelpers {
+
+    // Some mindless computation to do between synchronizations...
+
+    /**
+     * generates 32 bit pseudo-random numbers.
+     * Adapted from http://www.snippets.org
+     */
+    public static int compute1(int x) {
+        int lo = 16807 * (x & 0xFFFF);
+        int hi = 16807 * (x >>> 16);
+        lo += (hi & 0x7FFF) << 16;
+        if ((lo & 0x80000000) != 0) {
+            lo &= 0x7fffffff;
+            ++lo;
+        }
+        lo += hi >>> 15;
+        if (lo == 0 || (lo & 0x80000000) != 0) {
+            lo &= 0x7fffffff;
+            ++lo;
+        }
+        return lo;
+    }
+
+    /**
+     *  Computes a linear congruential random number a random number
+     *  of times.
+     */
+    public static int compute2(int x) {
+        int loops = (x >>> 4) & 7;
+        while (loops-- > 0) {
+            x = (x * 2147483647) % 16807;
+        }
+        return x;
+    }
+
+    /**
+     * An actually useful random number generator, but unsynchronized.
+     * Basically same as java.util.Random.
+     */
+    public static class SimpleRandom {
+        private final static long multiplier = 0x5DEECE66DL;
+        private final static long addend = 0xBL;
+        private final static long mask = (1L << 48) - 1;
+        static final AtomicLong seq = new AtomicLong(1);
+        private long seed = System.nanoTime() + seq.getAndIncrement();
+
+        public void setSeed(long s) {
+            seed = s;
+        }
+
+        public int next() {
+            long nextseed = (seed * multiplier + addend) & mask;
+            seed = nextseed;
+            return ((int)(nextseed >>> 17)) & 0x7FFFFFFF;
+        }
+    }
+
+    public static class BarrierTimer implements Runnable {
+        public volatile long startTime;
+        public volatile long endTime;
+        public void run() {
+            long t = System.nanoTime();
+            if (startTime == 0)
+                startTime = t;
+            else
+                endTime = t;
+        }
+        public void clear() {
+            startTime = 0;
+            endTime = 0;
+        }
+        public long getTime() {
+            return endTime - startTime;
+        }
+    }
+
+    public static String rightJustify(long n) {
+        // There's probably a better way to do this...
+        String field = "         ";
+        String num = Long.toString(n);
+        if (num.length() >= field.length())
+            return num;
+        StringBuffer b = new StringBuffer(field);
+        b.replace(b.length()-num.length(), b.length(), num);
+        return b.toString();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,230 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/*
+ * @test
+ * @bug 6785442
+ * @summary Checks race between poll and remove(Object), while
+ * occasionally moonlighting as a microbenchmark.
+ * @run main RemovePollRace 12345
+ */
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Queue;
+import java.util.Map;
+
+public class RemovePollRace {
+    // Suitable for benchmarking.  Overriden by args[0] for testing.
+    int count = 1024 * 1024;
+
+    final Map<String,String> results = new ConcurrentHashMap<String,String>();
+
+    Collection<Queue<Boolean>> concurrentQueues() {
+        List<Queue<Boolean>> queues = new ArrayList<Queue<Boolean>>();
+        queues.add(new ConcurrentLinkedQueue<Boolean>());
+        queues.add(new ArrayBlockingQueue<Boolean>(count, false));
+        queues.add(new ArrayBlockingQueue<Boolean>(count, true));
+        queues.add(new LinkedBlockingQueue<Boolean>());
+        queues.add(new LinkedBlockingDeque<Boolean>());
+
+        try {
+            queues.add((Queue<Boolean>)
+                       Class.forName("java.util.concurrent.LinkedTransferQueue")
+                       .newInstance());
+        } catch (IllegalAccessException e) {
+        } catch (InstantiationException e) {
+        } catch (ClassNotFoundException e) {
+            // OK; not yet added to JDK
+        }
+
+        // Following additional implementations are available from:
+        // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html
+        // queues.add(new LinkedTransferQueue<Boolean>());
+        // queues.add(new SynchronizedLinkedListQueue<Boolean>());
+
+        // Avoid "first fast, second slow" benchmark effect.
+        Collections.shuffle(queues);
+        return queues;
+    }
+
+    void prettyPrintResults() {
+        List<String> classNames = new ArrayList<String>(results.keySet());
+        Collections.sort(classNames);
+        int maxClassNameLength = 0;
+        int maxNanosLength = 0;
+        for (String name : classNames) {
+            if (maxClassNameLength < name.length())
+                maxClassNameLength = name.length();
+            if (maxNanosLength < results.get(name).length())
+                maxNanosLength = results.get(name).length();
+        }
+        String format = String.format("%%%ds %%%ds nanos/item%%n",
+                                      maxClassNameLength, maxNanosLength);
+        for (String name : classNames)
+            System.out.printf(format, name, results.get(name));
+    }
+
+    void test(String[] args) throws Throwable {
+        if (args.length > 0)
+            count = Integer.valueOf(args[0]);
+        // Warmup
+        for (Queue<Boolean> queue : concurrentQueues())
+            test(queue);
+        results.clear();
+        for (Queue<Boolean> queue : concurrentQueues())
+            test(queue);
+
+        prettyPrintResults();
+    }
+
+    void await(CountDownLatch latch) {
+        try { latch.await(); }
+        catch (InterruptedException e) { unexpected(e); }
+    }
+
+    void test(final Queue<Boolean> q) throws Throwable {
+        long t0 = System.nanoTime();
+        final int SPINS = 5;
+        final AtomicLong removes = new AtomicLong(0);
+        final AtomicLong polls = new AtomicLong(0);
+        final int adderCount =
+            Math.max(1, Runtime.getRuntime().availableProcessors() / 4);
+        final int removerCount =
+            Math.max(1, Runtime.getRuntime().availableProcessors() / 4);
+        final int pollerCount = removerCount;
+        final int threadCount = adderCount + removerCount + pollerCount;
+        final CountDownLatch startingGate = new CountDownLatch(1);
+        final CountDownLatch addersDone = new CountDownLatch(adderCount);
+        final Runnable remover = new Runnable() {
+            public void run() {
+                await(startingGate);
+                int spins = 0;
+                for (;;) {
+                    boolean quittingTime = (addersDone.getCount() == 0);
+                    if (q.remove(Boolean.TRUE))
+                        removes.getAndIncrement();
+                    else if (quittingTime)
+                        break;
+                    else if (++spins > SPINS) {
+                        Thread.yield();
+                        spins = 0;
+                    }}}};
+        final Runnable poller = new Runnable() {
+            public void run() {
+                await(startingGate);
+                int spins = 0;
+                for (;;) {
+                    boolean quittingTime = (addersDone.getCount() == 0);
+                    if (q.poll() == Boolean.TRUE)
+                        polls.getAndIncrement();
+                    else if (quittingTime)
+                        break;
+                    else if (++spins > SPINS) {
+                        Thread.yield();
+                        spins = 0;
+                    }}}};
+        final Runnable adder = new Runnable() {
+            public void run() {
+                await(startingGate);
+                for (int i = 0; i < count; i++) {
+                    for (;;) {
+                        try { q.add(Boolean.TRUE); break; }
+                        catch (IllegalStateException e) { Thread.yield(); }
+                    }
+                }
+                addersDone.countDown();
+            }};
+
+        final List<Thread> adders   = new ArrayList<Thread>();
+        final List<Thread> removers = new ArrayList<Thread>();
+        final List<Thread> pollers  = new ArrayList<Thread>();
+        for (int i = 0; i < adderCount; i++)
+            adders.add(checkedThread(adder));
+        for (int i = 0; i < removerCount; i++)
+            removers.add(checkedThread(remover));
+        for (int i = 0; i < pollerCount; i++)
+            pollers.add(checkedThread(poller));
+
+        final List<Thread> allThreads = new ArrayList<Thread>();
+        allThreads.addAll(removers);
+        allThreads.addAll(pollers);
+        allThreads.addAll(adders);
+
+        for (Thread t : allThreads)
+            t.start();
+        startingGate.countDown();
+        for (Thread t : allThreads)
+            t.join();
+
+        String className = q.getClass().getSimpleName();
+        long elapsed = System.nanoTime() - t0;
+        int nanos = (int) ((double) elapsed / (adderCount * count));
+        results.put(className, String.valueOf(nanos));
+        if (removes.get() + polls.get() != adderCount * count) {
+            String msg = String.format
+                ("class=%s removes=%s polls=%d count=%d",
+                 className, removes.get(), polls.get(), count);
+            fail(msg);
+        }
+    }
+
+    //--------------------- Infrastructure ---------------------------
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
+        if (x == null ? y == null : x.equals(y)) pass();
+        else fail(x + " not equal to " + y);}
+    public static void main(String[] args) throws Throwable {
+        new RemovePollRace().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
+        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
+        if (failed > 0) throw new AssertionError("Some tests failed");}
+    Thread checkedThread(final Runnable r) {
+        return new Thread() {public void run() {
+            try {r.run();} catch (Throwable t) {unexpected(t);}}};}
+}
--- a/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java	Tue Aug 18 19:53:43 2009 -0700
@@ -28,62 +28,74 @@
  * @author Martin Buchholz
  */
 
+import java.util.*;
 import java.util.concurrent.*;
 
 public class OfferRemoveLoops {
-    private static void realMain(String[] args) throws Throwable {
+    void test(String[] args) throws Throwable {
         testQueue(new LinkedBlockingQueue<String>(10));
         testQueue(new LinkedBlockingQueue<String>());
         testQueue(new LinkedBlockingDeque<String>(10));
         testQueue(new LinkedBlockingDeque<String>());
         testQueue(new ArrayBlockingQueue<String>(10));
         testQueue(new PriorityBlockingQueue<String>(10));
+        testQueue(new ConcurrentLinkedQueue<String>());
     }
 
-    private abstract static class ControlledThread extends Thread {
+    abstract class CheckedThread extends Thread {
         abstract protected void realRun();
         public void run() {
             try { realRun(); } catch (Throwable t) { unexpected(t); }
         }
     }
 
-    private static void testQueue(final BlockingQueue<String> q) throws Throwable {
-        System.out.println(q.getClass());
-        final int count = 10000;
-        final long quittingTime = System.nanoTime() + 1L * 1000L * 1000L * 1000L;
-        Thread t1 = new ControlledThread() {
-                protected void realRun() {
-                    for (int i = 0, j = 0; i < count; i++)
-                        while (! q.remove(String.valueOf(i))
-                               && System.nanoTime() - quittingTime < 0)
-                            Thread.yield();}};
-        Thread t2 = new ControlledThread() {
-                protected void realRun() {
-                    for (int i = 0, j = 0; i < count; i++)
-                        while (! q.offer(String.valueOf(i))
-                               && System.nanoTime() - quittingTime < 0)
-                            Thread.yield();}};
+    void testQueue(final Queue<String> q) throws Throwable {
+        System.out.println(q.getClass().getSimpleName());
+        final int count = 1000 * 1000;
+        final long testDurationSeconds = 1L;
+        final long testDurationMillis = testDurationSeconds * 1000L;
+        final long quittingTimeNanos
+            = System.nanoTime() + testDurationSeconds * 1000L * 1000L * 1000L;
+        Thread t1 = new CheckedThread() {
+            protected void realRun() {
+                for (int i = 0; i < count; i++) {
+                    if ((i % 1024) == 0 &&
+                        System.nanoTime() - quittingTimeNanos > 0)
+                        return;
+                    while (! q.remove(String.valueOf(i)))
+                        Thread.yield();
+                }}};
+        Thread t2 = new CheckedThread() {
+            protected void realRun() {
+                for (int i = 0; i < count; i++) {
+                    if ((i % 1024) == 0 &&
+                        System.nanoTime() - quittingTimeNanos > 0)
+                        return;
+                    while (! q.offer(String.valueOf(i)))
+                        Thread.yield();
+                    }}};
         t1.setDaemon(true); t2.setDaemon(true);
         t1.start(); t2.start();
-        t1.join(10000); t2.join(10000);
+        t1.join(10 * testDurationMillis);
+        t2.join(10 * testDurationMillis);
         check(! t1.isAlive());
         check(! t2.isAlive());
     }
 
     //--------------------- Infrastructure ---------------------------
-    static volatile int passed = 0, failed = 0;
-    static void pass() { passed++; }
-    static void fail() { failed++; Thread.dumpStack(); }
-    static void unexpected(Throwable t) { failed++; t.printStackTrace(); }
-    static void check(boolean cond) { if (cond) pass(); else fail(); }
-    static void equal(Object x, Object y) {
+    volatile int passed = 0, failed = 0;
+    void pass() {passed++;}
+    void fail() {failed++; Thread.dumpStack();}
+    void fail(String msg) {System.err.println(msg); fail();}
+    void unexpected(Throwable t) {failed++; t.printStackTrace();}
+    void check(boolean cond) {if (cond) pass(); else fail();}
+    void equal(Object x, Object y) {
         if (x == null ? y == null : x.equals(y)) pass();
-        else {System.out.println(x + " not equal to " + y); fail(); }}
-
+        else fail(x + " not equal to " + y);}
     public static void main(String[] args) throws Throwable {
-        try { realMain(args); } catch (Throwable t) { unexpected(t); }
-
+        new OfferRemoveLoops().instanceMain(args);}
+    public void instanceMain(String[] args) throws Throwable {
+        try {test(args);} catch (Throwable t) {unexpected(t);}
         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
-        if (failed > 0) throw new Exception("Some tests failed");
-    }
+        if (failed > 0) throw new AssertionError("Some tests failed");}
 }
--- a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -56,6 +56,11 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     NULL=NUL
     PS=";"
@@ -69,7 +74,7 @@
 
 ${TESTJAVA}${FS}bin${FS}javac \
     -d . \
-    -classpath ${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar \
+    -classpath "${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar" \
     ${TESTSRC}${FS}FailOverTest.java
 
 if [ $? -ne 0 ]; then
@@ -77,7 +82,7 @@
 fi
 
 ${TESTJAVA}${FS}bin${FS}java \
-    -classpath ${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}. \
+    -classpath "${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}." \
     FailOverTest
 result=$?
 
--- a/jdk/test/javax/security/auth/Subject/doAs/Test.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/javax/security/auth/Subject/doAs/Test.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -43,6 +43,11 @@
     FS="/"
     RM="/bin/rm -f"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    RM="rm"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/swing/plaf/synth/Test6660049.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6660049 6849518
+ * @summary Tests the Region initialization
+ * @author Sergey Malenkov
+ */
+
+import sun.awt.SunToolkit;
+
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.SwingUtilities;
+import javax.swing.plaf.synth.Region;
+import javax.swing.plaf.synth.SynthLookAndFeel;
+
+public class Test6660049 implements Runnable {
+    public static void main(String[] args) {
+        SwingUtilities.invokeLater(new Test6660049(
+                javax.swing.JButton.class,
+                javax.swing.JCheckBox.class,
+                javax.swing.JCheckBoxMenuItem.class,
+                javax.swing.JColorChooser.class,
+                javax.swing.JComboBox.class,
+                javax.swing.JDesktopPane.class,
+                javax.swing.JEditorPane.class,
+                javax.swing.JFileChooser.class,
+                javax.swing.JFormattedTextField.class,
+                javax.swing.JInternalFrame.class,
+                javax.swing.JLabel.class,
+                javax.swing.JList.class,
+                javax.swing.JMenu.class,
+                javax.swing.JMenuBar.class,
+                javax.swing.JMenuItem.class,
+                javax.swing.JOptionPane.class,
+                javax.swing.JPanel.class,
+                javax.swing.JPasswordField.class,
+                javax.swing.JPopupMenu.class,
+                javax.swing.JProgressBar.class,
+                javax.swing.JRadioButton.class,
+                javax.swing.JRadioButtonMenuItem.class,
+                javax.swing.JRootPane.class,
+                javax.swing.JScrollBar.class,
+                javax.swing.JScrollPane.class,
+                javax.swing.JSeparator.class,
+                javax.swing.JSlider.class,
+                javax.swing.JSpinner.class,
+                javax.swing.JSplitPane.class,
+                javax.swing.JTabbedPane.class,
+                javax.swing.JTable.class,
+                javax.swing.JTextArea.class,
+                javax.swing.JTextField.class,
+                javax.swing.JTextPane.class,
+                javax.swing.JToggleButton.class,
+                javax.swing.JToolBar.class,
+                javax.swing.JToolTip.class,
+                javax.swing.JTree.class,
+                javax.swing.JViewport.class,
+                javax.swing.table.JTableHeader.class));
+    }
+
+    private final Class<? extends JComponent>[] types;
+    private final Region region;
+
+    private Test6660049(Class<? extends JComponent>... types) {
+        this.types = types;
+        run();
+
+        this.region = new Region("Button", "ButtonUI", true) {
+            @Override
+            public String getName() {
+                throw new Error("6660049: exploit is available");
+            }
+        };
+    }
+
+    public void run() {
+        if (this.region != null) {
+            SunToolkit.createNewAppContext();
+        }
+        for (Class<? extends JComponent> type : this.types) {
+            Region region = getRegion(type);
+            if (region == null) {
+                throw new Error("6849518: region is not initialized");
+            }
+        }
+        getRegion(JButton.class).getName();
+    }
+
+    private static Region getRegion(Class<? extends JComponent> type) {
+        try {
+            return SynthLookAndFeel.getRegion(type.newInstance());
+        }
+        catch (IllegalAccessException exception) {
+            throw new Error("unexpected exception", exception);
+        }
+        catch (InstantiationException exception) {
+            throw new Error("unexpected exception", exception);
+        }
+    }
+}
--- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-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
@@ -23,9 +23,7 @@
 
 /**
  * @test
- * @bug 4635230
- * @bug 6283345
- * @bug 6303830
+ * @bug 4635230 6283345 6303830 6824440
  * @summary Basic unit tests for generating XML Signatures with JSR 105
  * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
  *     X509KeySelector.java GenerationTests.java
@@ -248,8 +246,14 @@
         System.out.println("* Generating signature-enveloping-hmac-sha1-40.xml");
         SignatureMethod hmacSha1 = fac.newSignatureMethod
             (SignatureMethod.HMAC_SHA1, new HMACParameterSpec(40));
-        test_create_signature_enveloping(sha1, hmacSha1, null,
-            getSecretKey("secret".getBytes("ASCII")), sks, false);
+        try {
+            test_create_signature_enveloping(sha1, hmacSha1, null,
+                getSecretKey("secret".getBytes("ASCII")), sks, false);
+        } catch (Exception e) {
+            if (!(e instanceof XMLSignatureException)) {
+                throw e;
+            }
+        }
         System.out.println();
     }
 
--- a/jdk/test/javax/xml/crypto/dsig/ValidationTests.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/javax/xml/crypto/dsig/ValidationTests.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2005-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
@@ -23,9 +23,7 @@
 
 /**
  * @test
- * @bug 4635230
- * @bug 6365103
- * @bug 6366054
+ * @bug 4635230 6365103 6366054 6824440
  * @summary Basic unit tests for validating XML Signatures with JSR 105
  * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java
  *     X509KeySelector.java ValidationTests.java
@@ -42,6 +40,7 @@
 import javax.xml.crypto.URIReference;
 import javax.xml.crypto.URIReferenceException;
 import javax.xml.crypto.XMLCryptoContext;
+import javax.xml.crypto.dsig.XMLSignatureException;
 import javax.xml.crypto.dsig.XMLSignatureFactory;
 
 /**
@@ -68,7 +67,6 @@
         "signature-enveloping-dsa.xml",
         "signature-enveloping-rsa.xml",
         "signature-enveloping-hmac-sha1.xml",
-        "signature-enveloping-hmac-sha1-40.xml",
         "signature-external-dsa.xml",
         "signature-external-b64-dsa.xml",
         "signature-retrievalmethod-rawx509crt.xml",
@@ -106,7 +104,6 @@
         KVKS,
         KVKS,
         SKKS,
-        SKKS,
         KVKS,
         KVKS,
         CKS,
@@ -146,6 +143,36 @@
             atLeastOneFailed = true;
         }
 
+        System.out.println("Validating signature-enveloping-hmac-sha1-40.xml");
+        try {
+            test_signature("signature-enveloping-hmac-sha1-40.xml", SKKS, false);
+            System.out.println("FAILED");
+            atLeastOneFailed = true;
+        } catch (XMLSignatureException xse) {
+            System.out.println(xse.getMessage());
+            System.out.println("PASSED");
+        }
+
+        System.out.println("Validating signature-enveloping-hmac-sha1-trunclen-0-attack.xml");
+        try {
+            test_signature("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", SKKS, false);
+            System.out.println("FAILED");
+            atLeastOneFailed = true;
+        } catch (XMLSignatureException xse) {
+            System.out.println(xse.getMessage());
+            System.out.println("PASSED");
+        }
+
+        System.out.println("Validating signature-enveloping-hmac-sha1-trunclen-8-attack.xml");
+        try {
+            test_signature("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", SKKS, false);
+            System.out.println("FAILED");
+            atLeastOneFailed = true;
+        } catch (XMLSignatureException xse) {
+            System.out.println(xse.getMessage());
+            System.out.println("PASSED");
+        }
+
         if (atLeastOneFailed) {
             throw new Exception
                 ("At least one signature did not validate as expected");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-0-attack.xml	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+  <SignedInfo>
+    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+      <HMACOutputLength>0</HMACOutputLength>
+    </SignatureMethod>
+    <Reference URI="#object">
+      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+      <DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue>
+    </Reference>
+  </SignedInfo>
+  <SignatureValue>
+  </SignatureValue>
+  <Object Id="object">some other text</Object>
+</Signature>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-8-attack.xml	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+  <SignedInfo>
+    <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />
+    <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1">
+      <HMACOutputLength>8</HMACOutputLength>
+    </SignatureMethod>
+    <Reference URI="#object">
+      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+      <DigestValue>nz4GS0NbH2SrWlD/4fX313CoTzc=</DigestValue>
+    </Reference>
+  </SignedInfo>
+  <SignatureValue>
+    Qw==
+  </SignatureValue>
+  <Object Id="object">some other text</Object>
+</Signature>
--- a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -56,6 +56,12 @@
     FS="/"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    TMP=/tmp
+    ;;
   Windows_95 | Windows_98 | Windows_NT )
     NULL=NUL
     PS=";"
--- a/jdk/test/sun/net/www/MarkResetTest.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/net/www/MarkResetTest.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -32,6 +32,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -32,6 +32,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -32,6 +32,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/sun/net/www/protocol/jar/B5105410.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/net/www/protocol/jar/B5105410.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -39,6 +39,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -28,23 +28,54 @@
 # @summary various resource and classloading bugs related to jar files
 #set -x
 DEST=`pwd`
+
+OS=`uname -s`
+case "$OS" in
+  SunOS )
+    PS=":"
+    FS="/"
+    ;;
+  Linux )
+    PS=":"
+    FS="/"
+    ;;
+  Windows* )
+    PS=";"
+    FS="\\"
+    ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    #
+    # javac does not like /cygdrive produced by `pwd`.
+    #
+    DEST=`cygpath -d ${DEST}`
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
+esac
+
 #
 # build jar1 
 #
-mkdir ${DEST}/jar1
-cd ${TESTSRC}/etc/jar1 
-cp -r . ${DEST}/jar1
-${TESTJAVA}/bin/javac -d ${DEST}/jar1 ${TESTSRC}/src/jar1/LoadResourceBundle.java
-${TESTJAVA}/bin/javac -d ${DEST}/jar1 ${TESTSRC}/src/jar1/GetResource.java
-cd ${DEST}/jar1
-${TESTJAVA}/bin/jar cfM jar1.jar jar1 res1.txt
+mkdir -p ${DEST}${FS}jar1
+cd ${TESTSRC}${FS}etc${FS}jar1 
+cp -r . ${DEST}${FS}jar1
+${TESTJAVA}${FS}bin${FS}javac -d ${DEST}${FS}jar1 \
+    ${TESTSRC}${FS}src${FS}jar1${FS}LoadResourceBundle.java
+${TESTJAVA}${FS}bin${FS}javac -d ${DEST}${FS}jar1 \
+    ${TESTSRC}${FS}src${FS}jar1${FS}GetResource.java
+cd ${DEST}${FS}jar1
+${TESTJAVA}${FS}bin${FS}jar cfM jar1.jar jar1 res1.txt
 mv jar1.jar ..
 #
 # build the test sources and run them
 #
-${TESTJAVA}/bin/javac -d ${DEST} ${TESTSRC}/src/test/*.java
+${TESTJAVA}${FS}bin${FS}javac -d ${DEST} ${TESTSRC}${FS}src${FS}test${FS}*.java
 cd ${DEST}
-${TESTJAVA}/bin/java RunAllTests
+${TESTJAVA}${FS}bin${FS}java RunAllTests
 result=$?
 if [ "$result" -ne "0" ]; then
     exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ec/TestEC.java	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6840752
+ * @summary  Provide out-of-the-box support for ECC algorithms
+ * @library ../pkcs11
+ * @library ../pkcs11/ec
+ * @run main TestEC
+ */
+
+import java.security.Provider;
+
+/*
+ * Leverage the collection of EC tests used by PKCS11
+ *
+ * NOTE: the following files were copied here from the PKCS11 EC Test area
+ *       and must be kept in sync with the originals:
+ *
+ *           ../pkcs11/ec/p12passwords.txt
+ *           ../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12
+ *           ../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12
+ */
+
+public class TestEC {
+
+    public static void main(String[] args) throws Exception {
+        Provider p = new sun.security.ec.SunEC();
+        System.out.println("Running tests with " + p.getName() +
+            " provider...\n");
+
+        long start = System.currentTimeMillis();
+        new TestECDH().main(p);
+        new TestECDSA().main(p);
+        //new TestCurves().main(p);
+        new TestKeyFactory().main(p);
+        new TestECGenSpec().main(p);
+        new ReadPKCS12().main(p);
+        //new ReadCertificates().main(p);
+        long stop = System.currentTimeMillis();
+
+        System.out.println("\nCompleted tests with " + p.getName() +
+            " provider (" + (stop - start) + " ms).");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ec/p12passwords.txt	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,18 @@
+# MS_ECC_Samples.zip
+256-ecc.pfx ecc
+256_2-ecc.pfx ecc
+384-ecc.pfx ecc
+521-ecc.pfx ecc
+# MS_Client_certs.zip
+eccclicert256.pfx 1
+eccclicert384.pfx 1
+eccclicert521.pfx 1
+# NSS_ECC_PKCS12.zip
+ECCp160.p12 ecc
+ECCp192.p12 ecc
+ECCp224.p12 ecc
+ECCp256.p12 ecc
+ECCp384.p12 ecc
+ECCp521.p12 ecc
+# All other files
+* password
Binary file jdk/test/sun/security/ec/pkcs12/secp256r1server-secp384r1ca.p12 has changed
Binary file jdk/test/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12 has changed
--- a/jdk/test/sun/security/krb5/ConfPlusProp.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/krb5/ConfPlusProp.java	Tue Aug 18 19:53:43 2009 -0700
@@ -23,7 +23,7 @@
 /*
  * @test
  * @bug 6857795
- * @buf 6858589
+ * @bug 6858589
  * @summary krb5.conf ignored if system properties on realm and kdc are provided
  */
 
--- a/jdk/test/sun/security/krb5/auto/Context.java	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/krb5/auto/Context.java	Tue Aug 18 19:53:43 2009 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2008-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
@@ -22,6 +22,7 @@
  */
 
 import com.sun.security.auth.module.Krb5LoginModule;
+import java.security.Key;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
@@ -38,6 +39,9 @@
 import org.ietf.jgss.GSSName;
 import org.ietf.jgss.MessageProp;
 import org.ietf.jgss.Oid;
+import com.sun.security.jgss.ExtendedGSSContext;
+import com.sun.security.jgss.InquireType;
+import com.sun.security.jgss.AuthorizationDataEntry;
 
 /**
  * Context of a JGSS subject, encapsulating Subject and GSSContext.
@@ -276,6 +280,34 @@
                 }
             }
         }
+        if (x != null && x instanceof ExtendedGSSContext) {
+            if (x.isEstablished()) {
+                ExtendedGSSContext ex = (ExtendedGSSContext)x;
+                Key k = (Key)ex.inquireSecContext(
+                        InquireType.KRB5_GET_SESSION_KEY);
+                if (k == null) {
+                    throw new Exception("Session key cannot be null");
+                }
+                System.out.println("Session key is: " + k);
+                boolean[] flags = (boolean[])ex.inquireSecContext(
+                        InquireType.KRB5_GET_TKT_FLAGS);
+                if (flags == null) {
+                    throw new Exception("Ticket flags cannot be null");
+                }
+                System.out.println("Ticket flags is: " + Arrays.toString(flags));
+                String authTime = (String)ex.inquireSecContext(
+                        InquireType.KRB5_GET_AUTHTIME);
+                if (authTime == null) {
+                    throw new Exception("Auth time cannot be null");
+                }
+                System.out.println("AuthTime is: " + authTime);
+                if (!x.isInitiator()) {
+                    AuthorizationDataEntry[] ad = (AuthorizationDataEntry[])ex.inquireSecContext(
+                            InquireType.KRB5_GET_AUTHZ_DATA);
+                    System.out.println("AuthzData is: " + Arrays.toString(ad));
+                }
+            }
+        }
     }
 
     /**
--- a/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -68,6 +68,20 @@
     CP="cp"
     CHMOD="chmod"
     ;;
+  CYGWIN* )
+    FS="/"
+    PS=";"
+    CP="cp"
+    CHMOD="chmod"
+    #
+    # javac does not like /cygdrive produced by `pwd`
+    #
+    TESTSRC=`cygpath -d ${TESTSRC}`
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
 esac
 
 # compile test
--- a/jdk/test/sun/security/pkcs11/Provider/Login.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/pkcs11/Provider/Login.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -69,6 +69,20 @@
     CP="cp"
     CHMOD="chmod"
     ;;
+  CYGWIN* )
+    FS="/"
+    PS=";"
+    CP="cp"
+    CHMOD="chmod"
+    #
+    # javac does not like /cygdrive produced by `pwd`
+    #
+    TESTSRC=`cygpath -d ${TESTSRC}`
+    ;;
+  * )
+    echo "Unrecognized system!"
+    exit 1;
+    ;;
 esac
 
 # first make cert/key DBs writable
--- a/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -55,6 +55,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
--- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -43,10 +43,17 @@
 OS=`uname -s`
 case "$OS" in
     SunOS | Linux )
+        FILESEP="/"
 	PATHSEP=":"
 	;;
 
+    CYGWIN* )
+        FILESEP="/"
+	PATHSEP=";"
+	;;
+
     Windows* )
+        FILESEP="\\"
 	PATHSEP=";"
 	;;
 esac
@@ -56,11 +63,13 @@
 #
 # Compile the tests, package into their respective jars
 #
-${TESTJAVA}/bin/javac -d . \
-    ${TESTSRC}/NotifyHandshakeTest.java \
-    ${TESTSRC}/NotifyHandshakeTestHeyYou.java
-${TESTJAVA}/bin/jar -cvf com.jar com/NotifyHandshakeTest*.class
-${TESTJAVA}/bin/jar -cvf edu.jar edu/NotifyHandshakeTestHeyYou.class
+${TESTJAVA}${FILESEP}bin${FILESEP}javac -d . \
+    ${TESTSRC}${FILESEP}NotifyHandshakeTest.java \
+    ${TESTSRC}${FILESEP}NotifyHandshakeTestHeyYou.java
+${TESTJAVA}${FILESEP}bin${FILESEP}jar -cvf com.jar \
+    com${FILESEP}NotifyHandshakeTest*.class
+${TESTJAVA}${FILESEP}bin${FILESEP}jar -cvf edu.jar \
+    edu${FILESEP}NotifyHandshakeTestHeyYou.class
 
 #
 # Don't want the original class files to be used, because
@@ -73,11 +82,11 @@
 # This is the only thing we really care about as far as
 # test status goes.
 #
-${TESTJAVA}/bin/java \
+${TESTJAVA}${FILESEP}bin${FILESEP}java \
     -Dtest.src=${TESTSRC} \
     -classpath "com.jar${PATHSEP}edu.jar" \
     -Djava.security.manager \
-    -Djava.security.policy=${TESTSRC}/NotifyHandshakeTest.policy \
+    -Djava.security.policy=${TESTSRC}${FILESEP}NotifyHandshakeTest.policy \
     com.NotifyHandshakeTest
 retval=$?
 
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -36,6 +36,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
@@ -46,6 +50,7 @@
     ;;
 esac
 
-${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxy.java
+${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java \
+    ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxy.java
 ${TESTJAVA}${FS}bin${FS}java PostThruProxy ${HOSTNAME} ${TESTSRC}
 exit
--- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -36,6 +36,10 @@
     PS=":"
     FS="/"
     ;;
+  CYGWIN* )
+    PS=";"
+    FS="/"
+    ;;
   Windows* )
     PS=";"
     FS="\\"
@@ -46,6 +50,8 @@
     ;;
 esac
 
-${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxyWithAuth.java
+${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java \
+    ${TESTSRC}${FS}ProxyTunnelServer.java \
+    ${TESTSRC}${FS}PostThruProxyWithAuth.java
 ${TESTJAVA}${FS}bin${FS}java PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC}
 exit
--- a/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -53,6 +53,13 @@
     CP="${FS}bin${FS}cp -f"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    CP="cp -f"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     PS=";"
--- a/jdk/test/sun/security/tools/jarsigner/PercentSign.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/jarsigner/PercentSign.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -53,6 +53,13 @@
     CP="${FS}bin${FS}cp -f"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    CP="cp -f"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     PS=";"
--- a/jdk/test/sun/security/tools/jarsigner/oldsig.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/jarsigner/oldsig.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -49,6 +49,13 @@
     CP="${FS}bin${FS}cp -f"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    CP="cp -f"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     PS=";"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/tools/jarsigner/samename.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+# 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.
+#
+
+# @test
+# @bug 6866479
+# @summary libzip.so caused JVM to crash when running jarsigner
+#
+
+if [ "${TESTJAVA}" = "" ] ; then
+  JAVAC_CMD=`which javac`
+  TESTJAVA=`dirname $JAVAC_CMD`/..
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  Windows_* | CYGWIN* )
+    SIGNEDJAR=EM.jar
+    FS="\\"
+    ;;
+  * )
+    SIGNEDJAR=em.jar
+    FS="/"
+    ;;
+esac
+
+KS=samename.jks
+JFILE=em.jar
+
+KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
+JAR=$TESTJAVA${FS}bin${FS}jar
+JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
+
+rm $KS $JFILE $SIGNEDJAR
+echo A > A
+$JAR cvf $JFILE A
+
+$KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300
+
+$JARSIGNER -keystore $KS -storepass changeit -signedjar $SIGNEDJAR $JFILE a
+
--- a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -52,6 +52,12 @@
     FS="/"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     PS=";"
@@ -66,14 +72,21 @@
 
 # the test code
 #genkey
-${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias dummyTestCA -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreCA.dks -storepass storepass -storetype "dks" -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
+${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias dummyTestCA \
+    -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" \
+    -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 \
+    -keypass storepass -keystore keystoreCA.dks -storepass storepass \
+    -storetype "dks" -provider "org.test.dummy.DummyProvider" \
+    -providerPath ${TESTCLASSES}
 
 if [ $? -ne 0 ]; then 
     exit 1
 fi
 
 #Change keystore password
-${TESTJAVA}${FS}bin${FS}keytool -storepasswd -new storepass2 -keystore keystoreCA.dks -storetype "dks" -storepass storepass -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
+${TESTJAVA}${FS}bin${FS}keytool -storepasswd -new storepass2 \
+    -keystore keystoreCA.dks -storetype "dks" -storepass storepass \
+    -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
 
 if [ $? -ne 0 ]; then 
     exit 1
@@ -81,21 +94,29 @@
 
 
 #Change keystore key password
-${TESTJAVA}${FS}bin${FS}keytool -keypasswd -alias "dummyTestCA" -keypass storepass -new keypass -keystore keystoreCA.dks -storetype "dks" -storepass storepass2 -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
+${TESTJAVA}${FS}bin${FS}keytool -keypasswd -alias "dummyTestCA" \
+    -keypass storepass -new keypass -keystore keystoreCA.dks \
+    -storetype "dks" -storepass storepass2 \
+    -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
 
 if [ $? -ne 0 ]; then 
     exit 1
 fi
 
 #Export certificate
-${TESTJAVA}${FS}bin${FS}keytool -v -export -rfc -alias "dummyTestCA" -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dks" -storepass storepass2 -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
+${TESTJAVA}${FS}bin${FS}keytool -v -export -rfc -alias "dummyTestCA" \
+    -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dks" \
+    -storepass storepass2 -provider "org.test.dummy.DummyProvider" \
+    -providerPath ${TESTCLASSES}
 
 if [ $? -ne 0 ]; then 
     exit 1
 fi
 
 #list keystore
-${TESTJAVA}${FS}bin${FS}keytool -v -list -keystore keystoreCA.dks -storetype "dks" -storepass storepass2 -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
+${TESTJAVA}${FS}bin${FS}keytool -v -list -keystore keystoreCA.dks \
+    -storetype "dks" -storepass storepass2 \
+    -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES}
 
 if [ $? -ne 0 ]; then 
     exit 1
--- a/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -55,6 +55,10 @@
     PATHSEP=":"
     FILESEP="/"
     ;;
+  CYGWIN* )
+    PATHSEP=";"
+    FILESEP="/"
+    ;;
   Windows* )
     PATHSEP=";"
     FILESEP="\\"
--- a/jdk/test/sun/security/tools/keytool/NoExtNPE.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/NoExtNPE.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -48,6 +48,9 @@
   Linux )
     FILESEP="/"
     ;;
+  CYGWIN* )
+    FILESEP="/"
+    ;;
   Windows* )
     FILESEP="\\"
     ;;
--- a/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -51,6 +51,12 @@
     FS="/"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     PS=";"
--- a/jdk/test/sun/security/tools/keytool/StandardAlgName.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/StandardAlgName.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -52,6 +52,12 @@
     FS="/"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     PS=";"
--- a/jdk/test/sun/security/tools/keytool/i18n.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/i18n.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -52,6 +52,12 @@
     FS="/"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    PS=";"
+    FS="/"
+    TMP=/tmp
+    ;;
   Windows* )
     NULL=NUL
     PS=";"
--- a/jdk/test/sun/security/tools/keytool/printssl.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/printssl.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -40,6 +40,9 @@
   SunOS | Linux )
     FS="/"
     ;;
+  CYGWIN* )
+    FS="/"
+    ;;
   Windows_* )
     FS="\\"
     ;;
--- a/jdk/test/sun/security/tools/keytool/resource.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/resource.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -48,6 +48,11 @@
     FS="/"
     TMP=/tmp
     ;;
+  CYGWIN* )
+    NULL=/dev/null
+    FS="/"
+    TMP=/tmp
+    ;;
   Windows_* )
     NULL=NUL
     FS="\\"
--- a/jdk/test/sun/security/tools/keytool/standard.sh	Tue Aug 18 19:50:12 2009 +0100
+++ b/jdk/test/sun/security/tools/keytool/standard.sh	Tue Aug 18 19:53:43 2009 -0700
@@ -24,6 +24,7 @@
 # @test
 # @summary (almost) all keytool behaviors
 # @author Weijun Wang
+# @run shell/timeout=600 standard.sh
 #
 # This test is always excecuted.
 #
@@ -43,11 +44,15 @@
 # set platform-dependent variables
 OS=`uname -s`
 case "$OS" in
+  SunOS | Linux | CYGWIN* )
+    FS="/"
+    ;;
   Windows_* )
     FS="\\"
     ;;
   * )
-    FS="/"
+    echo "Unrecognized system!"
+    exit 1;
     ;;
 esac