Merge
authorduke
Wed, 05 Jul 2017 17:01:09 +0200
changeset 3888 37dcc8290671
parent 3887 2d600411d2b7 (current diff)
parent 3883 94ee7c22fab7 (diff)
child 3899 bb6def34ee9a
Merge
jaxp/make/build.properties
jaxp/make/build.xml
jaxp/make/tools/StripProperties/StripProperties.java
jaxp/make/tools/StripProperties/StripPropertiesTask.java
jdk/src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java
jdk/src/share/native/sun/security/ec/ec.c
--- a/.hgtags-top-repo	Mon Sep 28 19:38:55 2009 -0700
+++ b/.hgtags-top-repo	Wed Jul 05 17:01:09 2017 +0200
@@ -46,3 +46,4 @@
 82e6c820c51ac27882b77755d42efefdbf1dcda0 jdk7-b69
 175cb3fe615998d1004c6d3fd96e6d2e86b6772d jdk7-b70
 4c36e9853dda27bdac5ef4839a610509fbe31d34 jdk7-b71
+0d7e03b426df27c21dcc44ffb9178eacd1b04f10 jdk7-b72
--- a/README-builds.html	Mon Sep 28 19:38:55 2009 -0700
+++ b/README-builds.html	Wed Jul 05 17:01:09 2017 +0200
@@ -38,12 +38,17 @@
             <ul>
                 <li><a href="#introduction">Introduction</a></li>
                 <li><a href="#MBE">Minimum Build Environments</a></li>
-                <li><a href="#SDBE">Specific Developer Build Environments</a></li>
+                <li><a href="#SDBE">Specific Developer Build Environments</a>
                     <ul>
                         <li><a href="#fedora">Fedora Linux</a> </li>
                         <li><a href="#centos">CentOS Linux</a> </li>
-                        <li><a href="#ubuntu">Ubuntu Linux</a> </li>
+		        <li><a href="#debian">Debian GNU/Linux</a></li>
+			<li><a href="#ubuntu">Ubuntu Linux</a> </li>
+		        <li><a href="#opensuse">OpenSUSE</a></li>
+		        <li><a href="#mandriva">Mandriva</a></li>
+		        <li><a href="#opensolaris">OpenSolaris</a></li>
                     </ul>
+		</li>
                 <li><a href="#directories">Source Directory Structure</a> </li>
                 <li><a href="#building">Build Information</a>
                     <ul>
@@ -209,24 +214,59 @@
             we will try to provide what information we have available to us.
         </blockquote>
         <!-- ------------------------------------------------------ -->
-        <h3><a name="fedora">Fedora 9</a></h3>
+        <h3><a name="fedora">Fedora</a></h3>
         <blockquote>
-            After installing
-            <a href="http://www.fedoraproject.org/">Fedora 9</a>
-            you need to make sure you have
-            the "Software Development" bundle installed, plus the
-            following packages:
-            <blockquote>
-                <ul>
-                    <li>cups devel: Cups Development Package</li>
-                    <li>freetype 2.3+ devel: Freetype 2.3 Development Package</li>
-                    <li>hg: Mercurial, if you need to clone or manage source repositories</li>
-                    <li>ksh: May be needed when using <tt>webrev</tt></li>
-                </ul>
+	  <h4>Fedora 9</h4>
+	  <p>
+	    <blockquote>
+              After installing <a href="http://fedoraproject.org">Fedora</a> 9 
+	      you need to install several build dependencies. The simplest
+	      way to do it is to execute the following commands as user 
+	      <tt>root</tt>:
+	      <p/>
+	      <code>yum-builddep java-openjdk</code>
+	      <p/>
+	      <code>yum install gcc gcc-c++</code>
+	      <p/>
+	      In addition, it's necessary to set a few environment variables for the build:
+
+	      <p/>
+	      <code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-openjdk</code>
             </blockquote>
-            <p>
-            Always a good idea to do a complete Software Update/Refresh
-            after you get all the packages installed.
+	  <h4>Fedora 10</h4>
+	  <p>
+	    <blockquote>
+              After installing <a href="http://fedoraproject.org">Fedora</a> 10 
+	      you need to install several build dependencies. The simplest
+	      way to do it is to execute the following commands as user 
+	      <tt>root</tt>:
+	      <p/>
+	      <code>yum-builddep java-1.6.0-openjdk</code>
+	      <p/>
+	      <code>yum install gcc gcc-c++</code>
+	      <p/>
+	      In addition, it's necessary to set a few environment variables for the build:
+
+	      <p/>
+	      <code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-openjdk</code>
+            </blockquote>
+	  <h4>Fedora 11</h4>
+	  <p>
+	    <blockquote>
+              After installing <a href="http://fedoraproject.org">Fedora</a> 11 
+	      you need to install several build dependencies. The simplest
+	      way to do it is to execute the following commands as user 
+	      <tt>root</tt>:
+	      <p/>
+	      <code>yum-builddep java-1.6.0-openjdk</code>
+	      <p/>
+	      <code>yum install gcc gcc-c++</code>
+	      <p/>
+	      In addition, it's necessary to set a few environment variables for the build:
+
+	      <p/>
+	      <code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-openjdk</code>
+             </blockquote>
         </blockquote>
         <!-- ------------------------------------------------------ -->
         <h3><a name="centos">CentOS 5.2</a></h3>
@@ -269,145 +309,146 @@
             it's needed.
         </blockquote>
         <!-- ------------------------------------------------------ -->
-        <h3><a name="ubuntu">Ubuntu</a></h3>
+        <h3><a name="debian">Debian</a></h3>
+        <blockquote>
+            <h4>Debian 5.0 (Lenny)</h4>
+            <p>
+	      <blockquote>
+		After installing <a href="http://debian.org">Debian</a> 5 
+		you need to install several build dependencies. 
+		The simplest way to install the build dependencies is to 
+		execute the following commands as user <tt>root</tt>:
+		<p/>
+		<code>aptitude build-dep openjdk-6</code>
+		<p/>
+		<code>aptitude install openjdk-6-jdk libmotif-dev</code>
+		<p/>
+		In addition, it's necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
+	      </blockquote>
+        </blockquote>
+        <!-- ====================================================== -->
+	<h3><a name="ubuntu">Ubuntu</a></h3>
         <blockquote>
-            In addition to needing the Bootstrap JDK and the Binary Plugs, 
-            when building on Ubuntu you will need to
-            make sure certain packages are installed.
-            In particular, certain X11 packages, make, m4, gawk, gcc 4, 
-            binutils, cups, freetype
-            and alsa.
-            <!-- ------------------------------------------------------ -->
-            <h4>Ubuntu 6.06</h4>
+            <h4>Ubuntu 8.04</h4>
             <p>
-            The following list of packages for Ubuntu 6.06 is a working set that
-            does appear to work. 
+	      <blockquote>
+		After installing <a href="http://ubuntu.org">Ubuntu</a> 8.04 
+		you need to install several build dependencies. 
+		<p/>
+		First, you need to enable the universe repository in the 
+		Software Sources application and reload the repository 
+		information. The Software Sources application is available 
+		under the System/Administration menu. 
+		<p/>
+		The simplest way to install the build dependencies is to 
+		execute the following commands:
+		<p/>
+		<code>sudo aptitude build-dep openjdk-6</code>
+		<p/>
+		<code>sudo aptitude install openjdk-6-jdk</code>
+		<p/>
+		In addition, it's necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
+              </blockquote>
+           <h4>Ubuntu 8.10</h4>
             <p>
-            <b>Note that it's quite possible that some of these
-                packages are not required, so anyone discovering that some of the
-                packages listed below are NOT required,
-                please let the
-                OpenJDK
-            team know.</b>
+	      <blockquote>
+		After installing <a href="http://ubuntu.org">Ubuntu</a> 8.10 
+		you need to install several build dependencies. The simplest
+		way to do it is to execute the following commands:
+		<p/>
+		<code>sudo aptitude build-dep openjdk-6</code>
+		<p/>
+		<code>sudo aptitude install openjdk-6-jdk</code>
+		<p/>
+		In addition, it's necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
+             </blockquote>
+           <h4>Ubuntu 9.04</h4>
             <p>
-            All the packages below can be installed with the
-            Synaptic Package manager provided with the base Ubuntu 6.06 release.
-            <blockquote>
-                <ul>
-                    <li>binutils (2.16.1cvs20060117-1ubuntu2.1)</li>
-                    <li>cpp (4:4.0.3-1)</li>
-                    <li>cpp-4.0 (4.0.3-1ubuntu5)</li>
-                    <li>libfreetype6-dev</li>
-                    <li>g++ (4:4.0.3-1)</li>
-                    <li>g++-4.0 (4.0.3-1ubuntu5)</li>
-                    <li>gawk (1:3.1.5-2build1)</li>
-                    <li>gcc (4:4.0.3-1)</li>
-                    <li>gcc-4.0 (4.0.3-1ubuntu5)</li>
-                    <li>libasound2-dev (1.0.10-2ubuntu4)</li>
-                    <li>libc6 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4</li>
-                    <li>libc6-dev (2.3.6-0ubuntu20.4)</li>
-                    <li>libc6-i686 (2.3.6-0ubuntu20) to 2.3.6-0ubuntu20.4</li>
-                    <li>libcupsys2-dev (1.2.2-0ubuntu0.6.06)</li>
-                    <li>libgcrypt11-dev (1.2.2-1)</li>
-                    <li>libgnutls-dev (1.2.9-2ubuntu1.1)</li>
-                    <li>libgnutls12 (1.2.9-2ubuntu1) to 1.2.9-2ubuntu1.1</li>
-                    <li>libgpg-error-dev (1.1-4)</li>
-                    <li>libice-dev (2:1.0.0-0ubuntu2)</li>
-                    <li>liblockfile1 (1.06.1)</li>
-                    <li>libopencdk8-dev (0.5.7-2)</li>
-                    <li>libpopt-dev (1.7-5)</li>
-                    <li>libsm-dev (2:1.0.0-0ubuntu2)</li>
-                    <li>libstdc++6-4.0-dev (4.0.3-1ubuntu5)</li>
-                    <li>libtasn1-2-dev (0.2.17-1ubuntu1)</li>
-                    <li>libx11-dev (2:1.0.0-0ubuntu9)</li>
-                    <li>libxau-dev (1:1.0.0-0ubuntu4)</li>
-                    <li>libxaw-headers (2:1.0.1-0ubuntu3)</li>
-                    <li>libxaw7-dev (2:1.0.1-0ubuntu3)</li>
-                    <li>libxdmcp-dev (1:1.0.0-0ubuntu2)</li>
-                    <li>libxext-dev (2:1.0.0-0ubuntu4)</li>
-                    <li>libxi-dev (2:1.0.0-0ubuntu3) </li>
-                    <li>libxmu-dev (2:1.0.0-0ubuntu3)</li>
-                    <li>libxmu-headers (2:1.0.0-0ubuntu3)</li>
-                    <li>libxmuu-dev (2:1.0.0-0ubuntu3)</li>
-                    <li>libxp-dev (6.8.2-11ubuntu2)</li>
-                    <li>libxpm-dev (1:3.5.4.2-0ubuntu3)</li>
-                    <li>libxrandr-dev (1:1.1.0.2-0ubuntu4)</li>
-                    <li>libxt-dev (1:1.0.0-0ubuntu3)</li>
-                    <li>libxtrap-dev (2:1.0.0-0ubuntu2)</li>
-                    <li>libxtst-dev (2:1.0.1-0ubuntu2)</li>
-                    <li>libxv-dev (2:1.0.1-0ubuntu3)</li>
-                    <li>linux-kernel-headers (2.6.11.2-0ubuntu18)</li>
-                    <li>m4 (1.4.4-1)</li>
-                    <li>make (3.80+3.81.b4-1)</li>
-                    <li>ssl-cert (1.0.13)</li>
-                    <li>x-dev (7.0.4-0ubuntu2)</li>
-                    <li>x11proto-core-dev (7.0.4-0ubuntu2)</li>
-                    <li>x11proto-input-dev (1.3.2-0ubuntu2)</li>
-                    <li>x11proto-kb-dev (1.0.2-0ubuntu2)</li>
-                    <li>x11proto-randr-dev (1.1.2-0ubuntu2)</li>
-                    <li>x11proto-record-dev (1.13.2-0ubuntu2)</li>
-                    <li>x11proto-trap-dev (3.4.3-0ubuntu2)</li>
-                    <li>x11proto-video-dev (2.2.2-0ubuntu2)</li>
-                    <li>x11proto-xext-dev (7.0.2-0ubuntu2)</li>
-                    <li>xlibs-dev (7.0.0-0ubuntu45)</li>
-                    <li>zlib1g-dev (1:1.2.3-6ubuntu4)</li>
-                </ul>
-            </blockquote>
-            <!-- ------------------------------------------------------ -->
-            <h4>Ubuntu 7.04</h4>
+	      <blockquote>
+		After installing <a href="http://ubuntu.org">Ubuntu</a> 9.04 
+		you need to install several build dependencies. The simplest
+		way to do it is to execute the following commands:
+		<p/>
+		<code>sudo aptitude build-dep openjdk-6</code>
+		<p/>
+		<code>sudo aptitude install openjdk-6-jdk</code>
+		<p/>
+		In addition, it's necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk</code>
+             </blockquote>
+        </blockquote>
+        <!-- ====================================================== -->
+        <h3><a name="opensuse">OpenSUSE</a></h3>
+        <blockquote>
+            <h4>OpenSUSE 11.1</h4>
             <p>
-            Using the Synaptic Package Manager, download the following
-            packages (double indented packages are automatically aquired
-            due to package dependencies):
-            <blockquote>
-                <ul>
-                    <li>build-essential</li>
-                    <ul>
-                        <li>dpkg-dev</li>
-                        <li>g++</li>
-                        <li>g++-4.1</li>
-                        <li>libc6-dev</li>
-                        <li>libstdc++6.4.1-dev</li>
-                        <li>linux-libc-dev</li>
-                    </ul>
-                    <li>gawk</li>
-                    <li>m4</li>
-                    <li>libasound2-dev</li>
-                    <li>libcupsys2-dev</li>
-                    <ul>
-                        <li>libgcrypt11-dev</li>
-                        <li>lgnutls-dev</li>
-                        <li>libgpg-error-dev</li>
-                        <li>liblzo-dev</li>
-                        <li>libopencdk8-dev</li>
-                        <li>libpopt-dev</li>
-                        <li>libtasn1-3-dev</li>
-                        <li>zlib1g-dev</li>
-                    </ul>
-                    <li>sun-java6-jdk</li>
-                    <ul>
-                        <li>java-common</li>
-                        <li>libltdl3</li>
-                        <li>odbcinst1debian1</li>
-                        <li>sun-java6-bin</li>
-                        <li>sun-java6-jre</li>
-                        <li>unixodbc</li>
-                    </ul>
-                    <li>xlibs-dev</li>
-                    <ul>
-                        <li>(many)</li>
-                    </ul>
-                    <li>x11proto-print-dev</li>
-                    <li>libxaw7-dev</li>
-                    <ul>
-                        <li>libxaw-headers</li>
-                    </ul>
-                    <li>libxp-dev</li>
-                    <li>libfreetype6-dev</li>
-                </ul>
-            </blockquote>
+	      <blockquote>
+		After installing <a href="http://opensuse.org">OpenSUSE</a> 11.1 
+		you need to install several build dependencies. 
+		The simplest way to install the build dependencies is to 
+		execute the following commands:
+		<p/>
+		<code>sudo zypper source-install -d java-1_6_0-openjdk</code>
+		<p/>
+		<code>sudo zypper install make</code>
+		<p/>
+		In addition, it is necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-1.6.0-openjdk</code>
+		<p/>
+		Finally, you need to unset the <code>JAVA_HOME</code> environment variable:
+		<p/>
+		<code>export -n JAVA_HOME</code>
+	      </blockquote>
+	</blockquote>
+        <!-- ====================================================== -->
+        <h3><a name="mandriva">Mandriva</a></h3>
+        <blockquote>
+            <h4>Mandriva Linux One 2009 Spring</h4>
+            <p>
+	      <blockquote>
+		After installing <a href="http://mandriva.org">Mandriva</a> Linux One 2009 Spring 
+		you need to install several build dependencies. 
+		The simplest way to install the build dependencies is to 
+		execute the following commands as user <tt>root</tt>:
+		<p/>
+		<code>urpmi java-1.6.0-openjdk-devel ant make gcc gcc-c++ freetype-devel zip unzip libcups2-devel libxrender1-devel libalsa2-devel libstc++-static-devel libxtst6-devel libxi-devel</code>
+                <p/>
+		In addition, it is necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_BOOTDIR=/usr/lib/jvm/java-1.6.0-openjdk</code>
+	      </blockquote>
         </blockquote>
-        <!-- ------------------------------------------------------ -->
+        <!-- ====================================================== -->
+        <h3><a name="opensolaris">OpenSolaris</a></h3>
+        <blockquote>
+            <h4>OpenSolaris 2009.06</h4>
+            <p>
+	      <blockquote>
+		After installing <a href="http://opensolaris.org">OpenSolaris</a> 2009.06 
+		you need to install several build dependencies. 
+		The simplest way to install the build dependencies is to 
+		execute the following commands:
+		<p/>
+		<code>pfexec pkg install SUNWgmake SUNWj6dev SUNWant sunstudioexpress SUNWcups SUNWzip SUNWunzip SUNWxwhl SUNWxorg-headers SUNWaudh SUNWfreetype2</code>
+                <p/>
+		In addition, it is necessary to set a few environment variables for the build:
+		<p/>
+		<code>export LANG=C ALT_COMPILER_PATH=/opt/SunStudioExpress/bin/ ALT_CUPS_HEADERS_PATH=/usr/include/</code>
+		<p/>
+		Finally, you need to make sure that the build process can find the Sun Studio compilers:
+		<p/>
+		<code>export PATH=$PATH:/opt/SunStudioExpress/bin/</code>
+	      </blockquote>
+        </blockquote>
+        <!-- ------------------------------------------------------ -->  
         <hr>
         <h2><a name="directories">Source Directory Structure</a></h2>
         <blockquote>
--- a/corba/.hgtags	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/.hgtags	Wed Jul 05 17:01:09 2017 +0200
@@ -46,3 +46,4 @@
 8120d308ec4e805c5588b8d9372844d781c4112d jdk7-b69
 175bd68779546078dbdb6dacd7f0aced79ed22b1 jdk7-b70
 3f1ef7f899ea2aec189c4fb67e5c8fa374437c50 jdk7-b71
+c793a31209263fbb867c23c752599d85c21abb73 jdk7-b72
--- a/corba/make/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -141,12 +141,12 @@
 
 #----- src.zip
 
-SRC_ZIP_FILES = $(shell $(FIND) $(SRC_CLASSES_DIR) \( -name SCCS -o -name \*-template \) -prune -o -type f -print )
+SRC_ZIP_FILES = $(shell $(FIND) $(SRC_CLASSES_DIR) \( -name \*-template \) -prune -o -type f -print )
 
 SRC_ZIP = $(LIB_DIR)/src.zip
 $(SRC_ZIP): $(SRC_ZIP_FILES)
 	abs_src_zip=`cd $(@D) ; pwd`/$(@F) ; \
-	( cd $(SRC_CLASSES_DIR) ; $(FIND) . \( -name SCCS -o -name \*-template \) -prune -o -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ; \
+	( cd $(SRC_CLASSES_DIR) ; $(FIND) . \( -name \*-template \) -prune -o -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ; \
 	( cd $(GENSRC_DIR) ; $(FIND) . -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ;
 
 #----- bin.zip
--- a/corba/make/common/BuildToolJar.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/BuildToolJar.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1998-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,22 +24,29 @@
 #
 
 # Input: BUILDDIR PACKAGE PKGDIR PROGRAM BUILDTOOL_SOURCE_ROOT BUILDTOOL_MAIN
- 
+
+# All subdirectories under the package root for the tool (max depth 4)
+_WC_DIRS          = * */* */*/* */*/*/*
+
 BUILDTOOL_MAIN_SOURCE_FILE = $(BUILDTOOL_SOURCE_ROOT)/$(BUILDTOOL_MAIN)
 BUILDTOOL_MANIFEST_FILE    = $(BUILDTOOLCLASSDIR)/$(PROGRAM)_manifest.mf
 BUILDTOOL_JAR_FILE         = $(BUILDTOOLJARDIR)/$(PROGRAM).jar
-BUILDTOOL_ALL_FILES       := $(shell $(CD) $(BUILDTOOL_SOURCE_ROOT) \
-    && $(FIND) $(PKGDIR) $(SCM_DIRS_prune) -o -type f -print)
-BUILTTOOL_MAINCLASS = $(subst /,.,$(BUILDTOOL_MAIN:%.java=%))
+BUILTTOOL_MAINCLASS        = $(subst /,.,$(BUILDTOOL_MAIN:%.java=%))
 
-all build: $(BUILDTOOL_JAR_FILE) tool_info
+# Wildcard patterns that find all the sources for this build tool
+BUILDTOOL_WC_PATTERNS      = $(BUILDTOOL_SOURCE_ROOT)/$(PKGDIR)/*.java \
+    $(patsubst %, $(BUILDTOOL_SOURCE_ROOT)/$(PKGDIR)/%/*.java, $(_WC_DIRS))
+
+# Wildcard expansion that finds all the files
+BUILDTOOL_SRC_FILES       := $(wildcard $(BUILDTOOL_WC_PATTERNS))
+
+all build: $(BUILDTOOL_JAR_FILE)
 
 $(BUILDTOOL_MANIFEST_FILE): $(BUILDTOOL_MAIN_SOURCE_FILE)
 	@$(prep-target)
 	$(ECHO) "Main-Class: $(BUILTTOOL_MAINCLASS)" > $@
 
-$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) \
-    $(BUILDTOOL_ALL_FILES:%=$(BUILDTOOL_SOURCE_ROOT)/%)
+$(BUILDTOOL_JAR_FILE): $(BUILDTOOL_MANIFEST_FILE) $(BUILDTOOL_SRC_FILES)
 	@$(prep-target)
 	@$(MKDIR) -p $(BUILDTOOLCLASSDIR)
 	$(BOOT_JAVAC_CMD) -d $(BUILDTOOLCLASSDIR) \
@@ -49,23 +56,8 @@
 	    $(JAR_JFLAGS) || $(RM) $@
 	@$(java-vm-cleanup)
 
-# Printing out a build tool information line
-define printBuildToolSetting
-if [ "$2" != "" ] ; then $(PRINTF) "%-25s %s\n" "$1:" "$2"; fi
-endef
+clean clobber::
+	$(RM) -r $(BUILDTOOLCLASSDIR)/$(PKGDIR) \
+                 $(BUILDTOOL_MANIFEST_FILE) \
+                 $(BUILDTOOL_JAR_FILE)
 
-# Print out the build tool information
-tool_info:
-	@$(ECHO) "========================================================="
-	@$(call printBuildToolSetting,BUILDTOOL,$(PROGRAM))
-	@$(call printBuildToolSetting,PACKAGE,$(PACKAGE))
-	@$(call printBuildToolSetting,BUILDTOOL_SOURCE_ROOT,$(BUILDTOOL_SOURCE_ROOT))
-	@$(call printBuildToolSetting,BUILTTOOL_MAINCLASS,$(BUILTTOOL_MAINCLASS))
-	@$(call printBuildToolSetting,BUILDTOOL_JAR_FILE,$(BUILDTOOL_JAR_FILE))
-	@$(ECHO) "========================================================="
-
-clean clobber::
-	$(RM) -r $(BUILDTOOLCLASSDIR)/$(PKGDIR)
-	$(RM) $(BUILDTOOL_MANIFEST_FILE)
-	$(RM) $(BUILDTOOL_JAR_FILE)
-
--- a/corba/make/common/CancelImplicits.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/CancelImplicits.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 1998-1999 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1998-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
@@ -56,11 +56,3 @@
 %: %.sh
 endif
 
-#
-# If you are using RCS, you must set the variable USE_RCS at the make
-# command line. Otherwise we disable RCS.
-#
-ifndef USE_RCS
-%:: %,v
-%:: RCS/%,v
-endif
--- a/corba/make/common/Defs.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/Defs.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 1995-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 1995-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
@@ -310,125 +310,32 @@
 SUBDIRS_MAKEFLAGS-clobber = INCREMENTAL_BUILD=false
 SUBDIRS_MAKEFLAGS-clean   = INCREMENTAL_BUILD=false
 
-# Current directory
-CURRENT_DIRECTORY := $(shell $(PWD))
-
-# If no timing wanted, we need to define these as empty
-ifdef NO_TIMING
-
-TIMING_ID:=NA
-
-define TIMING_start
-t=0:0:0:0
-endef
-
-define TIMING_end
-time_used=0
-endef
-
-else # NO_TIMING
-
-# Default timing id
-TIMING_ID:=$(shell $(BASENAME) $(CURRENT_DIRECTORY))
-
-# Timing start (must be used in same shell, e.g. same command line)
-#    Defines the shell variable $1 to have the start time.
-define TIMING_start
-$1=`$(DATE) +%j:%H:%M:%S`
-endef
-
-# Timing end (must be used in same shell, e.g. same command line)
-#    Expects shell variable $1 to have been defined as the start time.
-#    Expects shell variable $2 to have timing id string
-#    Sets total_seconds shell variable as the total seconds used.
-#    Sets time_used shell variable to contain format "%dh%dm%ds"
-define TIMING_end
-begTime="$${$1}"; \
-timing_id="$${$2}"; \
-endTime=`$(DATE) +%j:%H:%M:%S`; \
-d1=`$(ECHO) $${begTime} | $(CUT) -d':' -f1 | $(SED) -e 's@^0*@@'`; \
-if [ "$${d1}" = "" ] ; then d1=0; fi; \
-h1=`$(ECHO) $${begTime} | $(CUT) -d':' -f2 | $(SED) -e 's@^0*@@'`; \
-if [ "$${h1}" = "" ] ; then h1=0; fi; \
-m1=`$(ECHO) $${begTime} | $(CUT) -d':' -f3 | $(SED) -e 's@^0*@@'`; \
-if [ "$${m1}" = "" ] ; then m1=0; fi; \
-s1=`$(ECHO) $${begTime} | $(CUT) -d':' -f4 | $(SED) -e 's@^0*@@'`; \
-if [ "$${s1}" = "" ] ; then s1=0; fi; \
-d2=`$(ECHO) $${endTime} | $(CUT) -d':' -f1 | $(SED) -e 's@^0*@@'`; \
-if [ "$${d2}" = "" ] ; then d2=0; fi; \
-h2=`$(ECHO) $${endTime} | $(CUT) -d':' -f2 | $(SED) -e 's@^0*@@'`; \
-if [ "$${h2}" = "" ] ; then h2=0; fi; \
-m2=`$(ECHO) $${endTime} | $(CUT) -d':' -f3 | $(SED) -e 's@^0*@@'`; \
-if [ "$${m2}" = "" ] ; then m2=0; fi; \
-s2=`$(ECHO) $${endTime} | $(CUT) -d':' -f4 | $(SED) -e 's@^0*@@'`; \
-if [ "$${s2}" = "" ] ; then s2=0; fi; \
-t1_secs=`$(EXPR) $${d1} '*' 60 '*' 60 '*' 24 '+' $${h1} '*' 60 '*' 60 \
-		 '+' $${m1} '*' 60 '+' $${s1}`; \
-t2_secs=`$(EXPR) $${d2} '*' 60 '*' 60 '*' 24 '+' $${h2} '*' 60 '*' 60 \
-		 '+' $${m2} '*' 60 '+' $${s2}`; \
-total_seconds=`$(EXPR) $${t2_secs} '-' $${t1_secs}`; \
-if [ "$${total_seconds}" -lt 0 ] ; then total_seconds=0; fi; \
-t_hour=`$(EXPR) $${total_seconds} '/' '(' 60 '*' 60 ')'`h; \
-t_min=`$(EXPR) '(' $${total_seconds} '%' '(' 60 '*' 60 ')' ')' '/' 60`m; \
-t_sec=`$(EXPR) $${total_seconds} '%' 60`s; \
-time_used=$${t_sec}; \
-if [ "$${t_hour}" != "0h" ] ; then \
-time_used=$${t_hour}$${t_min}$${t_sec}; \
-elif [ "$${t_min}" != "0m" ] ; then \
-time_used=$${t_min}$${t_sec}; \
-else \
-time_used=$${t_sec}; \
-fi; \
-$(PRINTF) "  Timing: %05d seconds or %s for %s\n" \
-    $${total_seconds} $${time_used} $${timing_id}
-endef
-
-endif # NO_TIMING
-
 # Given a SUBDIRS list, cd into them and make them
 #   SUBDIRS_MAKEFLAGS      Make settings for a subdir make
 #   SUBDIRS_MAKEFLAGS-$@   Make settings specific to this target
 define SUBDIRS-loop
-@$(ECHO) "Begin Processing SUBDIRS: $(SUBDIRS)"
 @for i in DUMMY $(SUBDIRS) ; do \
   if [ "$$i" != "DUMMY" ] ; then \
-    $(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \
-    timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \
-    $(call TIMING_start,startTime); \
-    curDir=$(CURRENT_DIRECTORY); \
-    $(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \
-			  $(SUBDIRS_MAKEFLAGS) \
-			  $(SUBDIRS_MAKEFLAGS-$@) \
-			  FULL_VERSION=$(FULL_VERSION) \
-			  RELEASE=$(RELEASE) || exit 1; \
-	       $(CD) $${curDir}; \
-    $(call TIMING_end,startTime,timing_id); \
-    $(ECHO) "<<<Finished Recursively making "$$i" "$@" @ `$(DATE)`." ; \
+    $(MAKE) -C $${i} $@ \
+          $(SUBDIRS_MAKEFLAGS) \
+          $(SUBDIRS_MAKEFLAGS-$@) \
+          FULL_VERSION=$(FULL_VERSION) \
+          RELEASE=$(RELEASE) || exit 1; \
   fi ; \
 done
-@$(ECHO) "Done Processing SUBDIRS: $(SUBDIRS)"
 endef
 
 # Given a OTHERSUBDIRS list, cd into them and make them (extra loop define)
 #   OTHERSUBDIRS_MAKEFLAGS      Make settings for a subdir make
 define OTHERSUBDIRS-loop
-@$(ECHO) "Begin Processing OTHERSUBDIRS: $(OTHERSUBDIRS)"
 @for i in DUMMY $(OTHERSUBDIRS) ; do \
   if [ "$$i" != "DUMMY" ] ; then \
-    $(ECHO) ">>>Recursively making "$$i" "$@" @ `$(DATE)` ..."; \
-    timing_id="$(TIMING_ID)-`$(BASENAME) $${i}`"; \
-    $(call TIMING_start,startTime); \
-    curDir=$(CURRENT_DIRECTORY); \
-    $(CD) $$i; $(MAKE) $@ TIMING_ID=$${timing_id} \
-		          $(OTHERSUBDIRS_MAKEFLAGS) \
-			  FULL_VERSION=$(FULL_VERSION) \
-			  RELEASE=$(RELEASE) || exit 1; \
-	       $(CD) $${curDir}; \
-    $(call TIMING_end,startTime,timing_id); \
-    $(ECHO) "<<<Finished Recursively making "$$i" "$@" @ `$(DATE)`." ; \
+    $(MAKE) -C $${i} $@ \
+          $(OTHERSUBDIRS_MAKEFLAGS) \
+          FULL_VERSION=$(FULL_VERSION) \
+          RELEASE=$(RELEASE) || exit 1; \
   fi ; \
 done
-@$(ECHO) "Done Processing OTHERSUBDIRS: $(OTHERSUBDIRS)"
 endef
 
 #
@@ -460,46 +367,23 @@
   VERSION_DEFINES = -DRELEASE='"$(RELEASE)"'
 endif
 
-# Note: As a rule, GNU Make rules should not appear in any of the 
-# Defs*.gmk files. These were added for Kestrel-Solaris and do address
-# a TeamWare bug. They should be moved elsewhere for Merlin.
-# 
-#  Override gnumake built-in rules which do sccs get operations badly.
-#  (They put the checked out code in the current directory, not in the
-#  directory of the original file.) 
-# Since this is a symptom of a teamware failure, complain and die on the spot.
+# Prevent the use of many default suffix rules we do not need
+.SUFFIXES:
+.SUFFIXES: .c .o .h .obj .cpp .hpp .java .class
 
-# This message immediately goes to stdout and the build terminates.
-define SCCS-trouble
-$(error  \
-"ERROR: File $@ referenced while building in $(CURRENT_DIRECTORY) \
- is out of date with respect to its SCCS file $<. \
- This can happen from an unresolved Teamware conflict, a file movement, or \
- a failure in which SCCS files are updated but the 'sccs get' was not done. \
- You should double check for other out of date files in your workspace. \
- Or run: cd $(TOPDIR) && $(MAKE) sccs_get")
-endef
-
-%:: s.%
-	@$(SCCS-trouble)
-%:: SCCS/s.%
-	@$(SCCS-trouble)
-	@$(ECHO) "         is out of date with respect to its SCCS file." >> $(WARNING_FILE)
-	@$(ECHO) "         This file may be from an unresolved Teamware conflict." >> $(WARNING_FILE)
-	@$(ECHO) "         This is also a symptom of a Teamware bringover/putback failure" >> $(WARNING_FILE)
-	@$(ECHO) "         in which SCCS files are updated but not checked out." >> $(WARNING_FILE)
-	@$(ECHO) "         Check for other out of date files in your workspace." >> $(WARNING_FILE)
-	@$(ECHO) "" >> $(WARNING_FILE)
-	@#exit 666
-
+# Make sure we are all insane
 ifdef INSANE
   export INSANE
 endif
 
-ifdef ALT_COPYRIGHT_YEAR
-  COPYRIGHT_YEAR = $(ALT_COPYRIGHT_YEAR)
-else
-  COPYRIGHT_YEAR = $(shell $(DATE) '+%Y')
+# Make sure we have the current year
+ifndef COPYRIGHT_YEAR
+  ifdef ALT_COPYRIGHT_YEAR
+    COPYRIGHT_YEAR := $(ALT_COPYRIGHT_YEAR)
+  else
+    COPYRIGHT_YEAR := $(shell $(DATE) '+%Y')
+  endif
+  export COPYRIGHT_YEAR
 endif
 
 # Install of imported file (JDK_IMPORT_PATH, or some other external location)
--- a/corba/make/common/Rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/Rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -27,17 +27,6 @@
 #
 # Rules shared by all Java makefiles.
 #
-# Used to apply to source file $<, checks code conventions, issues warnings.
-define check-conventions
-  if [ "$(CONVENTION_WATCH)" = "true" ] ; then \
-    if [ "`$(CAT) -n -v -t $< | $(EGREP) -v '\@\(\#\)' | $(EGREP) '\^[MLI]'`" != "" ] ; then \
-      $(ECHO) "WARNING: File contains tabs, ^M, or ^L characters: $<"; \
-      if [ "$(CONVENTION_DETAILS)" = "true" ] ; then \
-        $(CAT) -n -v -t $< | $(EGREP) -v '\@\(\#\)' | $(EGREP) '\^[MLI]' ; \
-      fi; \
-    fi; \
-  fi
-endef
 
 # Make sure the default rule is all
 rules_default_rule: all
@@ -162,7 +151,6 @@
 # Add a java source to the list
 define add-java-file
 $(ECHO) "$?" >> $(JAVA_SOURCE_LIST)
-$(check-conventions)
 endef
 
 $(CLASSDESTDIR)/%.class: $(GENSRCDIR)/%.java
@@ -197,11 +185,8 @@
 
 .compile.classlist : $(JAVA_SOURCE_LIST)
 	@$(MKDIR) -p $(CLASSDESTDIR)
-	@if [ `$(CAT) $(JAVA_SOURCE_LIST) | $(WC) -l` -ge 1 ] ; then \
-	  $(ECHO) "# Java sources to be compiled: (listed in file $(JAVA_SOURCE_LIST))"; \
+	if [ -s $(JAVA_SOURCE_LIST) ] ; then \
 	  $(CAT) $(JAVA_SOURCE_LIST); \
-	  $(ECHO) "# Running javac:"; \
-	  $(ECHO) $(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
 	  $(JAVAC_CMD) $(JAVAC_PREFER_SOURCE) -sourcepath "$(SOURCEPATH)" -d $(CLASSDESTDIR) @$(JAVA_SOURCE_LIST); \
 	fi
 	@$(java-vm-cleanup)
@@ -220,10 +205,7 @@
 packages.clean:
 ifeq ($(DONT_CLOBBER_CLASSES),false)
   ifdef AUTO_FILES_JAVA_DIRS
-	@for sdir in $(AUTO_FILES_JAVA_DIRS); do \
-	  $(ECHO) "$(RM) -r $(CLASSDESTDIR)/$$sdir"; \
-	  $(RM) -r $(CLASSDESTDIR)/$$sdir; \
-        done
+	$(RM) -r $(patsubst %, $(CLASSDESTDIR)/%, $(AUTO_FILES_JAVA_DIRS))
   else
 	$(RM) -r $(CLASSDESTDIR)/$(PKGDIR)
   endif
@@ -259,15 +241,13 @@
 
 $(CLASSHDR_DOTFILE): $(CLASSES_export)
 	$(prep-target)
-	@$(ECHO) "# Running javah:"
 	$(JAVAH_CMD) -d $(CLASSHDRDIR)/ \
 		$(CLASSES.export) $(subst $$,\$$,$(EXPORTED_inner))
 	@$(java-vm-cleanup)
 	@$(TOUCH) $@
 
 classheaders.clean:
-	$(RM) $(CLASSHDR_DOTFILE)
-	$(RM) -r $(CLASSHDRDIR)
+	$(RM) -r $(CLASSHDRDIR) $(CLASSHDR_DOTFILE)
 
 else # FILES_export
 
--- a/corba/make/common/shared/Compiler-msvc.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/shared/Compiler-msvc.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -48,11 +48,17 @@
   NMAKE          = MFLAGS= MAKEFLAGS= $(COMPILER_PATH)nmake -nologo
 
   # Compiler version and type (Always get word after "Version")
-  CC_VER  := $(shell $(CC) 2>&1 | $(HEAD) -n 1 | $(SED) 's/.*\(Version.*\)/\1/' | $(NAWK) '{print $$2}')
-  
+  ifndef CC_VER
+    CC_VER  := $(shell $(CC) 2>&1 | $(HEAD) -n 1 | $(SED) 's/.*\(Version.*\)/\1/' | $(NAWK) '{print $$2}')
+    export CC_VER
+  endif
+
   # SDK-64 and MSVC6 put REBASE.EXE in a different places - go figure...
   ifeq ($(ARCH_DATA_MODEL), 32)
-    LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
+    ifndef LINK_VER
+      LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
+      export LINK_VER
+    endif
     CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
     ifeq ($(CC_MAJORVER), 13)
       # This should be: CC_VER=13.10.3077 LINK_VER=7.10.3077
@@ -93,7 +99,10 @@
     endif
   else
     # else ARCH_DATA_MODEL is 64
-    LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
+    ifndef LINK_VER
+      LINK_VER := $(shell $(LINK) | $(HEAD) -n 1 | $(NAWK) '{print $$6}')
+      export LINK_VER
+    endif
     CC_MAJORVER :=$(call MajorVersion,$(CC_VER))
     CC_MINORVER :=$(call MinorVersion,$(CC_VER))
     CC_MICROVER :=$(call MicroVersion,$(CC_VER))
--- a/corba/make/common/shared/Defs-utils.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/shared/Defs-utils.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -116,7 +116,6 @@
 RMDIR          = $(UTILS_COMMAND_PATH)rmdir
 RPM            = $(UTILS_COMMAND_PATH)rpm
 RPMBUILD       = $(UTILS_COMMAND_PATH)rpmbuild
-SCCS           = $(UTILS_CCS_BIN_PATH)sccs
 SED            = $(UTILS_COMMAND_PATH)sed
 SH             = $(UTILS_COMMAND_PATH)sh
 SHOWREV        = $(UTILS_USR_BIN_PATH)showrev
--- a/corba/make/common/shared/Defs-windows.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/shared/Defs-windows.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -113,32 +113,38 @@
 
 # UNIXCOMMAND_PATH: path to where the most common Unix commands are.
 #  NOTE: Must end with / so that it could be empty, allowing PATH usage.
-ifdef ALT_UNIXCOMMAND_PATH
-  xALT_UNIXCOMMAND_PATH  :="$(subst \,/,$(ALT_UNIXCOMMAND_PATH))"
-  fxALT_UNIXCOMMAND_PATH :=$(call FullPath,$(xALT_UNIXCOMMAND_PATH))
-  UNIXCOMMAND_PATH       :=$(call PrefixPath,$(fxALT_UNIXCOMMAND_PATH))
-else
-  ifdef USING_CYGWIN
-    UNIXCOMMAND_PATH :=$(call PrefixPath,/usr/bin)
+ifndef UNIXCOMMAND_PATH
+  ifdef ALT_UNIXCOMMAND_PATH
+    xALT_UNIXCOMMAND_PATH  :="$(subst \,/,$(ALT_UNIXCOMMAND_PATH))"
+    fxALT_UNIXCOMMAND_PATH :=$(call FullPath,$(xALT_UNIXCOMMAND_PATH))
+    UNIXCOMMAND_PATH       :=$(call PrefixPath,$(fxALT_UNIXCOMMAND_PATH))
   else
-    ifdef ROOTDIR
-      xROOTDIR :="$(subst \,/,$(ROOTDIR))"
-      _rootdir :=$(call FullPath,$(xROOTDIR))
+    ifdef USING_CYGWIN
+      UNIXCOMMAND_PATH :=$(call PrefixPath,/usr/bin)
     else
-      xROOTDIR :="$(_system_drive)/mksnt"
-      _rootdir :=$(call FullPath,$(xROOTDIR))
-    endif
-    ifneq ($(_rootdir),)
-      UNIXCOMMAND_PATH :=$(call PrefixPath,$(_rootdir)/mksnt)
+      ifdef ROOTDIR
+        xROOTDIR :="$(subst \,/,$(ROOTDIR))"
+        _rootdir :=$(call FullPath,$(xROOTDIR))
+      else
+        xROOTDIR :="$(_system_drive)/mksnt"
+        _rootdir :=$(call FullPath,$(xROOTDIR))
+      endif
+      ifneq ($(_rootdir),)
+        UNIXCOMMAND_PATH :=$(call PrefixPath,$(_rootdir)/mksnt)
+      endif
     endif
   endif
+  UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
+  export UNIXCOMMAND_PATH
 endif
-UNIXCOMMAND_PATH:=$(call AltCheckSpaces,UNIXCOMMAND_PATH)
 
 # Get version of MKS or CYGWIN
 ifdef USING_CYGWIN
-_CYGWIN_VER :=$(shell $(UNAME))
-CYGWIN_VER  :=$(call GetVersion,$(_CYGWIN_VER))
+  ifndef CYGWIN_VER
+    _CYGWIN_VER :=$(shell $(UNAME))
+    CYGWIN_VER  :=$(call GetVersion,$(_CYGWIN_VER))
+    export CYGWIN_VER
+  endif
 else # MKS
 _MKS_VER :=$(shell $(MKSINFO) 2>&1 | $(GREP) Release | $(TAIL) -1 | $(SED) -e 's@.*\(Release.*\)@\1@')
 MKS_VER  :=$(call GetVersion,$(_MKS_VER))
@@ -168,235 +174,234 @@
 
 # Process Windows values into FullPath values, these paths may have \ chars
 
-# System root
-ifdef SYSTEMROOT
-  xSYSTEMROOT  :="$(subst \,/,$(SYSTEMROOT))"
-  _system_root :=$(call FullPath,$(xSYSTEMROOT))
-else
-  ifdef SystemRoot
-     xSYSTEMROOT :="$(subst \,/,$(SystemRoot))"
-    _system_root :=$(call FullPath,$(xSYSTEMROOT))
+# Program Files directory
+ifndef SHORTPROGRAMFILES
+  ifdef PROGRAMFILES
+    xPROGRAMFILES      :="$(subst \,/,$(PROGRAMFILES))"
   else
-    ifdef WINDIR
-      xWINDIR      :="$(subst \,/,$(WINDIR))"
-      _system_root :=$(call FullPath,$(xWINDIR))
+    ifeq ($(ARCH_DATA_MODEL), 32)
+      xPROGRAMFILES    :="$(_system_drive)/Program Files"
     else
-      ifdef windir
-        xWINDIR      :="$(subst \,/,$(windir))"
-        _system_root :=$(call FullPath,$(xWINDIR))
-      endif
+      xPROGRAMFILES    :="$(_system_drive)/Program Files (x86)"
     endif
   endif
-endif
-_system_root:=$(call CheckValue,_system_root,$(_system_drive)/WINNT)
-
-# Program Files directory
-ifdef PROGRAMFILES
-  xPROGRAMFILES      :="$(subst \,/,$(PROGRAMFILES))"
-else
   ifeq ($(ARCH_DATA_MODEL), 32)
-    xPROGRAMFILES    :="$(_system_drive)/Program Files"
+    SHORTPROGRAMFILES  :=$(call FullPath,$(xPROGRAMFILES))
   else
-    xPROGRAMFILES    :="$(_system_drive)/Program Files (x86)"
+    ifdef PROGRAMW6432
+      xPROGRAMW6432    :="$(subst \,/,$(PROGRAMW6432))"
+    else
+      xPROGRAMW6432    :="$(_system_drive)/Program Files"
+    endif
+    SHORTPROGRAMFILES  :=$(call FullPath,$(xPROGRAMW6432))
   endif
-endif
-ifeq ($(ARCH_DATA_MODEL), 32)
-  _program_files     :=$(call FullPath,$(xPROGRAMFILES))
-else
-  ifdef PROGRAMW6432
-    xPROGRAMW6432    :="$(subst \,/,$(PROGRAMW6432))"
-  else
-    xPROGRAMW6432    :="$(_system_drive)/Program Files"
+  ifneq ($(word 1,$(SHORTPROGRAMFILES)),$(SHORTPROGRAMFILES))
+    SHORTPROGRAMFILES  :=
   endif
-  _program_files     :=$(call FullPath,$(xPROGRAMW6432))
-  _program_files32   :=$(call FullPath,$(xPROGRAMFILES))
-  ifneq ($(word 1,$(_program_files32)),$(_program_files32))
-    _program_files32:=
-  endif
-endif
-ifneq ($(word 1,$(_program_files)),$(_program_files))
-  _program_files:=
+  export SHORTPROGRAMFILES
 endif
 
 # Compilers, SDK, and Visual Studio (MSDEV) [32bit is different from 64bit]
 ifeq ($(ARCH_DATA_MODEL), 32)
-  # Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
-  ifdef MSVCDIR
-    xMSVCDIR  :="$(subst \,/,$(MSVCDIR))"
-    _msvc_dir :=$(call FullPath,$(xMSVCDIR))
-  else
-    ifdef MSVCDir
-      xMSVCDIR  :="$(subst \,/,$(MSVCDir))"
-      _msvc_dir :=$(call FullPath,$(xMSVCDIR))
+  ifndef SHORTMSVCDIR
+    # Try looking in MSVCDIR or MSVCDir area first (set by vcvars32.bat)
+    ifdef MSVCDIR
+      xMSVCDIR         :="$(subst \,/,$(MSVCDIR))"
+      SHORTMSVCDIR     :=$(call FullPath,$(xMSVCDIR))
     else
-      ifneq ($(_program_files),)
-        xMSVCDIR  :="$(_program_files)/Microsoft Visual Studio .NET 2003/Vc7"
-        _msvc_dir :=$(call FullPath,$(xMSVCDIR))
+      ifdef MSVCDir
+        xMSVCDIR       :="$(subst \,/,$(MSVCDir))"
+        SHORTMSVCDIR   :=$(call FullPath,$(xMSVCDIR))
+      else
+        ifneq ($(SHORTPROGRAMFILES),)
+          xMSVCDIR     :="$(SHORTPROGRAMFILES)/Microsoft Visual Studio .NET 2003/Vc7"
+          SHORTMSVCDIR :=$(call FullPath,$(xMSVCDIR))
+        endif
       endif
     endif
-  endif
-  ifneq ($(subst MSDev98,OLDOLDOLD,$(_msvc_dir)),$(_msvc_dir))
-    _msvc_dir :=
+    ifneq ($(subst MSDev98,OLDOLDOLD,$(SHORTMSVCDIR)),$(SHORTMSVCDIR))
+      SHORTMSVCDIR     :=
+    endif
+    # If we still don't have it, look for VS71COMNTOOLS, setup by installer?
+    ifeq ($(SHORTMSVCDIR),)
+      ifdef VS71COMNTOOLS  # /Common/Tools directory, use ../../Vc7
+        xVS71COMNTOOLS :="$(subst \,/,$(VS71COMNTOOLS))"
+        _vs71tools     :=$(call FullPath,$(xVS71COMNTOOLS))
+      endif
+      ifneq ($(_vs71tools),)
+        SHORTMSVCDIR   :=$(_vs71tools)/../../Vc7
+      endif
+    endif
+    export SHORTMSVCDIR
   endif
-  # If we still don't have it, look for VS71COMNTOOLS, setup by installer?
-  ifeq ($(_msvc_dir),)
-    ifdef VS71COMNTOOLS  # /Common/Tools directory, use ../../Vc7
-      xVS71COMNTOOLS :="$(subst \,/,$(VS71COMNTOOLS))"
-      _vs71tools     :=$(call FullPath,$(xVS71COMNTOOLS))
-    endif
-    ifneq ($(_vs71tools),)
-      _msvc_dir :=$(_vs71tools)/../../Vc7
-    endif
-  endif
-  ifneq ($(_msvc_dir),)
-    _compiler_bin :=$(_msvc_dir)/Bin
-    _redist_sdk   :=$(_msvc_dir)/../SDK/v1.1/Bin
-    _ms_sdk       :=$(_msvc_dir)/PlatformSDK
+  ifneq ($(SHORTMSVCDIR),)
+    SHORTCOMPILERBIN   :=$(SHORTMSVCDIR)/Bin
+    SHORTPSDK          :=$(SHORTMSVCDIR)/PlatformSDK
+    export SHORTCOMPILERBIN
+    export SHORTPSDK
   endif
 endif
 
 # The Microsoft Platform SDK installed by itself
-ifneq ($(_program_files),)
-  xPSDK  :="$(_program_files)/Microsoft Platform SDK"
-  _psdk  :=$(call FullPath,$(xPSDK))
-  ifeq ($(_psdk),)
-    xPSDK  :="$(_program_files)/Microsoft SDK"
-    _psdk :=$(call FullPath,$(xMSSDK))
+ifneq ($(SHORTPROGRAMFILES),)
+  ifndef SHORTPSDK
+    xPSDK       :="$(SHORTPROGRAMFILES)/Microsoft Platform SDK"
+    SHORTPSDK   :=$(call FullPath,$(xPSDK))
+    ifeq ($(SHORTPSDK),)
+      xPSDK     :="$(SHORTPROGRAMFILES)/Microsoft SDK"
+      SHORTPSDK :=$(call FullPath,$(xMSSDK))
+    endif
+    export SHORTPSDK
   endif
 endif
 
 # If no SDK found yet, look in other places
-ifeq ($(_ms_sdk),)
+ifndef SHORTPSDK
   ifdef MSSDK
-    xMSSDK  :="$(subst \,/,$(MSSDK))"
-    _ms_sdk :=$(call FullPath,$(xMSSDK))
+    xMSSDK      :="$(subst \,/,$(MSSDK))"
+    SHORTPSDK   :=$(call FullPath,$(xMSSDK))
   else
     ifdef MSSdk
-      xMSSDK  :="$(subst \,/,$(MSSdk))"
-      _ms_sdk :=$(call FullPath,$(xMSSDK))
-    else
-      _ms_sdk :=$(_psdk)
+      xMSSDK    :="$(subst \,/,$(MSSdk))"
+      SHORTPSDK :=$(call FullPath,$(xMSSDK))
     endif
   endif
+  export SHORTPSDK
 endif
 
 # Compilers for 64bit are from SDK
 ifeq ($(ARCH_DATA_MODEL), 64)
-  xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
-  MSSDK61 :=$(call FullPath,$(xMSSDK61))
-  xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
-  _vs2008 :=$(call FullPath,$(xVS2008))
-  ifneq ($(_vs2008),)
-    ifeq ($(ARCH), ia64)
-      _compiler_bin :=$(_vs2008)/VC/Bin/x86_ia64
-    endif
-    ifeq ($(ARCH), amd64)
-      _compiler_bin :=$(_vs2008)/VC/Bin/$(ARCH)
-      _redist_sdk   :=$(MSSDK61)/VC/redist
-    endif
-  else
-    ifneq ($(_ms_sdk),)
+  ifndef SHORTCOMPILERBIN
+    xMSSDK61 :="C:/Program Files/Microsoft SDKs/Windows/v6.1/"
+    MSSDK61 :=$(call FullPath,$(xMSSDK61))
+    xVS2008 :="C:/Program Files (x86)/Microsoft Visual Studio 9.0/"
+    _vs2008 :=$(call FullPath,$(xVS2008))
+    ifneq ($(_vs2008),)
       ifeq ($(ARCH), ia64)
-        _compiler_bin :=$(_ms_sdk)/Bin/Win64
+        SHORTCOMPILERBIN :=$(_vs2008)/VC/Bin/x86_ia64
       endif
       ifeq ($(ARCH), amd64)
-        _compiler_bin :=$(_ms_sdk)/Bin/Win64/x86/$(ARCH)
-        _redist_sdk   :=$(_ms_sdk)/redist/win64/AMD64
+        SHORTCOMPILERBIN :=$(_vs2008)/VC/Bin/$(ARCH)
+      endif
+    else
+      ifneq ($(SHORTPSDK),)
+        ifeq ($(ARCH), ia64)
+          SHORTCOMPILERBIN :=$(SHORTPSDK)/Bin/Win64
+        endif
+        ifeq ($(ARCH), amd64)
+          SHORTCOMPILERBIN :=$(SHORTPSDK)/Bin/Win64/x86/$(ARCH)
+        endif
       endif
     endif
+    export SHORTCOMPILERBIN
   endif
 endif
 
 # Location on system where jdk installs might be
-ifneq ($(_program_files),)
-  USRJDKINSTANCES_PATH =$(_program_files)/Java
+ifneq ($(SHORTPROGRAMFILES),)
+  USRJDKINSTANCES_PATH =$(SHORTPROGRAMFILES)/Java
 else
   USRJDKINSTANCES_PATH =$(_system_drive)/
 endif
 
 # SLASH_JAVA: location of all network accessable files
-ifdef ALT_SLASH_JAVA
-  xALT_SLASH_JAVA :="$(subst \,/,$(ALT_SLASH_JAVA))"
-  SLASH_JAVA      :=$(call FullPath,$(xALT_SLASH_JAVA))
-else
-  ifdef ALT_JDK_JAVA_DRIVE
-    SLASH_JAVA  =$(JDK_JAVA_DRIVE)
+ifndef SLASH_JAVA
+  ifdef ALT_SLASH_JAVA
+    xALT_SLASH_JAVA :="$(subst \,/,$(ALT_SLASH_JAVA))"
+    SLASH_JAVA      :=$(call FullPath,$(xALT_SLASH_JAVA))
   else
-    SLASH_JAVA  =J:
+    ifdef ALT_JDK_JAVA_DRIVE
+      SLASH_JAVA  =$(JDK_JAVA_DRIVE)
+    else
+      SLASH_JAVA  =J:
+    endif
   endif
+  SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
+  SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
+  export SLASH_JAVA
 endif
-SLASH_JAVA:=$(call AltCheckSpaces,SLASH_JAVA)
-SLASH_JAVA:=$(call AltCheckValue,SLASH_JAVA)
 
 # JDK_DEVTOOLS_DIR: common path for all the java devtools
-ifdef ALT_JDK_DEVTOOLS_DIR
-  xALT_JDK_DEVTOOLS_DIR :="$(subst \,/,$(ALT_JDK_DEVTOOLS_DIR))"
-  JDK_DEVTOOLS_DIR      :=$(call FullPath,$(xALT_JDK_DEVTOOLS_DIR))
-else
-  JDK_DEVTOOLS_DIR =$(SLASH_JAVA)/devtools
+ifndef JDK_DEVTOOLS_DIR
+  ifdef ALT_JDK_DEVTOOLS_DIR
+    xALT_JDK_DEVTOOLS_DIR :="$(subst \,/,$(ALT_JDK_DEVTOOLS_DIR))"
+    JDK_DEVTOOLS_DIR      :=$(call FullPath,$(xALT_JDK_DEVTOOLS_DIR))
+  else
+    JDK_DEVTOOLS_DIR =$(SLASH_JAVA)/devtools
+  endif
+  JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
+  JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
+  export JDK_DEVTOOLS_DIR
 endif
-JDK_DEVTOOLS_DIR:=$(call AltCheckSpaces,JDK_DEVTOOLS_DIR)
-JDK_DEVTOOLS_DIR:=$(call AltCheckValue,JDK_DEVTOOLS_DIR)
 
 # COMPILER_PATH: path to where the compiler and tools are installed.
 #  NOTE: Must end with / so that it could be empty, allowing PATH usage.
-ifdef ALT_COMPILER_PATH
-  xALT_COMPILER_PATH  :="$(subst \,/,$(ALT_COMPILER_PATH))"
-  fxALT_COMPILER_PATH :=$(call FullPath,$(xALT_COMPILER_PATH))
-  COMPILER_PATH       :=$(call PrefixPath,$(fxALT_COMPILER_PATH))
-else
-  COMPILER_PATH :=$(call PrefixPath,$(_compiler_bin))
+ifndef COMPILER_PATH
+  ifdef ALT_COMPILER_PATH
+    xALT_COMPILER_PATH  :="$(subst \,/,$(ALT_COMPILER_PATH))"
+    fxALT_COMPILER_PATH :=$(call FullPath,$(xALT_COMPILER_PATH))
+    COMPILER_PATH       :=$(call PrefixPath,$(fxALT_COMPILER_PATH))
+  else
+    COMPILER_PATH :=$(call PrefixPath,$(SHORTCOMPILERBIN))
+  endif
+  COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
+  export COMPILER_PATH
 endif
-COMPILER_PATH :=$(call AltCheckSpaces,COMPILER_PATH)
 
 # MSDEVTOOLS_PATH: path to where the additional MS Compiler tools are.
 #  NOTE: Must end with / so that it could be empty, allowing PATH usage.
-ifdef ALT_MSDEVTOOLS_PATH
-  xALT_MSDEVTOOLS_PATH  :="$(subst \,/,$(ALT_MSDEVTOOLS_PATH))"
-  fxALT_MSDEVTOOLS_PATH :=$(call FullPath,$(xALT_MSDEVTOOLS_PATH))
-  MSDEVTOOLS_PATH       :=$(call PrefixPath,$(fxALT_MSDEVTOOLS_PATH))
-else
-  ifeq ($(ARCH_DATA_MODEL), 64)
-    ifdef MSTOOLS
-      xMSTOOLS  :="$(subst \,/,$(MSTOOLS))"
-      _ms_tools :=$(call FullPath,$(xMSTOOLS))
-    else
-      ifdef Mstools
-        xMSTOOLS  :="$(subst \,/,$(Mstools))"
+ifndef MSDEVTOOLS_PATH
+  ifdef ALT_MSDEVTOOLS_PATH
+    xALT_MSDEVTOOLS_PATH  :="$(subst \,/,$(ALT_MSDEVTOOLS_PATH))"
+    fxALT_MSDEVTOOLS_PATH :=$(call FullPath,$(xALT_MSDEVTOOLS_PATH))
+    MSDEVTOOLS_PATH       :=$(call PrefixPath,$(fxALT_MSDEVTOOLS_PATH))
+  else
+    ifeq ($(ARCH_DATA_MODEL), 64)
+      ifdef MSTOOLS
+        xMSTOOLS  :="$(subst \,/,$(MSTOOLS))"
         _ms_tools :=$(call FullPath,$(xMSTOOLS))
       else
-        _ms_tools :=
+        ifdef Mstools
+          xMSTOOLS  :="$(subst \,/,$(Mstools))"
+          _ms_tools :=$(call FullPath,$(xMSTOOLS))
+        else
+          _ms_tools :=
+        endif
       endif
-    endif
-    ifneq ($(_ms_tools),)
-      _ms_tools_bin :=$(_ms_tools)/Bin
+      ifneq ($(_ms_tools),)
+        _ms_tools_bin :=$(_ms_tools)/Bin
+      else
+        # Assumes compiler bin is .../Bin/win64/x86/AMD64, rc.exe is 3 levels up
+        _ms_tools_bin :=$(SHORTCOMPILERBIN)/../../..
+      endif
     else
-      # Assumes compiler bin is .../Bin/win64/x86/AMD64, rc.exe is 3 levels up
-      _ms_tools_bin :=$(_compiler_bin)/../../..
+      _ms_tools_bin :=$(SHORTCOMPILERBIN)
     endif
-  else
-    _ms_tools_bin :=$(_compiler_bin)
+    MSDEVTOOLS_PATH :=$(call PrefixPath,$(_ms_tools_bin))
   endif
-  MSDEVTOOLS_PATH :=$(call PrefixPath,$(_ms_tools_bin))
+  MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
+  export MSDEVTOOLS_PATH
 endif
-MSDEVTOOLS_PATH:=$(call AltCheckSpaces,MSDEVTOOLS_PATH)
 
 # DEVTOOLS_PATH: for other tools required for building (such as zip, etc.)
 #  NOTE: Must end with / so that it could be empty, allowing PATH usage.
-ifdef ALT_DEVTOOLS_PATH
-  xALT_DEVTOOLS_PATH  :="$(subst \,/,$(ALT_DEVTOOLS_PATH))"
-  fxALT_DEVTOOLS_PATH :=$(call FullPath,$(xALT_DEVTOOLS_PATH))
-  DEVTOOLS_PATH       :=$(call PrefixPath,$(fxALT_DEVTOOLS_PATH))
-else
-  ifdef USING_CYGWIN
-    DEVTOOLS_PATH :=$(UNIXCOMMAND_PATH)
+ifndef DEVTOOLS_PATH
+  ifdef ALT_DEVTOOLS_PATH
+    xALT_DEVTOOLS_PATH  :="$(subst \,/,$(ALT_DEVTOOLS_PATH))"
+    fxALT_DEVTOOLS_PATH :=$(call FullPath,$(xALT_DEVTOOLS_PATH))
+    DEVTOOLS_PATH       :=$(call PrefixPath,$(fxALT_DEVTOOLS_PATH))
   else
-    xDEVTOOLS_PATH  :="$(_system_drive)/utils"
-    fxDEVTOOLS_PATH :=$(call FullPath,$(xDEVTOOLS_PATH))
-    DEVTOOLS_PATH  :=$(call PrefixPath,$(fxDEVTOOLS_PATH))
+    ifdef USING_CYGWIN
+      DEVTOOLS_PATH :=$(UNIXCOMMAND_PATH)
+    else
+      xDEVTOOLS_PATH  :="$(_system_drive)/utils"
+      fxDEVTOOLS_PATH :=$(call FullPath,$(xDEVTOOLS_PATH))
+      DEVTOOLS_PATH  :=$(call PrefixPath,$(fxDEVTOOLS_PATH))
+    endif
   endif
+  DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
+  export DEVTOOLS_PATH
 endif
-DEVTOOLS_PATH:=$(call AltCheckSpaces,DEVTOOLS_PATH)
 
 # _BOOTDIR1: First choice for a Bootstrap JDK, previous released JDK.
 # _BOOTDIR2: Second choice
@@ -410,20 +415,26 @@
 
 # BUILD_JDK_IMPORT_PATH: location of JDK install trees to import for
 #   multiple platforms, e.g. windows-i586, solaris-sparc, linux-586, etc.
-ifdef ALT_BUILD_JDK_IMPORT_PATH
-  BUILD_JDK_IMPORT_PATH  :=$(call FullPath,$(ALT_BUILD_JDK_IMPORT_PATH))
-else
-  BUILD_JDK_IMPORT_PATH   = $(PROMOTED_BUILD_BINARIES)
+ifndef BUILD_JDK_IMPORT_PATH
+  ifdef ALT_BUILD_JDK_IMPORT_PATH
+    BUILD_JDK_IMPORT_PATH  :=$(call FullPath,$(ALT_BUILD_JDK_IMPORT_PATH))
+  else
+    BUILD_JDK_IMPORT_PATH   = $(PROMOTED_BUILD_BINARIES)
+  endif
+  BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
+  BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
+  export BUILD_JDK_IMPORT_PATH
 endif
-BUILD_JDK_IMPORT_PATH:=$(call AltCheckSpaces,BUILD_JDK_IMPORT_PATH)
-BUILD_JDK_IMPORT_PATH:=$(call AltCheckValue,BUILD_JDK_IMPORT_PATH)
 
 # JDK_IMPORT_PATH: location of previously built JDK (this version) to import
-ifdef ALT_JDK_IMPORT_PATH
-  JDK_IMPORT_PATH  :=$(call FullPath,$(ALT_JDK_IMPORT_PATH))
-else
-  JDK_IMPORT_PATH   = $(BUILD_JDK_IMPORT_PATH)/$(PLATFORM)-$(ARCH)$(_JDK_IMPORT_VARIANT)
+ifndef JDK_IMPORT_PATH
+  ifdef ALT_JDK_IMPORT_PATH
+    JDK_IMPORT_PATH  :=$(call FullPath,$(ALT_JDK_IMPORT_PATH))
+  else
+    JDK_IMPORT_PATH   = $(BUILD_JDK_IMPORT_PATH)/$(PLATFORM)-$(ARCH)$(_JDK_IMPORT_VARIANT)
+  endif
+  JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
+  JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
+  export JDK_IMPORT_PATH
 endif
-JDK_IMPORT_PATH:=$(call AltCheckSpaces,JDK_IMPORT_PATH)
-JDK_IMPORT_PATH:=$(call AltCheckValue,JDK_IMPORT_PATH)
 
--- a/corba/make/common/shared/Defs.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/shared/Defs.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -228,12 +228,15 @@
 endif
 
 # FULL_VERSION is RELEASE and -BUILD_NUMBER if BUILD_NUMBER is set
-ifdef BUILD_NUMBER
-  FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
-else
-  BUILD_NUMBER = b00
-  USER_RELEASE_SUFFIX := $(shell echo $(USER)_`date '+%d_%b_%Y_%H_%M' | tr "A-Z" "a-z"`)
-  FULL_VERSION = $(RELEASE)-$(USER_RELEASE_SUFFIX)-$(BUILD_NUMBER)
+ifndef FULL_VERSION
+  ifdef BUILD_NUMBER
+    FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER)
+  else
+    BUILD_NUMBER = b00
+    USER_RELEASE_SUFFIX := $(shell echo $(USER)_`date '+%d_%b_%Y_%H_%M' | tr "A-Z" "a-z"`)
+    FULL_VERSION = $(RELEASE)-$(USER_RELEASE_SUFFIX)-$(BUILD_NUMBER)
+  endif
+  export FULL_VERSION
 endif
 
 # Promoted build location
--- a/corba/make/common/shared/Platform.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/common/shared/Platform.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -84,21 +84,14 @@
 #     REQUIRED_LINUX_VER          linux only: required version of linux
 #     REQUIRED_LINUX_FULLVER      linux only: required full version of linux
 
-SYSTEM_UNAME := $(shell uname)
+ifndef SYSTEM_UNAME
+  SYSTEM_UNAME := $(shell uname)
+  export SYSTEM_UNAME
+endif
 
 # Normal boot jdk is previous release, but a hard requirement is a 1.5 boot
 REQUIRED_BOOT_VER = 1.5
 
-#
-# Prune out all known SCM (Source Code Management) directories
-# so they will not be included when copying directory trees
-# or packaging up .jar files, etc.  This applies to all workspaces.
-#
-SCM_DIRs = .hg .svn CVS RCS SCCS Codemgr_wsdata deleted_files
-# When changing SCM_DIRs also change SCM_DIRS_rexp and SCM_DIRS_prune:
-SCM_DIRS_rexp = ".hg|.svn|CVS|RCS|SCCS|Codemgr_wsdata|deleted_files"
-SCM_DIRS_prune = \( -name .hg -o -name .svn -o -name CVS -o -name RCS -o -name SCCS -o -name Codemgr_wsdata -o -name deleted_files \) -prune
-
 # Don't define this unless it's not defined
 ifndef VARIANT
   VARIANT=OPT
@@ -372,14 +365,17 @@
   REQUIRED_FREE_SPACE=500000
   OS_VENDOR = Microsoft
   # How much RAM does this machine have:
-  MB_OF_MEMORY := $(shell \
-    if [ -f "C:/cygwin/bin/free.exe" ] ; then \
-      ( C:/cygwin/bin/bash.exe -c "C:/cygwin/bin/free.exe -m" ) | \
-	grep Mem: | \
-	sed -e 's@\ \ *@ @g' | cut -d' ' -f2 ; \
-    else \
-      echo "512"; \
-    fi)
+  ifndef MB_OF_MEMORY
+    MB_OF_MEMORY := $(shell \
+      if [ -f "C:/cygwin/bin/free.exe" ] ; then \
+        ( C:/cygwin/bin/bash.exe -c "C:/cygwin/bin/free.exe -m" ) | \
+	  grep Mem: | \
+	  sed -e 's@\ \ *@ @g' | cut -d' ' -f2 ; \
+      else \
+        echo "512"; \
+      fi)
+    export MB_OF_MEMORY
+  endif
 endif
 
 # Machines with 512Mb or less of real memory are considered low memory
@@ -387,30 +383,36 @@
 #    system swapping during the build.
 #    If we don't know, assume 512. Subtract 128 from MB for VM MAX.
 #    Don't set VM max over 1024-128=896.
-ifneq ($(MB_OF_MEMORY),)
-  LOW_MEMORY_MACHINE := $(shell \
-    if [ $(MB_OF_MEMORY) -le 512 ] ; then \
-      echo "true"; \
-    else \
-      echo "false"; \
-    fi)
-  MAX_VM_MEMORY := $(shell \
-    if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
-      expr $(MB_OF_MEMORY) '-' 128 ; \
-    else \
-      echo "896"; \
-    fi)
-  MIN_VM_MEMORY := $(shell \
-    if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
-      expr $(MAX_VM_MEMORY) '-' 8 ; \
-    else \
-      echo "128"; \
-    fi)
-else
-  MB_OF_MEMORY       := unknown
-  LOW_MEMORY_MACHINE := true
-  MAX_VM_MEMORY      := 384
-  MIN_VM_MEMORY      := 128
+ifndef MAX_VM_MEMORY
+  ifneq ($(MB_OF_MEMORY),)
+    LOW_MEMORY_MACHINE := $(shell \
+      if [ $(MB_OF_MEMORY) -le 512 ] ; then \
+        echo "true"; \
+      else \
+        echo "false"; \
+      fi)
+    MAX_VM_MEMORY := $(shell \
+      if [ $(MB_OF_MEMORY) -le 1024 ] ; then \
+        expr $(MB_OF_MEMORY) '-' 128 ; \
+      else \
+        echo "896"; \
+      fi)
+    MIN_VM_MEMORY := $(shell \
+      if [ $(MAX_VM_MEMORY) -le 128 ] ; then \
+        expr $(MAX_VM_MEMORY) '-' 8 ; \
+      else \
+        echo "128"; \
+      fi)
+  else
+    MB_OF_MEMORY       := unknown
+    LOW_MEMORY_MACHINE := true
+    MAX_VM_MEMORY      := 384
+    MIN_VM_MEMORY      := 128
+  endif
+  export MAX_VM_MEMORY
+  export MIN_VM_MEMORY
+  export LOW_MEMORY_MACHINE
+  export MAX_VM_MEMORY
 endif
 
 REQUIRED_ZIP_VER = 2.2
--- a/corba/make/jprt.properties	Mon Sep 28 19:38:55 2009 -0700
+++ b/corba/make/jprt.properties	Wed Jul 05 17:01:09 2017 +0200
@@ -34,8 +34,8 @@
 solaris_x64_5.10,\
 linux_i586_2.6,\
 linux_x64_2.6,\
-windows_i586,\
-windows_x64
+windows_i586_5.0,\
+windows_x64_5.2
 
 # The different build flavors we want
 jprt.build.flavors=product,fastdebug
--- a/hotspot/.hgtags	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/.hgtags	Wed Jul 05 17:01:09 2017 +0200
@@ -46,3 +46,4 @@
 54fd4d9232969ea6cd3d236e5ad276183bb0d423 jdk7-b69
 0632c3e615a315ff11e2ab1d64f4d82ff9853461 jdk7-b70
 50a95aa4a247f0cbbf66df285a8b1d78ffb153d9 jdk7-b71
+a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
--- a/hotspot/agent/make/saenv.sh	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/agent/make/saenv.sh	Wed Jul 05 17:01:09 2017 +0200
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2003-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
--- a/hotspot/agent/make/saenv64.sh	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/agent/make/saenv64.sh	Wed Jul 05 17:01:09 2017 +0200
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2003-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
--- a/hotspot/agent/src/os/solaris/proc/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/agent/src/os/solaris/proc/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2002-2006 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
--- a/hotspot/agent/src/os/solaris/proc/mapfile	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/agent/src/os/solaris/proc/mapfile	Wed Jul 05 17:01:09 2017 +0200
@@ -1,7 +1,7 @@
 #
 
 #
-# Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2003-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
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/CompactibleFreeListSpace.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeChunk.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/memory/FreeChunk.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
--- a/hotspot/make/hotspot_version	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/hotspot_version	Wed Jul 05 17:01:09 2017 +0200
@@ -35,7 +35,7 @@
 
 HS_MAJOR_VER=17
 HS_MINOR_VER=0
-HS_BUILD_NUMBER=01
+HS_BUILD_NUMBER=02
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=7
--- a/hotspot/make/linux/makefiles/jvmti.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/linux/makefiles/jvmti.make	Wed Jul 05 17:01:09 2017 +0200
@@ -70,10 +70,10 @@
 both = $(JvmtiGenClass) $(JvmtiSrcDir)/jvmti.xml $(JvmtiSrcDir)/jvmtiLib.xsl
 
 $(JvmtiGenClass): $(JvmtiGenSource)
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -g -d $(JvmtiOutDir) $(JvmtiGenSource)
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiGenSource)
 
 $(JvmtiEnvFillClass): $(JvmtiEnvFillSource)
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -g -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
 
 $(JvmtiOutDir)/jvmtiEnter.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl
 	@echo Generating $@
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug	Wed Jul 05 17:01:09 2017 +0200
@@ -74,6 +74,7 @@
                 JVM_CurrentTimeMillis;
                 JVM_DefineClass;
                 JVM_DefineClassWithSource;
+                JVM_DefineClassWithSourceCond;
                 JVM_DesiredAssertionStatus;
                 JVM_DisableCompiler;
                 JVM_DoPrivileged;
--- a/hotspot/make/linux/makefiles/mapfile-vers-product	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product	Wed Jul 05 17:01:09 2017 +0200
@@ -74,6 +74,7 @@
                 JVM_CurrentTimeMillis;
                 JVM_DefineClass;
                 JVM_DefineClassWithSource;
+                JVM_DefineClassWithSourceCond;
                 JVM_DesiredAssertionStatus;
                 JVM_DisableCompiler;
                 JVM_DoPrivileged;
--- a/hotspot/make/linux/makefiles/rules.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/linux/makefiles/rules.make	Wed Jul 05 17:01:09 2017 +0200
@@ -122,12 +122,20 @@
 endif
 endif
 
+COMPILE.JAVAC += $(BOOTSTRAP_JAVAC_FLAGS)
+
 SUM = /usr/bin/sum
 
 # 'gmake MAKE_VERBOSE=y' gives all the gory details.
 QUIETLY$(MAKE_VERBOSE)  = @
 RUN.JAR$(MAKE_VERBOSE) += >/dev/null
 
+# Settings for javac
+BOOT_SOURCE_LANGUAGE_VERSION = 6
+BOOT_TARGET_CLASS_VERSION = 6
+JAVAC_FLAGS = -g -encoding ascii
+BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
+
 # With parallel makes, print a message at the end of compilation.
 ifeq    ($(findstring j,$(MFLAGS)),j)
 COMPILE_DONE    = && { echo Done with $<; }
--- a/hotspot/make/linux/makefiles/sa.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/linux/makefiles/sa.make	Wed Jul 05 17:01:09 2017 +0200
@@ -74,8 +74,8 @@
 	  mkdir -p $(SA_CLASSDIR);        \
 	fi
 
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1)
-	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2)
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1)
+	$(QUIETLY) $(REMOTE) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2)
 
 	$(QUIETLY) $(REMOTE) $(COMPILE.RMIC)  -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
--- a/hotspot/make/linux/makefiles/top.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/linux/makefiles/top.make	Wed Jul 05 17:01:09 2017 +0200
@@ -24,7 +24,7 @@
 
 # top.make is included in the Makefile in the build directories.
 # It DOES NOT include the vm dependency info in order to be faster.
-# It's main job is to implement the incremental form of make lists.
+# Its main job is to implement the incremental form of make lists.
 # It also:
 #   -builds and runs adlc via adlc.make
 #   -generates JVMTI source and docs via jvmti.make (JSR-163)
@@ -114,7 +114,7 @@
 # make makeDeps: (and zap the cached db files to force a nonincremental run)
 
 $(GENERATED)/$(MakeDepsClass): $(MakeDepsSources)
-	@$(REMOTE) $(COMPILE.JAVAC) -classpath $(GAMMADIR)/src/share/tools/MakeDeps -g -d $(GENERATED) $(MakeDepsSources)
+	@$(REMOTE) $(COMPILE.JAVAC) -classpath $(GAMMADIR)/src/share/tools/MakeDeps -d $(GENERATED) $(MakeDepsSources)
 	@echo Removing $(Incremental_Lists) to force regeneration.
 	@rm -f $(Incremental_Lists)
 	@$(CDG) echo >$(Cached_plat)
--- a/hotspot/make/solaris/makefiles/jvmti.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/solaris/makefiles/jvmti.make	Wed Jul 05 17:01:09 2017 +0200
@@ -69,10 +69,10 @@
 both = $(JvmtiGenClass) $(JvmtiSrcDir)/jvmti.xml $(JvmtiSrcDir)/jvmtiLib.xsl
 
 $(JvmtiGenClass): $(JvmtiGenSource)
-	$(QUIETLY) $(COMPILE.JAVAC) -g -d $(JvmtiOutDir) $(JvmtiGenSource)
+	$(QUIETLY) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiGenSource)
 
 $(JvmtiEnvFillClass): $(JvmtiEnvFillSource)
-	$(QUIETLY) $(COMPILE.JAVAC) -g -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
+	$(QUIETLY) $(COMPILE.JAVAC) -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
 
 $(JvmtiOutDir)/jvmtiEnter.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl
 	@echo Generating $@
--- a/hotspot/make/solaris/makefiles/mapfile-vers	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/solaris/makefiles/mapfile-vers	Wed Jul 05 17:01:09 2017 +0200
@@ -74,6 +74,7 @@
 		JVM_CurrentTimeMillis;
 		JVM_DefineClass;
 		JVM_DefineClassWithSource;
+		JVM_DefineClassWithSourceCond;
 		JVM_DesiredAssertionStatus;
 		JVM_DisableCompiler;
 		JVM_DoPrivileged;
--- a/hotspot/make/solaris/makefiles/rules.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/solaris/makefiles/rules.make	Wed Jul 05 17:01:09 2017 +0200
@@ -122,12 +122,20 @@
 endif
 endif
 
+COMPILE.JAVAC += $(BOOTSTRAP_JAVAC_FLAGS)
+
 SUM = /usr/bin/sum
 
 # 'gmake MAKE_VERBOSE=y' gives all the gory details.
 QUIETLY$(MAKE_VERBOSE)  = @
 RUN.JAR$(MAKE_VERBOSE) += >/dev/null
 
+# Settings for javac
+BOOT_SOURCE_LANGUAGE_VERSION = 6
+BOOT_TARGET_CLASS_VERSION = 6
+JAVAC_FLAGS = -g -encoding ascii
+BOOTSTRAP_JAVAC_FLAGS = $(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
+
 # With parallel makes, print a message at the end of compilation.
 ifeq    ($(findstring j,$(MFLAGS)),j)
 COMPILE_DONE    = && { echo Done with $<; }
--- a/hotspot/make/solaris/makefiles/sa.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/solaris/makefiles/sa.make	Wed Jul 05 17:01:09 2017 +0200
@@ -67,8 +67,8 @@
 	$(QUIETLY) if [ ! -d $(SA_CLASSDIR) ] ; then \
 	  mkdir -p $(SA_CLASSDIR);        \
 	fi
-	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1)
-	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2)
+	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1)
+	$(QUIETLY) $(COMPILE.JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2)
 	
 	$(QUIETLY) $(COMPILE.RMIC)  -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	$(QUIETLY) echo "$(SA_BUILD_VERSION_PROP)" > $(SA_PROPERTIES)
--- a/hotspot/make/solaris/makefiles/top.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/solaris/makefiles/top.make	Wed Jul 05 17:01:09 2017 +0200
@@ -24,7 +24,7 @@
 
 # top.make is included in the Makefile in the build directories.
 # It DOES NOT include the vm dependency info in order to be faster.
-# It's main job is to implement the incremental form of make lists.
+# Its main job is to implement the incremental form of make lists.
 # It also:
 #   -builds and runs adlc via adlc.make
 #   -generates JVMTI source and docs via jvmti.make (JSR-163)
@@ -112,7 +112,7 @@
 # make makeDeps: (and zap the cached db files to force a nonincremental run)
 
 $(GENERATED)/$(MakeDepsClass): $(MakeDepsSources)
-	@$(COMPILE.JAVAC) -classpath $(GAMMADIR)/src/share/tools/MakeDeps -g -d $(GENERATED) $(MakeDepsSources)
+	@$(COMPILE.JAVAC) -classpath $(GAMMADIR)/src/share/tools/MakeDeps -d $(GENERATED) $(MakeDepsSources)
 	@echo Removing $(Incremental_Lists) to force regeneration.
 	@rm -f $(Incremental_Lists)
 	@$(CDG) echo >$(Cached_plat)
--- a/hotspot/make/windows/makefiles/generated.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/windows/makefiles/generated.make	Wed Jul 05 17:01:09 2017 +0200
@@ -91,7 +91,7 @@
 classes/MakeDeps.class: $(MakeDepsSources)
 	if exist classes rmdir /s /q classes
 	mkdir classes
-	$(COMPILE_JAVAC) -classpath $(WorkSpace)\src\share\tools\MakeDeps -g -d classes $(MakeDepsSources)
+	$(COMPILE_JAVAC) -classpath $(WorkSpace)\src\share\tools\MakeDeps -d classes $(MakeDepsSources)
 
 !if ("$(Variant)" == "compiler2") || ("$(Variant)" == "tiered")
 
--- a/hotspot/make/windows/makefiles/jvmti.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/windows/makefiles/jvmti.make	Wed Jul 05 17:01:09 2017 +0200
@@ -68,10 +68,10 @@
         @if not exist $(JvmtiOutDir) mkdir $(JvmtiOutDir)
 
 $(JvmtiGenClass): $(JvmtiGenSource)
-	$(COMPILE_JAVAC) -g -d $(JvmtiOutDir) $(JvmtiGenSource)
+	$(COMPILE_JAVAC) -d $(JvmtiOutDir) $(JvmtiGenSource)
 
 $(JvmtiEnvFillClass): $(JvmtiEnvFillSource)
-	@$(COMPILE_JAVAC) -g -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
+	@$(COMPILE_JAVAC) -d $(JvmtiOutDir) $(JvmtiEnvFillSource)
 
 $(JvmtiOutDir)/jvmtiEnter.cpp: $(both) $(JvmtiSrcDir)/jvmtiEnter.xsl
 	@echo Generating $@
--- a/hotspot/make/windows/makefiles/rules.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/windows/makefiles/rules.make	Wed Jul 05 17:01:09 2017 +0200
@@ -29,7 +29,7 @@
 RUN_JAVAP=$(BootStrapDir)\bin\javap
 RUN_JAVAH=$(BootStrapDir)\bin\javah
 RUN_JAR=$(BootStrapDir)\bin\jar
-COMPILE_JAVAC=$(BootStrapDir)\bin\javac
+COMPILE_JAVAC=$(BootStrapDir)\bin\javac $(BOOTSTRAP_JAVAC_FLAGS)
 COMPILE_RMIC=$(BootStrapDir)\bin\rmic
 BOOT_JAVA_HOME=$(BootStrapDir)
 !else
@@ -37,11 +37,17 @@
 RUN_JAVAP=javap
 RUN_JAVAH=javah
 RUN_JAR=jar
-COMPILE_JAVAC=javac
+COMPILE_JAVAC=javac $(BOOTSTRAP_JAVAC_FLAGS)
 COMPILE_RMIC=rmic
 BOOT_JAVA_HOME=
 !endif
 
+# Settings for javac
+BOOT_SOURCE_LANGUAGE_VERSION=6
+BOOT_TARGET_CLASS_VERSION=6
+JAVAC_FLAGS=-g -encoding ascii
+BOOTSTRAP_JAVAC_FLAGS=$(JAVAC_FLAGS) -source $(BOOT_SOURCE_LANGUAGE_VERSION) -target $(BOOT_TARGET_CLASS_VERSION)
+
 ProjectFile=vm.vcproj
 
 !if "$(MSC_VER)" == "1200"
--- a/hotspot/make/windows/makefiles/sa.make	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/windows/makefiles/sa.make	Wed Jul 05 17:01:09 2017 +0200
@@ -55,9 +55,9 @@
 $(GENERATED)\sa-jdi.jar: $(AGENT_FILES1:/=\) $(AGENT_FILES2:/=\)
 	@if not exist $(SA_CLASSDIR) mkdir $(SA_CLASSDIR)
 	@echo ...Building sa-jdi.jar
-	@echo ...$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -g -d $(SA_CLASSDIR) ....
-	@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
-	@$(COMPILE_JAVAC) -source 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -g -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
+	@echo ...$(COMPILE_JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -d $(SA_CLASSDIR) ....
+	@$(COMPILE_JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES1:/=\)
+	@$(COMPILE_JAVAC) -source 1.4 -target 1.4 -classpath $(SA_CLASSPATH) -sourcepath $(AGENT_SRC_DIR) -d $(SA_CLASSDIR) $(AGENT_FILES2:/=\)
 	$(COMPILE_RMIC) -classpath $(SA_CLASSDIR) -d $(SA_CLASSDIR) sun.jvm.hotspot.debugger.remote.RemoteDebuggerServer
 	$(QUIETLY) echo $(SA_BUILD_VERSION_PROP)> $(SA_PROPERTIES)
 	$(QUIETLY) rm -f $(SA_CLASSDIR)/sun/jvm/hotspot/utilities/soql/sa.js
--- a/hotspot/make/windows/projectfiles/common/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/make/windows/projectfiles/common/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -179,6 +179,6 @@
 $(HOTSPOTBUILDSPACE)/classes/MakeDeps.class: $(MakeDepsSources)
 	@if exist $(HOTSPOTBUILDSPACE)\classes rmdir /s /q $(HOTSPOTBUILDSPACE)\classes
 	@mkdir $(HOTSPOTBUILDSPACE)\classes
-	@$(COMPILE_JAVAC) -classpath $(HOTSPOTWORKSPACE)\src\share\tools\MakeDeps -g -d $(HOTSPOTBUILDSPACE)/classes $(MakeDepsSources)
+	@$(COMPILE_JAVAC) -classpath $(HOTSPOTWORKSPACE)\src\share\tools\MakeDeps -d $(HOTSPOTBUILDSPACE)/classes $(MakeDepsSources)
 
 FORCE:
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1696,6 +1696,9 @@
 void InterpreterMacroAssembler::record_klass_in_profile_helper(
                                         Register receiver, Register scratch,
                                         int start_row, Label& done) {
+  if (TypeProfileWidth == 0)
+    return;
+
   int last_row = VirtualCallData::row_limit() - 1;
   assert(start_row <= last_row, "must be work left to do");
   // Test this row for both the receiver and for null.
--- a/hotspot/src/cpu/sparc/vm/sparc.ad	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad	Wed Jul 05 17:01:09 2017 +0200
@@ -5707,7 +5707,7 @@
   effect(TEMP dst, TEMP tmp);
   ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
 
-  size(3*4);
+  size((3+1)*4);  // set may use two instructions.
   format %{ "LDUH   $mem,$dst\t! ushort/char & 16-bit mask -> long\n\t"
             "SET    $mask,$tmp\n\t"
             "AND    $dst,$tmp,$dst" %}
@@ -5851,7 +5851,7 @@
   effect(TEMP dst, TEMP tmp);
   ins_cost(MEMORY_REF_COST + 2*DEFAULT_COST);
 
-  size(3*4);
+  size((3+1)*4);  // set may use two instructions.
   format %{ "LDUW   $mem,$dst\t! int & 32-bit mask -> long\n\t"
             "SET    $mask,$tmp\n\t"
             "AND    $dst,$tmp,$dst" %}
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
@@ -827,8 +827,8 @@
     case vmIntrinsics::_dsin:   __ sin  (calc_input, calc_result, tmp1, tmp2);              break;
     case vmIntrinsics::_dcos:   __ cos  (calc_input, calc_result, tmp1, tmp2);              break;
     case vmIntrinsics::_dtan:   __ tan  (calc_input, calc_result, tmp1, tmp2);              break;
-    case vmIntrinsics::_dlog:   __ log  (calc_input, calc_result, LIR_OprFact::illegalOpr); break;
-    case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, LIR_OprFact::illegalOpr); break;
+    case vmIntrinsics::_dlog:   __ log  (calc_input, calc_result, tmp1);                    break;
+    case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1);                    break;
     default:                    ShouldNotReachHere();
   }
 
--- a/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/c1_LinearScan_x86.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -764,8 +764,6 @@
       break;
     }
 
-    case lir_log:
-    case lir_log10:
     case lir_abs:
     case lir_sqrt: {
       // Right argument appears to be unused
@@ -785,6 +783,30 @@
       break;
     }
 
+    case lir_log:
+    case lir_log10: {
+      // log and log10 needs one temporary fpu stack slot, so there is ontemporary
+      // registers stored in temp of the operation.
+      // the stack allocator must guarantee that the stack slots are really free,
+      // otherwise there might be a stack overflow.
+      assert(right->is_illegal(), "must be");
+      assert(left->is_fpu_register(), "must be");
+      assert(res->is_fpu_register(), "must be");
+      assert(op2->tmp_opr()->is_fpu_register(), "must be");
+
+      insert_free_if_dead(op2->tmp_opr());
+      insert_free_if_dead(res, left);
+      insert_exchange(left);
+      do_rename(left, res);
+
+      new_left = to_fpu_stack_top(res);
+      new_res = new_left;
+
+      op2->set_fpu_stack_size(sim()->stack_size());
+      assert(sim()->stack_size() <= 7, "at least one stack slot must be free");
+      break;
+    }
+
 
     case lir_tan:
     case lir_sin:
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1262,6 +1262,9 @@
                                         Register receiver, Register mdp,
                                         Register reg2,
                                         int start_row, Label& done) {
+  if (TypeProfileWidth == 0)
+    return;
+
   int last_row = VirtualCallData::row_limit() - 1;
   assert(start_row <= last_row, "must be work left to do");
   // Test this row for both the receiver and for null.
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1272,6 +1272,9 @@
                                         Register receiver, Register mdp,
                                         Register reg2,
                                         int start_row, Label& done) {
+  if (TypeProfileWidth == 0)
+    return;
+
   int last_row = VirtualCallData::row_limit() - 1;
   assert(start_row <= last_row, "must be work left to do");
   // Test this row for both the receiver and for null.
--- a/hotspot/src/os/windows/vm/os_windows.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1526,7 +1526,8 @@
     case 5000: st->print(" Windows 2000"); break;
     case 5001: st->print(" Windows XP"); break;
     case 5002:
-    case 6000: {
+    case 6000:
+    case 6001: {
       // Retrieve SYSTEM_INFO from GetNativeSystemInfo call so that we could
       // find out whether we are running on 64 bit processor or not.
       SYSTEM_INFO si;
@@ -1549,13 +1550,27 @@
           st->print(" Windows XP x64 Edition");
         else
             st->print(" Windows Server 2003 family");
-      } else { // os_vers == 6000
+      } else if (os_vers == 6000) {
         if (osvi.wProductType == VER_NT_WORKSTATION)
             st->print(" Windows Vista");
         else
             st->print(" Windows Server 2008");
         if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
             st->print(" , 64 bit");
+      } else if (os_vers == 6001) {
+        if (osvi.wProductType == VER_NT_WORKSTATION) {
+            st->print(" Windows 7");
+        } else {
+            // Unrecognized windows, print out its major and minor versions
+            st->print(" Windows NT %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
+        }
+        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+            st->print(" , 64 bit");
+      } else { // future os
+        // Unrecognized windows, print out its major and minor versions
+        st->print(" Windows NT %d.%d", osvi.dwMajorVersion, osvi.dwMinorVersion);
+        if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
+            st->print(" , 64 bit");
       }
       break;
     }
--- a/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/atomic_solaris_sparc.inline.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/os_cpu/solaris_x86/vm/atomic_solaris_x86.inline.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/adlc/archDesc.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/adlc/archDesc.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1031,7 +1031,8 @@
 //---------------------------addSUNcopyright-------------------------------
 // output SUN copyright info
 void ArchDesc::addSunCopyright(char* legal, int size, FILE *fp) {
-  fwrite(legal, size, 1, fp);
+  size_t count = fwrite(legal, 1, size, fp);
+  assert(count == (size_t) size, "copyright info truncated");
   fprintf(fp,"\n");
   fprintf(fp,"// Machine Generated File.  Do Not Edit!\n");
   fprintf(fp,"\n");
--- a/hotspot/src/share/vm/c1/c1_IR.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_IR.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2008 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
--- a/hotspot/src/share/vm/c1/c1_IR.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_IR.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2006 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
--- a/hotspot/src/share/vm/c1/c1_LIR.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -567,8 +567,6 @@
     case lir_rem:
     case lir_sqrt:
     case lir_abs:
-    case lir_log:
-    case lir_log10:
     case lir_logic_and:
     case lir_logic_or:
     case lir_logic_xor:
@@ -644,13 +642,16 @@
 
     case lir_tan:
     case lir_sin:
-    case lir_cos: {
+    case lir_cos:
+    case lir_log:
+    case lir_log10: {
       assert(op->as_Op2() != NULL, "must be");
       LIR_Op2* op2 = (LIR_Op2*)op;
 
-      // sin and cos need two temporary fpu stack slots, so register
-      // two temp operands.  Register input operand as temp to
-      // guarantee that they do not overlap
+      // On x86 tan/sin/cos need two temporary fpu stack slots and
+      // log/log10 need one so handle opr2 and tmp as temp inputs.
+      // Register input operand as temp to guarantee that it doesn't
+      // overlap with the input.
       assert(op2->_info == NULL, "not used");
       assert(op2->_opr1->is_valid(), "used");
       do_input(op2->_opr1); do_temp(op2->_opr1);
--- a/hotspot/src/share/vm/c1/c1_LIR.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIR.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1840,8 +1840,8 @@
 
   void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_abs , from, tmp, to)); }
   void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_sqrt, from, tmp, to)); }
-  void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_log,  from, tmp, to)); }
-  void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)              { append(new LIR_Op2(lir_log10, from, tmp, to)); }
+  void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)                { append(new LIR_Op2(lir_log,  from, LIR_OprFact::illegalOpr, to, tmp)); }
+  void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp)              { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
   void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
   void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }
   void tan (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_tan , from, tmp1, to, tmp2)); }
--- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2008 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
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -2547,6 +2547,7 @@
                                                     KlassHandle host_klass,
                                                     GrowableArray<Handle>* cp_patches,
                                                     symbolHandle& parsed_name,
+                                                    bool verify,
                                                     TRAPS) {
   // So that JVMTI can cache class file in the state before retransformable agents
   // have modified it
@@ -2591,7 +2592,7 @@
   instanceKlassHandle nullHandle;
 
   // Figure out whether we can skip format checking (matching classic VM behavior)
-  _need_verify = Verifier::should_verify_for(class_loader());
+  _need_verify = Verifier::should_verify_for(class_loader(), verify);
 
   // Set the verify flag in stream
   cfs->set_verify(_need_verify);
@@ -3210,6 +3211,7 @@
 
     // Fill in information already parsed
     this_klass->set_access_flags(access_flags);
+    this_klass->set_should_verify_class(verify);
     jint lh = Klass::instance_layout_helper(instance_size, false);
     this_klass->set_layout_helper(lh);
     assert(this_klass->oop_is_instance(), "layout is correct");
@@ -3229,6 +3231,12 @@
       this_klass->set_has_final_method();
     }
     this_klass->set_method_ordering(method_ordering());
+    // The instanceKlass::_methods_jmethod_ids cache and the
+    // instanceKlass::_methods_cached_itable_indices cache are
+    // both managed on the assumption that the initial cache
+    // size is equal to the number of methods in the class. If
+    // that changes, then instanceKlass::idnum_can_increment()
+    // has to be changed accordingly.
     this_klass->set_initial_method_idnum(methods->length());
     this_klass->set_name(cp->klass_name_at(this_class_index));
     if (LinkWellKnownClasses || is_anonymous())  // I am well known to myself
--- a/hotspot/src/share/vm/classfile/classFileParser.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -260,9 +260,10 @@
                                      Handle class_loader,
                                      Handle protection_domain,
                                      symbolHandle& parsed_name,
+                                     bool verify,
                                      TRAPS) {
     KlassHandle no_host_klass;
-    return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, THREAD);
+    return parseClassFile(name, class_loader, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD);
   }
   instanceKlassHandle parseClassFile(symbolHandle name,
                                      Handle class_loader,
@@ -270,6 +271,7 @@
                                      KlassHandle host_klass,
                                      GrowableArray<Handle>* cp_patches,
                                      symbolHandle& parsed_name,
+                                     bool verify,
                                      TRAPS);
 
   // Verifier checks
--- a/hotspot/src/share/vm/classfile/classLoader.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -874,6 +874,7 @@
                                                        class_loader,
                                                        protection_domain,
                                                        parsed_name,
+                                                       false,
                                                        CHECK_(h));
 
     // add to package table
--- a/hotspot/src/share/vm/classfile/classLoader.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 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
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -252,7 +252,7 @@
   typeArrayOop value  = java_lang_String::value(obj);
   int          offset = java_lang_String::offset(obj);
   int          length = java_lang_String::length(obj);
-  jchar* base = value->char_at_addr(offset);
+  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
   symbolOop sym = SymbolTable::lookup_unicode(base, length, THREAD);
   return symbolHandle(THREAD, sym);
 }
@@ -261,7 +261,7 @@
   typeArrayOop value  = java_lang_String::value(java_string);
   int          offset = java_lang_String::offset(java_string);
   int          length = java_lang_String::length(java_string);
-  jchar* base = value->char_at_addr(offset);
+  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
   return SymbolTable::probe_unicode(base, length);
 }
 
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -970,6 +970,7 @@
                                                              host_klass,
                                                              cp_patches,
                                                              parsed_name,
+                                                             true,
                                                              THREAD);
 
 
@@ -1025,6 +1026,7 @@
                                                Handle class_loader,
                                                Handle protection_domain,
                                                ClassFileStream* st,
+                                               bool verify,
                                                TRAPS) {
 
   // Classloaders that support parallelism, e.g. bootstrap classloader,
@@ -1055,6 +1057,7 @@
                                                              class_loader,
                                                              protection_domain,
                                                              parsed_name,
+                                                             verify,
                                                              THREAD);
 
   const char* pkg = "java/";
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -259,7 +259,9 @@
                                TRAPS);
 
   // Resolve from stream (called by jni_DefineClass and JVM_DefineClass)
-  static klassOop resolve_from_stream(symbolHandle class_name, Handle class_loader, Handle protection_domain, ClassFileStream* st, TRAPS);
+  static klassOop resolve_from_stream(symbolHandle class_name, Handle class_loader,
+                                      Handle protection_domain,
+                                      ClassFileStream* st, bool verify, TRAPS);
 
   // Lookup an already loaded class. If not found NULL is returned.
   static klassOop find(symbolHandle class_name, Handle class_loader, Handle protection_domain, TRAPS);
--- a/hotspot/src/share/vm/classfile/verifier.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -53,8 +53,8 @@
 
 // Methods in Verifier
 
-bool Verifier::should_verify_for(oop class_loader) {
-  return class_loader == NULL ?
+bool Verifier::should_verify_for(oop class_loader, bool should_verify_class) {
+  return (class_loader == NULL || !should_verify_class) ?
     BytecodeVerificationLocal : BytecodeVerificationRemote;
 }
 
@@ -68,7 +68,7 @@
   return !need_verify;
 }
 
-bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, TRAPS) {
+bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool should_verify_class, TRAPS) {
   ResourceMark rm(THREAD);
   HandleMark hm;
 
@@ -81,7 +81,7 @@
   // If the class should be verified, first see if we can use the split
   // verifier.  If not, or if verification fails and FailOverToOldVerifier
   // is set, then call the inference verifier.
-  if (is_eligible_for_verification(klass)) {
+  if (is_eligible_for_verification(klass, should_verify_class)) {
     if (TraceClassInitialization) {
       tty->print_cr("Start class verification for: %s", klassName);
     }
@@ -141,12 +141,13 @@
   }
 }
 
-bool Verifier::is_eligible_for_verification(instanceKlassHandle klass) {
+bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) {
   symbolOop name = klass->name();
   klassOop refl_magic_klass = SystemDictionary::reflect_magic_klass();
 
-  return (should_verify_for(klass->class_loader()) &&
+  return (should_verify_for(klass->class_loader(), should_verify_class) &&
     // return if the class is a bootstrapping class
+    // or defineClass specified not to verify by default (flags override passed arg)
     // We need to skip the following four for bootstraping
     name != vmSymbols::java_lang_Object() &&
     name != vmSymbols::java_lang_Class() &&
--- a/hotspot/src/share/vm/classfile/verifier.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/classfile/verifier.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -34,16 +34,18 @@
    * Otherwise, no exception is thrown and the return indicates the
    * error.
    */
-  static bool verify(instanceKlassHandle klass, Mode mode, TRAPS);
+  static bool verify(instanceKlassHandle klass, Mode mode, bool should_verify_class, TRAPS);
 
-  // Return false if the class is loaded by the bootstrap loader.
-  static bool should_verify_for(oop class_loader);
+  // Return false if the class is loaded by the bootstrap loader,
+  // or if defineClass was called requesting skipping verification
+  // -Xverify:all/none override this value
+  static bool should_verify_for(oop class_loader, bool should_verify_class);
 
   // Relax certain verifier checks to enable some broken 1.1 apps to run on 1.2.
   static bool relax_verify_for(oop class_loader);
 
  private:
-  static bool is_eligible_for_verification(instanceKlassHandle klass);
+  static bool is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class);
   static symbolHandle inference_verify(
     instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS);
 };
--- a/hotspot/src/share/vm/code/debugInfoRec.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/code/debugInfoRec.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-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
--- a/hotspot/src/share/vm/code/nmethod.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/compiler/oopMap.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/compiler/oopMap.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-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
--- a/hotspot/src/share/vm/compiler/oopMap.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/compiler/oopMap.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-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
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentZFThread.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentZFThread.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-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
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-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
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -302,9 +302,9 @@
     if (cur->isHumongous()) {
       return MemRegion(last_start, end);
     }
-    cur->reset_zero_fill();
     assert(cur == _regions.top(), "Should be top");
     if (!cur->is_empty()) break;
+    cur->reset_zero_fill();
     shrink_bytes -= cur->capacity();
     num_regions_deleted++;
     _regions.pop();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -2752,7 +2752,6 @@
   cm->revisit_klass_stack()->push(k);
 }
 
-#if ( defined(COMPILER1) || defined(COMPILER2) )
 void PSParallelCompact::revisit_mdo(ParCompactionManager* cm, DataLayout* p) {
   cm->revisit_mdo_stack()->push(p);
 }
@@ -2778,7 +2777,6 @@
     follow_stack(cm);
   }
 }
-#endif //  ( COMPILER1 || COMPILER2 )
 
 
 #ifdef VALIDATE_MARK_SWEEP
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
@@ -73,7 +73,6 @@
   follow_stack();
 }
 
-#if ( defined(COMPILER1) || defined(COMPILER2) )
 void MarkSweep::revisit_mdo(DataLayout* p) {
   _revisit_mdo_stack->push(p);
 }
@@ -92,7 +91,6 @@
   }
   follow_stack();
 }
-#endif //  ( COMPILER1 || COMPILER2 )
 
 MarkSweep::FollowRootClosure  MarkSweep::follow_root_closure;
 
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-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
--- a/hotspot/src/share/vm/memory/iterator.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/memory/iterator.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2001 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
--- a/hotspot/src/share/vm/memory/iterator.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/memory/iterator.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/memory/serialize.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/memory/serialize.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 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
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -110,7 +110,7 @@
   // 1) Verify the bytecodes
   Verifier::Mode mode =
     throw_verifyerror ? Verifier::ThrowException : Verifier::NoException;
-  return Verifier::verify(this_oop, mode, CHECK_false);
+  return Verifier::verify(this_oop, mode, this_oop->should_verify_class(), CHECK_false);
 }
 
 
@@ -967,33 +967,78 @@
 
 
 // Lookup or create a jmethodID.
-// This code can be called by the VM thread.  For this reason it is critical that
-// there are no blocking operations (safepoints) while the lock is held -- or a
-// deadlock can occur.
-jmethodID instanceKlass::jmethod_id_for_impl(instanceKlassHandle ik_h, methodHandle method_h) {
+// This code is called by the VMThread and JavaThreads so the
+// locking has to be done very carefully to avoid deadlocks
+// and/or other cache consistency problems.
+//
+jmethodID instanceKlass::get_jmethod_id(instanceKlassHandle ik_h, methodHandle method_h) {
   size_t idnum = (size_t)method_h->method_idnum();
   jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
   size_t length = 0;
   jmethodID id = NULL;
-  // array length stored in first element, other elements offset by one
-  if (jmeths == NULL ||                         // If there is no jmethodID array,
-      (length = (size_t)jmeths[0]) <= idnum ||  // or if it is too short,
-      (id = jmeths[idnum+1]) == NULL) {         // or if this jmethodID isn't allocated
+
+  // We use a double-check locking idiom here because this cache is
+  // performance sensitive. In the normal system, this cache only
+  // transitions from NULL to non-NULL which is safe because we use
+  // release_set_methods_jmethod_ids() to advertise the new cache.
+  // A partially constructed cache should never be seen by a racing
+  // thread. We also use release_store_ptr() to save a new jmethodID
+  // in the cache so a partially constructed jmethodID should never be
+  // seen either. Cache reads of existing jmethodIDs proceed without a
+  // lock, but cache writes of a new jmethodID requires uniqueness and
+  // creation of the cache itself requires no leaks so a lock is
+  // generally acquired in those two cases.
+  //
+  // If the RedefineClasses() API has been used, then this cache can
+  // grow and we'll have transitions from non-NULL to bigger non-NULL.
+  // Cache creation requires no leaks and we require safety between all
+  // cache accesses and freeing of the old cache so a lock is generally
+  // acquired when the RedefineClasses() API has been used.
 
-    // Do all the safepointing things (allocations) before grabbing the lock.
-    // These allocations will have to be freed if they are unused.
+  if (jmeths != NULL) {
+    // the cache already exists
+    if (!ik_h->idnum_can_increment()) {
+      // the cache can't grow so we can just get the current values
+      get_jmethod_id_length_value(jmeths, idnum, &length, &id);
+    } else {
+      // cache can grow so we have to be more careful
+      if (Threads::number_of_threads() == 0 ||
+          SafepointSynchronize::is_at_safepoint()) {
+        // we're single threaded or at a safepoint - no locking needed
+        get_jmethod_id_length_value(jmeths, idnum, &length, &id);
+      } else {
+        MutexLocker ml(JmethodIdCreation_lock);
+        get_jmethod_id_length_value(jmeths, idnum, &length, &id);
+      }
+    }
+  }
+  // implied else:
+  // we need to allocate a cache so default length and id values are good
 
-    // Allocate a new array of methods.
+  if (jmeths == NULL ||   // no cache yet
+      length <= idnum ||  // cache is too short
+      id == NULL) {       // cache doesn't contain entry
+
+    // This function can be called by the VMThread so we have to do all
+    // things that might block on a safepoint before grabbing the lock.
+    // Otherwise, we can deadlock with the VMThread or have a cache
+    // consistency issue. These vars keep track of what we might have
+    // to free after the lock is dropped.
+    jmethodID  to_dealloc_id     = NULL;
+    jmethodID* to_dealloc_jmeths = NULL;
+
+    // may not allocate new_jmeths or use it if we allocate it
     jmethodID* new_jmeths = NULL;
     if (length <= idnum) {
-      // A new array will be needed (unless some other thread beats us to it)
+      // allocate a new cache that might be used
       size_t size = MAX2(idnum+1, (size_t)ik_h->idnum_allocated_count());
       new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1);
       memset(new_jmeths, 0, (size+1)*sizeof(jmethodID));
-      new_jmeths[0] =(jmethodID)size;  // array size held in the first element
+      // cache size is stored in element[0], other elements offset by one
+      new_jmeths[0] = (jmethodID)size;
     }
 
-    // Allocate a new method ID.
+    // allocate a new jmethodID that might be used
     jmethodID new_id = NULL;
     if (method_h->is_old() && !method_h->is_obsolete()) {
       // The method passed in is old (but not obsolete), we need to use the current version
@@ -1007,63 +1052,111 @@
       new_id = JNIHandles::make_jmethod_id(method_h);
     }
 
-    if (Threads::number_of_threads() == 0 || SafepointSynchronize::is_at_safepoint()) {
-      // No need and unsafe to lock the JmethodIdCreation_lock at safepoint.
-      id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
+    if (Threads::number_of_threads() == 0 ||
+        SafepointSynchronize::is_at_safepoint()) {
+      // we're single threaded or at a safepoint - no locking needed
+      id = get_jmethod_id_fetch_or_update(ik_h, idnum, new_id, new_jmeths,
+                                          &to_dealloc_id, &to_dealloc_jmeths);
     } else {
       MutexLocker ml(JmethodIdCreation_lock);
-      id = get_jmethod_id(ik_h, idnum, new_id, new_jmeths);
+      id = get_jmethod_id_fetch_or_update(ik_h, idnum, new_id, new_jmeths,
+                                          &to_dealloc_id, &to_dealloc_jmeths);
+    }
+
+    // The lock has been dropped so we can free resources.
+    // Free up either the old cache or the new cache if we allocated one.
+    if (to_dealloc_jmeths != NULL) {
+      FreeHeap(to_dealloc_jmeths);
+    }
+    // free up the new ID since it wasn't needed
+    if (to_dealloc_id != NULL) {
+      JNIHandles::destroy_jmethod_id(to_dealloc_id);
     }
   }
   return id;
 }
 
 
-jmethodID instanceKlass::get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
-                                        jmethodID new_id, jmethodID* new_jmeths) {
-  // Retry lookup after we got the lock or ensured we are at safepoint
+// Common code to fetch the jmethodID from the cache or update the
+// cache with the new jmethodID. This function should never do anything
+// that causes the caller to go to a safepoint or we can deadlock with
+// the VMThread or have cache consistency issues.
+//
+jmethodID instanceKlass::get_jmethod_id_fetch_or_update(
+            instanceKlassHandle ik_h, size_t idnum, jmethodID new_id,
+            jmethodID* new_jmeths, jmethodID* to_dealloc_id_p,
+            jmethodID** to_dealloc_jmeths_p) {
+  assert(new_id != NULL, "sanity check");
+  assert(to_dealloc_id_p != NULL, "sanity check");
+  assert(to_dealloc_jmeths_p != NULL, "sanity check");
+  assert(Threads::number_of_threads() == 0 ||
+         SafepointSynchronize::is_at_safepoint() ||
+         JmethodIdCreation_lock->owned_by_self(), "sanity check");
+
+  // reacquire the cache - we are locked, single threaded or at a safepoint
   jmethodID* jmeths = ik_h->methods_jmethod_ids_acquire();
-  jmethodID  id                = NULL;
-  jmethodID  to_dealloc_id     = NULL;
-  jmethodID* to_dealloc_jmeths = NULL;
-  size_t     length;
+  jmethodID  id     = NULL;
+  size_t     length = 0;
 
-  if (jmeths == NULL || (length = (size_t)jmeths[0]) <= idnum) {
+  if (jmeths == NULL ||                         // no cache yet
+      (length = (size_t)jmeths[0]) <= idnum) {  // cache is too short
     if (jmeths != NULL) {
-      // We have grown the array: copy the existing entries, and delete the old array
+      // copy any existing entries from the old cache
       for (size_t index = 0; index < length; index++) {
         new_jmeths[index+1] = jmeths[index+1];
       }
-      to_dealloc_jmeths = jmeths; // using the new jmeths, deallocate the old one
+      *to_dealloc_jmeths_p = jmeths;  // save old cache for later delete
     }
     ik_h->release_set_methods_jmethod_ids(jmeths = new_jmeths);
   } else {
+    // fetch jmethodID (if any) from the existing cache
     id = jmeths[idnum+1];
-    to_dealloc_jmeths = new_jmeths; // using the old jmeths, deallocate the new one
+    *to_dealloc_jmeths_p = new_jmeths;  // save new cache for later delete
   }
   if (id == NULL) {
+    // No matching jmethodID in the existing cache or we have a new
+    // cache or we just grew the cache. This cache write is done here
+    // by the first thread to win the foot race because a jmethodID
+    // needs to be unique once it is generally available.
     id = new_id;
-    jmeths[idnum+1] = id;  // install the new method ID
+
+    // The jmethodID cache can be read while unlocked so we have to
+    // make sure the new jmethodID is complete before installing it
+    // in the cache.
+    OrderAccess::release_store_ptr(&jmeths[idnum+1], id);
   } else {
-    to_dealloc_id = new_id; // the new id wasn't used, mark it for deallocation
-  }
-
-  // Free up unneeded or no longer needed resources
-  FreeHeap(to_dealloc_jmeths);
-  if (to_dealloc_id != NULL) {
-    JNIHandles::destroy_jmethod_id(to_dealloc_id);
+    *to_dealloc_id_p = new_id; // save new id for later delete
   }
   return id;
 }
 
 
+// Common code to get the jmethodID cache length and the jmethodID
+// value at index idnum if there is one.
+//
+void instanceKlass::get_jmethod_id_length_value(jmethodID* cache,
+       size_t idnum, size_t *length_p, jmethodID* id_p) {
+  assert(cache != NULL, "sanity check");
+  assert(length_p != NULL, "sanity check");
+  assert(id_p != NULL, "sanity check");
+
+  // cache size is stored in element[0], other elements offset by one
+  *length_p = (size_t)cache[0];
+  if (*length_p <= idnum) {  // cache is too short
+    *id_p = NULL;
+  } else {
+    *id_p = cache[idnum+1];  // fetch jmethodID (if any)
+  }
+}
+
+
 // Lookup a jmethodID, NULL if not found.  Do no blocking, no allocations, no handles
 jmethodID instanceKlass::jmethod_id_or_null(methodOop method) {
   size_t idnum = (size_t)method->method_idnum();
   jmethodID* jmeths = methods_jmethod_ids_acquire();
   size_t length;                                // length assigned as debugging crumb
   jmethodID id = NULL;
-  if (jmeths != NULL &&                         // If there is a jmethodID array,
+  if (jmeths != NULL &&                         // If there is a cache
       (length = (size_t)jmeths[0]) > idnum) {   // and if it is long enough,
     id = jmeths[idnum+1];                       // Look up the id (may be NULL)
   }
@@ -1074,18 +1167,35 @@
 // Cache an itable index
 void instanceKlass::set_cached_itable_index(size_t idnum, int index) {
   int* indices = methods_cached_itable_indices_acquire();
-  if (indices == NULL ||                         // If there is no index array,
-      ((size_t)indices[0]) <= idnum) {           // or if it is too short
-    // Lock before we allocate the array so we don't leak
+  int* to_dealloc_indices = NULL;
+
+  // We use a double-check locking idiom here because this cache is
+  // performance sensitive. In the normal system, this cache only
+  // transitions from NULL to non-NULL which is safe because we use
+  // release_set_methods_cached_itable_indices() to advertise the
+  // new cache. A partially constructed cache should never be seen
+  // by a racing thread. Cache reads and writes proceed without a
+  // lock, but creation of the cache itself requires no leaks so a
+  // lock is generally acquired in that case.
+  //
+  // If the RedefineClasses() API has been used, then this cache can
+  // grow and we'll have transitions from non-NULL to bigger non-NULL.
+  // Cache creation requires no leaks and we require safety between all
+  // cache accesses and freeing of the old cache so a lock is generally
+  // acquired when the RedefineClasses() API has been used.
+
+  if (indices == NULL || idnum_can_increment()) {
+    // we need a cache or the cache can grow
     MutexLocker ml(JNICachedItableIndex_lock);
-    // Retry lookup after we got the lock
+    // reacquire the cache to see if another thread already did the work
     indices = methods_cached_itable_indices_acquire();
     size_t length = 0;
-    // array length stored in first element, other elements offset by one
+    // cache size is stored in element[0], other elements offset by one
     if (indices == NULL || (length = (size_t)indices[0]) <= idnum) {
       size_t size = MAX2(idnum+1, (size_t)idnum_allocated_count());
       int* new_indices = NEW_C_HEAP_ARRAY(int, size+1);
-      // Copy the existing entries, if any
+      new_indices[0] = (int)size;
+      // copy any existing entries
       size_t i;
       for (i = 0; i < length; i++) {
         new_indices[i+1] = indices[i+1];
@@ -1095,15 +1205,32 @@
         new_indices[i+1] = -1;
       }
       if (indices != NULL) {
-        FreeHeap(indices);  // delete any old indices
+        // We have an old cache to delete so save it for after we
+        // drop the lock.
+        to_dealloc_indices = indices;
       }
       release_set_methods_cached_itable_indices(indices = new_indices);
     }
+
+    if (idnum_can_increment()) {
+      // this cache can grow so we have to write to it safely
+      indices[idnum+1] = index;
+    }
   } else {
     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   }
-  // This is a cache, if there is a race to set it, it doesn't matter
-  indices[idnum+1] = index;
+
+  if (!idnum_can_increment()) {
+    // The cache cannot grow and this JNI itable index value does not
+    // have to be unique like a jmethodID. If there is a race to set it,
+    // it doesn't matter.
+    indices[idnum+1] = index;
+  }
+
+  if (to_dealloc_indices != NULL) {
+    // we allocated a new cache so free the old one
+    FreeHeap(to_dealloc_indices);
+  }
 }
 
 
@@ -2299,6 +2426,11 @@
 
 // Add an information node that contains weak references to the
 // interesting parts of the previous version of the_class.
+// This is also where we clean out any unused weak references.
+// Note that while we delete nodes from the _previous_versions
+// array, we never delete the array itself until the klass is
+// unloaded. The has_been_redefined() query depends on that fact.
+//
 void instanceKlass::add_previous_version(instanceKlassHandle ikh,
        BitMap* emcp_methods, int emcp_method_count) {
   assert(Thread::current()->is_VM_thread(),
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -217,6 +217,7 @@
   bool            _is_marked_dependent;  // used for marking during flushing and deoptimization
   bool            _rewritten;            // methods rewritten.
   bool            _has_nonstatic_fields; // for sizing with UseCompressedOops
+  bool            _should_verify_class;  // allow caching of preverification
   u2              _minor_version;        // minor version number of class file
   u2              _major_version;        // major version number of class file
   ClassState      _init_state;           // state of class
@@ -362,6 +363,10 @@
   int  get_init_state()                    { return _init_state; } // Useful for debugging
   bool is_rewritten() const                { return _rewritten; }
 
+  // defineClass specified verification
+  bool should_verify_class() const         { return _should_verify_class; }
+  void set_should_verify_class(bool value) { _should_verify_class = value; }
+
   // marking
   bool is_marked_dependent() const         { return _is_marked_dependent; }
   void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
@@ -460,6 +465,10 @@
   // RedefineClasses() support for previous versions:
   void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods,
          int emcp_method_count);
+  // If the _previous_versions array is non-NULL, then this klass
+  // has been redefined at least once even if we aren't currently
+  // tracking a previous version.
+  bool has_been_redefined() const { return _previous_versions != NULL; }
   bool has_previous_version() const;
   void init_previous_versions() {
     _previous_versions = NULL;
@@ -501,9 +510,14 @@
   void set_bootstrap_method(oop mh)                   { oop_store(&_bootstrap_method, mh); }
 
   // jmethodID support
-  static jmethodID get_jmethod_id(instanceKlassHandle ik_h, size_t idnum,
-                                  jmethodID new_id, jmethodID* new_jmeths);
-  static jmethodID jmethod_id_for_impl(instanceKlassHandle ik_h, methodHandle method_h);
+  static jmethodID get_jmethod_id(instanceKlassHandle ik_h,
+                     methodHandle method_h);
+  static jmethodID get_jmethod_id_fetch_or_update(instanceKlassHandle ik_h,
+                     size_t idnum, jmethodID new_id, jmethodID* new_jmeths,
+                     jmethodID* to_dealloc_id_p,
+                     jmethodID** to_dealloc_jmeths_p);
+  static void get_jmethod_id_length_value(jmethodID* cache, size_t idnum,
+                size_t *length_p, jmethodID* id_p);
   jmethodID jmethod_id_or_null(methodOop method);
 
   // cached itable index support
@@ -749,6 +763,11 @@
   void set_init_thread(Thread *thread)  { _init_thread = thread; }
 
   u2 idnum_allocated_count() const      { return _idnum_allocated_count; }
+  // The RedefineClasses() API can cause new method idnums to be needed
+  // which will cause the caches to grow. Safety requires different
+  // cache management logic if the caches can grow instead of just
+  // going from NULL to non-NULL.
+  bool idnum_can_increment() const      { return has_been_redefined(); }
   jmethodID* methods_jmethod_ids_acquire() const
          { return (jmethodID*)OrderAccess::load_ptr_acquire(&_methods_jmethod_ids); }
   void release_set_methods_jmethod_ids(jmethodID* jmeths)
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 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
--- a/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/instanceRefKlass.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/oops/methodDataOop.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodDataOop.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/oops/methodOop.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/methodOop.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -555,7 +555,7 @@
 
   // Get this method's jmethodID -- allocate if it doesn't exist
   jmethodID jmethod_id()                            { methodHandle this_h(this);
-                                                      return instanceKlass::jmethod_id_for_impl(method_holder(), this_h); }
+                                                      return instanceKlass::get_jmethod_id(method_holder(), this_h); }
 
   // Lookup the jmethodID for this method.  Return NULL if not found.
   // NOTE that this function can be called from a signal handler
--- a/hotspot/src/share/vm/oops/objArrayOop.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/oops/objArrayOop.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/opto/compile.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/compile.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/opto/escape.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/escape.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -439,6 +439,11 @@
   Node *base = addp->in(AddPNode::Base)->uncast();
   if (base->is_top()) { // The AddP case #3 and #6.
     base = addp->in(AddPNode::Address)->uncast();
+    while (base->is_AddP()) {
+      // Case #6 (unsafe access) may have several chained AddP nodes.
+      assert(base->in(AddPNode::Base)->is_top(), "expected unsafe access address only");
+      base = base->in(AddPNode::Address)->uncast();
+    }
     assert(base->Opcode() == Op_ConP || base->Opcode() == Op_ThreadLocal ||
            base->Opcode() == Op_CastX2P || base->is_DecodeN() ||
            (base->is_Mem() && base->bottom_type() == TypeRawPtr::NOTNULL) ||
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -622,11 +622,13 @@
 
 //---------------------------PreserveReexecuteState----------------------------
 PreserveReexecuteState::PreserveReexecuteState(GraphKit* kit) {
+  assert(!kit->stopped(), "must call stopped() before");
   _kit    =    kit;
   _sp     =    kit->sp();
   _reexecute = kit->jvms()->_reexecute;
 }
 PreserveReexecuteState::~PreserveReexecuteState() {
+  if (_kit->stopped()) return;
   _kit->jvms()->_reexecute = _reexecute;
   _kit->set_sp(_sp);
 }
@@ -1086,7 +1088,7 @@
     alen = _gvn.transform( new (C, 3) LoadRangeNode(0, immutable_memory(), r_adr, TypeInt::POS));
   } else {
     alen = alloc->Ideal_length();
-    Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_aryptr(), &_gvn);
+    Node* ccast = alloc->make_ideal_length(_gvn.type(array)->is_oopptr(), &_gvn);
     if (ccast != alen) {
       alen = _gvn.transform(ccast);
     }
@@ -1123,8 +1125,8 @@
     case T_OBJECT : {
       const Type *t = _gvn.type( value );
 
-      const TypeInstPtr* tp = t->isa_instptr();
-      if (tp != NULL && !tp->klass()->is_loaded()
+      const TypeOopPtr* tp = t->isa_oopptr();
+      if (tp != NULL && tp->klass() != NULL && !tp->klass()->is_loaded()
           // Only for do_null_check, not any of its siblings:
           && !assert_null && null_control == NULL) {
         // Usually, any field access or invocation on an unloaded oop type
--- a/hotspot/src/share/vm/opto/idealKit.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/idealKit.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/opto/idealKit.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/idealKit.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005-2006 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
--- a/hotspot/src/share/vm/opto/ifnode.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/ifnode.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/opto/library_call.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -3903,19 +3903,10 @@
     guarantee(alloc != NULL && alloc->maybe_set_complete(&_gvn), "");
   }
 
-  // Cast to Object for arraycopy.
-  // We can't use the original CheckCastPP since it should be moved
-  // after the arraycopy to prevent stores flowing above it.
-  Node* new_obj = new(C, 2) CheckCastPPNode(alloc_obj->in(0), raw_obj,
-                                            TypeInstPtr::NOTNULL);
-  new_obj = _gvn.transform(new_obj);
-  // Substitute in the locally valid dest_oop.
-  replace_in_map(alloc_obj, new_obj);
-
   // Copy the fastest available way.
   // TODO: generate fields copies for small objects instead.
   Node* src  = obj;
-  Node* dest = new_obj;
+  Node* dest = alloc_obj;
   Node* size = _gvn.transform(obj_size);
 
   // Exclude the header but include array length to copy by 8 bytes words.
@@ -3961,7 +3952,7 @@
     int raw_adr_idx = Compile::AliasIdxRaw;
     post_barrier(control(),
                  memory(raw_adr_type),
-                 new_obj,
+                 alloc_obj,
                  no_particular_field,
                  raw_adr_idx,
                  no_particular_value,
@@ -3969,16 +3960,8 @@
                  false);
   }
 
-  // Move the original CheckCastPP after arraycopy.
-  _gvn.hash_delete(alloc_obj);
-  alloc_obj->set_req(0, control());
-  // Replace raw memory edge with new CheckCastPP to have a live oop
-  // at safepoints instead of raw value.
-  assert(new_obj->is_CheckCastPP() && new_obj->in(1) == alloc_obj->in(1), "sanity");
-  alloc_obj->set_req(1, new_obj);    // cast to the original type
-  _gvn.hash_find_insert(alloc_obj);  // put back into GVN table
-  // Restore in the locally valid dest_oop.
-  replace_in_map(new_obj, alloc_obj);
+  // Do not let reads from the cloned object float above the arraycopy.
+  insert_mem_bar(Op_MemBarCPUOrder);
 }
 
 //------------------------inline_native_clone----------------------------
@@ -4448,15 +4431,6 @@
     assert(init->is_complete(), "we just did this");
     assert(dest->is_CheckCastPP(), "sanity");
     assert(dest->in(0)->in(0) == init, "dest pinned");
-
-    // Cast to Object for arraycopy.
-    // We can't use the original CheckCastPP since it should be moved
-    // after the arraycopy to prevent stores flowing above it.
-    Node* new_obj = new(C, 2) CheckCastPPNode(dest->in(0), dest->in(1),
-                                              TypeInstPtr::NOTNULL);
-    dest = _gvn.transform(new_obj);
-    // Substitute in the locally valid dest_oop.
-    replace_in_map(original_dest, dest);
     adr_type = TypeRawPtr::BOTTOM;  // all initializations are into raw memory
     // From this point on, every exit path is responsible for
     // initializing any non-copied parts of the object to zero.
@@ -4786,18 +4760,6 @@
   set_i_o(     _gvn.transform(result_i_o)    );
   set_memory(  _gvn.transform(result_memory), adr_type );
 
-  if (dest != original_dest) {
-    // Pin the "finished" array node after the arraycopy/zeroing operations.
-    _gvn.hash_delete(original_dest);
-    original_dest->set_req(0, control());
-    // Replace raw memory edge with new CheckCastPP to have a live oop
-    // at safepoints instead of raw value.
-    assert(dest->is_CheckCastPP() && dest->in(1) == original_dest->in(1), "sanity");
-    original_dest->set_req(1, dest);       // cast to the original type
-    _gvn.hash_find_insert(original_dest);  // put back into GVN table
-    // Restore in the locally valid dest_oop.
-    replace_in_map(dest, original_dest);
-  }
   // The memory edges above are precise in order to model effects around
   // array copies accurately to allow value numbering of field loads around
   // arraycopy.  Such field loads, both before and after, are common in Java
@@ -4808,7 +4770,9 @@
   // The next memory barrier is added to avoid it. If the arraycopy can be
   // optimized away (which it can, sometimes) then we can manually remove
   // the membar also.
-  if (InsertMemBarAfterArraycopy)
+  //
+  // Do not let reads from the cloned object float above the arraycopy.
+  if (InsertMemBarAfterArraycopy || alloc != NULL)
     insert_mem_bar(Op_MemBarCPUOrder);
 }
 
--- a/hotspot/src/share/vm/opto/phaseX.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/opto/phaseX.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/phaseX.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/opto/postaloc.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/postaloc.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1998-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1998-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
--- a/hotspot/src/share/vm/opto/superword.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/superword.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -990,8 +990,8 @@
 // (5) We know there is no dependence cycle, so there in no other case;
 // (6) Finally, all memory ops in another single pack should be moved in the same direction.
 //
-// To schedule a load pack: the memory edge of every loads in the pack must be
-// the same as the memory edge of the last executed load in the pack
+// To schedule a load pack, we use the memory state of either the first or the last load in
+// the pack, based on the dependence constraint.
 void SuperWord::co_locate_pack(Node_List* pk) {
   if (pk->at(0)->is_Store()) {
     MemNode* first     = executed_first(pk)->as_Mem();
@@ -1076,15 +1076,32 @@
       current = my_mem->as_Mem();
     } // end while
   } else if (pk->at(0)->is_Load()) { //load
-    // all use the memory state that the last executed load uses
-    LoadNode* last_load  = executed_last(pk)->as_Load();
-    Node* last_mem       = last_load->in(MemNode::Memory);
-    _igvn.hash_delete(last_mem);
-    // Give each load same memory state as last
+    // all loads in the pack should have the same memory state. By default,
+    // we use the memory state of the last load. However, if any load could
+    // not be moved down due to the dependence constraint, we use the memory
+    // state of the first load.
+    Node* last_mem  = executed_last(pk)->in(MemNode::Memory);
+    Node* first_mem = executed_first(pk)->in(MemNode::Memory);
+    bool schedule_last = true;
+    for (uint i = 0; i < pk->size(); i++) {
+      Node* ld = pk->at(i);
+      for (Node* current = last_mem; current != ld->in(MemNode::Memory);
+           current=current->in(MemNode::Memory)) {
+        assert(current != first_mem, "corrupted memory graph");
+        if(current->is_Mem() && !independent(current, ld)){
+          schedule_last = false; // a later store depends on this load
+          break;
+        }
+      }
+    }
+
+    Node* mem_input = schedule_last ? last_mem : first_mem;
+    _igvn.hash_delete(mem_input);
+    // Give each load the same memory state
     for (uint i = 0; i < pk->size(); i++) {
       LoadNode* ld = pk->at(i)->as_Load();
       _igvn.hash_delete(ld);
-      ld->set_req(MemNode::Memory, last_mem);
+      ld->set_req(MemNode::Memory, mem_input);
       _igvn._worklist.push(ld);
     }
   }
--- a/hotspot/src/share/vm/opto/type.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -2236,12 +2236,12 @@
 
 //------------------------------make-------------------------------------------
 const TypeOopPtr *TypeOopPtr::make(PTR ptr,
-                                   int offset) {
+                                   int offset, int instance_id) {
   assert(ptr != Constant, "no constant generic pointers");
   ciKlass*  k = ciKlassKlass::make();
   bool      xk = false;
   ciObject* o = NULL;
-  return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, InstanceBot))->hashcons();
+  return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id))->hashcons();
 }
 
 
@@ -2330,7 +2330,8 @@
 
   case OopPtr: {                 // Meeting to other OopPtrs
     const TypeOopPtr *tp = t->is_oopptr();
-    return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()) );
+    int instance_id = meet_instance_id(tp->instance_id());
+    return make( meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id );
   }
 
   case InstPtr:                  // For these, flip the call around to cut down
@@ -2801,7 +2802,7 @@
 
   case OopPtr: {                // Meeting to OopPtrs
     // Found a OopPtr type vs self-InstPtr type
-    const TypePtr *tp = t->is_oopptr();
+    const TypeOopPtr *tp = t->is_oopptr();
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
     switch (tp->ptr()) {
@@ -2812,8 +2813,10 @@
                   (ptr == Constant ? const_oop() : NULL), offset, instance_id);
     }
     case NotNull:
-    case BotPTR:
-      return TypeOopPtr::make(ptr, offset);
+    case BotPTR: {
+      int instance_id = meet_instance_id(tp->instance_id());
+      return TypeOopPtr::make(ptr, offset, instance_id);
+    }
     default: typerr(t);
     }
   }
@@ -3259,7 +3262,7 @@
 
   case OopPtr: {                // Meeting to OopPtrs
     // Found a OopPtr type vs self-AryPtr type
-    const TypePtr *tp = t->is_oopptr();
+    const TypeOopPtr *tp = t->is_oopptr();
     int offset = meet_offset(tp->offset());
     PTR ptr = meet_ptr(tp->ptr());
     switch (tp->ptr()) {
@@ -3270,8 +3273,10 @@
                   _ary, _klass, _klass_is_exact, offset, instance_id);
     }
     case BotPTR:
-    case NotNull:
-      return TypeOopPtr::make(ptr, offset);
+    case NotNull: {
+      int instance_id = meet_instance_id(tp->instance_id());
+      return TypeOopPtr::make(ptr, offset, instance_id);
+    }
     default: ShouldNotReachHere();
     }
   }
--- a/hotspot/src/share/vm/opto/type.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -714,7 +714,7 @@
   static const TypeOopPtr* make_from_constant(ciObject* o);
 
   // Make a generic (unclassed) pointer to an oop.
-  static const TypeOopPtr* make(PTR ptr, int offset);
+  static const TypeOopPtr* make(PTR ptr, int offset, int instance_id = InstanceBot);
 
   ciObject* const_oop()    const { return _const_oop; }
   virtual ciKlass* klass() const { return _klass;     }
--- a/hotspot/src/share/vm/prims/jni.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -299,7 +299,8 @@
     }
   }
   klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader,
-                                                     Handle(), &st, CHECK_NULL);
+                                                     Handle(), &st, true,
+                                                     CHECK_NULL);
 
   if (TraceClassResolution && k != NULL) {
     trace_class_resolution(k);
--- a/hotspot/src/share/vm/prims/jvm.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -762,7 +762,11 @@
 }
 
 // common code for JVM_DefineClass() and JVM_DefineClassWithSource()
-static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) {
+// and JVM_DefineClassWithSourceCond()
+static jclass jvm_define_class_common(JNIEnv *env, const char *name,
+                                      jobject loader, const jbyte *buf,
+                                      jsize len, jobject pd, const char *source,
+                                      jboolean verify, TRAPS) {
   if (source == NULL)  source = "__JVM_DefineClass__";
 
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
@@ -803,6 +807,7 @@
   Handle protection_domain (THREAD, JNIHandles::resolve(pd));
   klassOop k = SystemDictionary::resolve_from_stream(class_name, class_loader,
                                                      protection_domain, &st,
+                                                     verify != 0,
                                                      CHECK_NULL);
 
   if (TraceClassResolution && k != NULL) {
@@ -816,16 +821,24 @@
 JVM_ENTRY(jclass, JVM_DefineClass(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd))
   JVMWrapper2("JVM_DefineClass %s", name);
 
-  return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, THREAD);
+  return jvm_define_class_common(env, name, loader, buf, len, pd, NULL, true, THREAD);
 JVM_END
 
 
 JVM_ENTRY(jclass, JVM_DefineClassWithSource(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source))
   JVMWrapper2("JVM_DefineClassWithSource %s", name);
 
-  return jvm_define_class_common(env, name, loader, buf, len, pd, source, THREAD);
-JVM_END
-
+  return jvm_define_class_common(env, name, loader, buf, len, pd, source, true, THREAD);
+JVM_END
+
+JVM_ENTRY(jclass, JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name,
+                                                jobject loader, const jbyte *buf,
+                                                jsize len, jobject pd,
+                                                const char *source, jboolean verify))
+  JVMWrapper2("JVM_DefineClassWithSourceCond %s", name);
+
+  return jvm_define_class_common(env, name, loader, buf, len, pd, source, verify, THREAD);
+JVM_END
 
 JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name))
   JVMWrapper("JVM_FindLoadedClass");
--- a/hotspot/src/share/vm/prims/jvm.h	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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
@@ -417,6 +417,17 @@
                           const jbyte *buf, jsize len, jobject pd,
                           const char *source);
 
+/* Define a class with a source with conditional verification (added HSX 14)
+ * -Xverify:all will verify anyway, -Xverify:none will not verify,
+ * -Xverify:remote (default) will obey this conditional
+ * i.e. true = should_verify_class
+ */
+JNIEXPORT jclass JNICALL
+JVM_DefineClassWithSourceCond(JNIEnv *env, const char *name,
+                              jobject loader, const jbyte *buf,
+                              jsize len, jobject pd, const char *source,
+                              jboolean verify);
+
 /* Define a class with a source (MLVM) */
 JNIEXPORT jclass JNICALL
 JVM_DefineClassWithCP(JNIEnv *env, const char *name, jobject loader,
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -933,7 +933,7 @@
       // description.
       RedefineVerifyMark rvm(&the_class, &scratch_class, state);
       Verifier::verify(
-        scratch_class, Verifier::ThrowException, THREAD);
+        scratch_class, Verifier::ThrowException, true, THREAD);
     }
 
     if (HAS_PENDING_EXCEPTION) {
@@ -959,7 +959,7 @@
       // verify what we have done during constant pool merging
       {
         RedefineVerifyMark rvm(&the_class, &scratch_class, state);
-        Verifier::verify(scratch_class, Verifier::ThrowException, THREAD);
+        Verifier::verify(scratch_class, Verifier::ThrowException, true, THREAD);
       }
 
       if (HAS_PENDING_EXCEPTION) {
--- a/hotspot/src/share/vm/runtime/atomic.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/atomic.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2008 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
--- a/hotspot/src/share/vm/runtime/perfData.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/perfData.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2001-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2001-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
--- a/hotspot/src/share/vm/runtime/safepoint.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -769,9 +769,23 @@
   // to grab the Threads_lock which we own here, so a thread cannot be
   // resumed during safepoint synchronization.
 
-  // We check with locking because another thread that has not yet
-  // synchronized may be trying to suspend this one.
-  bool is_suspended = _thread->is_any_suspended_with_lock();
+  // We check to see if this thread is suspended without locking to
+  // avoid deadlocking with a third thread that is waiting for this
+  // thread to be suspended. The third thread can notice the safepoint
+  // that we're trying to start at the beginning of its SR_lock->wait()
+  // call. If that happens, then the third thread will block on the
+  // safepoint while still holding the underlying SR_lock. We won't be
+  // able to get the SR_lock and we'll deadlock.
+  //
+  // We don't need to grab the SR_lock here for two reasons:
+  // 1) The suspend flags are both volatile and are set with an
+  //    Atomic::cmpxchg() call so we should see the suspended
+  //    state right away.
+  // 2) We're being called from the safepoint polling loop; if
+  //    we don't see the suspended state on this iteration, then
+  //    we'll come around again.
+  //
+  bool is_suspended = _thread->is_ext_suspended();
   if (is_suspended) {
     roll_forward(_at_safepoint);
     return;
--- a/hotspot/src/share/vm/runtime/sweeper.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2005 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
--- a/hotspot/src/share/vm/runtime/thread.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1942,7 +1942,7 @@
 
   MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
 
-  assert(!this->is_any_suspended(),
+  assert(!this->is_ext_suspended(),
     "a thread trying to self-suspend should not already be suspended");
 
   if (this->is_suspend_equivalent()) {
--- a/hotspot/src/share/vm/runtime/thread.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -967,11 +967,6 @@
     return (_suspend_flags & _ext_suspended) != 0;
   }
 
-  // legacy method that checked for either external suspension or vm suspension
-  bool is_any_suspended() const {
-    return is_ext_suspended();
-  }
-
   bool is_external_suspend_with_lock() const {
     MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
     return is_external_suspend();
@@ -997,10 +992,6 @@
     return ret;
   }
 
-  bool is_any_suspended_with_lock() const {
-    MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
-    return is_any_suspended();
-  }
   // utility methods to see if we are doing some kind of suspension
   bool is_being_ext_suspended() const            {
     MutexLockerEx ml(SR_lock(), Mutex::_no_safepoint_check_flag);
--- a/hotspot/src/share/vm/runtime/vframeArray.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/vframeArray.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2007 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
--- a/hotspot/src/share/vm/runtime/vframe_hp.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/runtime/vframe_hp.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 1997-2006 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
--- a/hotspot/src/share/vm/services/threadService.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/services/threadService.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
--- a/hotspot/src/share/vm/services/threadService.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/src/share/vm/services/threadService.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
--- a/hotspot/test/compiler/6636138/Test1.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/test/compiler/6636138/Test1.java	Wed Jul 05 17:01:09 2017 +0200
@@ -45,7 +45,7 @@
         for (int i = 0; i < src.length; i++) {
             if (src[i] != ref[i]) {
                 System.out.println("Error: src and ref don't match at " + i);
-                System.exit(-1);
+                System.exit(97);
             }
         }
     }
--- a/hotspot/test/compiler/6636138/Test2.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/test/compiler/6636138/Test2.java	Wed Jul 05 17:01:09 2017 +0200
@@ -51,7 +51,7 @@
             int value = (i-1 + src.length)%src.length; // correct value after shifting
                 if (src[i] != value) {
                     System.out.println("Error: src["+i+"] should be "+ value + " instead of " + src[i]);
-                    System.exit(-1);
+                    System.exit(97);
                 }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6855215/Test6855215.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,55 @@
+/*
+ * 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 6855215
+ * @summary Calculation error (NaN) after about 1500 calculations
+ *
+ * @run main/othervm -Xbatch -XX:UseSSE=0 Test6855215
+ */
+
+public class Test6855215 {
+    private double m;
+    private double b;
+
+    public static double log10(double x) {
+        return Math.log(x) / Math.log(10);
+    }
+
+    void calcMapping(double xmin, double xmax, double ymin, double ymax) {
+        m = (ymax - ymin) / (log10(xmax) - log10(xmin));
+        b = (log10(xmin) * ymax - log10(xmax) * ymin);
+    }
+
+    public static void main(String[] args) {
+        Test6855215 c = new Test6855215();
+        for (int i = 0; i < 30000; i++) {
+            c.calcMapping(91, 121, 177, 34);
+            if (c.m != c.m) {
+                throw new InternalError();
+            }
+        }
+    }
+}
--- a/hotspot/test/compiler/6865031/Test.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/hotspot/test/compiler/6865031/Test.java	Wed Jul 05 17:01:09 2017 +0200
@@ -26,7 +26,7 @@
  * @test
  * @bug 6865031
  * @summary Application gives bad result (throws bad exception) with compressed oops
- * @run main/othervm -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:HeapBaseMinAddress=32g -XX:-LoopUnswitching -XX:CompileCommand=inline,AbstractMemoryEfficientList.equals Test hello goodbye
  */
 
 import java.lang.ref.ReferenceQueue;
--- a/jaxp/.hgignore	Mon Sep 28 19:38:55 2009 -0700
+++ b/jaxp/.hgignore	Wed Jul 05 17:01:09 2017 +0200
@@ -1,4 +1,5 @@
 ^build/
 ^dist/
+^drop/
 ^webrev/
 ^nbproject/private/
--- a/jaxp/.hgtags	Mon Sep 28 19:38:55 2009 -0700
+++ b/jaxp/.hgtags	Wed Jul 05 17:01:09 2017 +0200
@@ -46,3 +46,4 @@
 a4ab0d6ded63bed0fd1e5be55d38090e0ee5efb7 jdk7-b69
 c83f0106b78a85c7e614d27a328675460b2081cf jdk7-b70
 ff94d8ce0daded647bb326630e643d010357afce jdk7-b71
+37c805b6156fd492c12301688b54a6bcca39e729 jdk7-b72
--- a/jaxp/README	Mon Sep 28 19:38:55 2009 -0700
+++ b/jaxp/README	Wed Jul 05 17:01:09 2017 +0200
@@ -1,14 +1,25 @@
 README:
-  This file should be located at the top of the jaxp Mercurial repository.
+  
+  This file should be located at the top of the Mercurial repository.
 
   See http://openjdk.java.net/ for more information about the OpenJDK.
 
   See ../README-builds.html for complete details on build machine requirements.
 
 Simple Build Instructions:
-
+  This repository can be loaded as a NetBeans project, built with ant, or
+  built with GNU make, e.g.
+    ant
+       -OR-
     cd make && gnumake
      
-  The files that will be imported into the jdk build will be in the "dist"
-  directory.
+  The built files that will be imported into the jdk build will be in the 
+  "dist" directory.
+  Help information is available by running "ant -projecthelp" or "make help".
 
+Drop Repository:
+  This repository builds sources from a created "drop" source directory.
+  These files will normally be copied from a shared directory area or
+  downloaded from a public website.
+  See the ant build script (build.xml) for more details.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/build-defs.xml	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,125 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+
+<project name="jaxp_defs" default="all" basedir=".">
+
+    <!-- Specific build properties. -->
+    <property file="jaxp.properties"/>
+
+    <!-- Where generated xml files will stay. -->
+    <property name="xml.gen.dir" value="${build.dir}/xml_generated"/>
+    <property name="xml.template" value="build-drop-template.xml"/>
+
+    <!--  ############### -->
+    <!--  Begin Macrodefs -->
+
+    <!-- Copies template file, replaces @DROP@ pattern, and imports it. -->
+    <macrodef name="drop-import">
+        <attribute name="name"/>
+        <sequential>
+            <property name="xml.gen.@{name}" value="${xml.gen.dir}/build-drop-@{name}.xml"/>
+            <mkdir dir="${xml.gen.dir}"/>
+            <copy file="${xml.template}" tofile="${xml.gen.@{name}}"/>
+            <replace file="${xml.gen.@{name}}" token="@DROP@" value="@{name}"/>
+            <import file="${xml.gen.@{name}}"/>
+        </sequential>
+    </macrodef>
+
+    <!--  End of Macrodefs -->
+    <!--  ############### -->
+
+    <!-- Create xml file and import it for these drops. -->
+    <drop-import name="jaxp_src"/>
+    <!-- <drop-import name="jaxp_tests"/> -->
+
+
+    <!-- Special build area preparation. -->
+    <target name="-drop-build-prep" depends="init, -init-src-dirs">
+        <mkdir dir="${build.classes.dir}"/>
+        <copy todir="${build.classes.dir}">
+            <fileset dir="${primary.src.dir}"
+                     includes="**/*.properties"/>
+        </copy>
+        <replaceregexp match="#(.*)$" replace="#" flags="gm">
+            <fileset dir="${build.classes.dir}" includes="**/*.properties"/>
+        </replaceregexp>
+    </target>
+
+    <!-- Try to get drop sources, set property use.orig.src.dir if no drops. -->
+    <target name="-set-props"
+	    depends="init,
+                     jaxp_src-update">
+        <condition property="use.orig.src.dir">
+            <and>
+                <available file="${orig.src.dir}" type="dir"/>
+                <not>
+                    <and>
+                        <available file="${jaxp_src.src.dir}" type="dir"/>
+                    </and>
+                </not>
+            </and>
+        </condition>
+    </target>
+
+    <!-- Set up source to use orig.src.dir, if use.orig.src.dir defined. -->
+    <target name="-use-orig" depends="-set-props" if="use.orig.src.dir">
+        <property name="primary.src.dir" value="${orig.src.dir}"/>
+        <path id="src.dir.id">
+            <pathelement path="${primary.src.dir}"/>
+        </path>
+    </target>
+
+    <!-- Set up source to use drop.dir, if use.orig.src.dir not defined. -->
+    <target name="-use-drop" depends="-set-props" unless="use.orig.src.dir">
+        <property name="primary.src.dir" value="${jaxp_src.src.dir}"/>
+        <path id="src.dir.id">
+            <pathelement path="${primary.src.dir}"/>
+        </path>
+    </target>
+
+    <!-- Source directory selection. -->
+    <target name="-init-src-dirs"
+	    depends="init, -use-orig, -use-drop">
+        <echo message="Using primary.src.dir=${primary.src.dir}"/>
+        <pathconvert property="src.list.id" refid="src.dir.id"/>
+        <echo message="Using src.dir.id=${src.list.id}"/>
+    </target>
+
+    <!-- Create orig src.zip. -->
+    <target name="-orig-src-zip" depends="init, -set-props" if="use.orig.src.dir">
+        <zip file="${dist.src.zip}" basedir="${primary.src.dir}"/>
+    </target>
+
+    <!-- Create drop src.zip. -->
+    <target name="-drop-src-zip" depends="init, -set-props" unless="use.orig.src.dir">
+        <zip file="${dist.src.zip}" basedir="${primary.src.dir}"/>
+    </target>
+
+    <!-- Create src.zip. -->
+    <target name="-dist-src-zip" depends="init, -orig-src-zip, -drop-src-zip">
+    </target>
+    
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/build-drop-template.xml	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,131 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+
+<project name="@DROP@-drop" default="all" basedir=".">
+
+    <!-- Locations of master drop bundles. -->
+    <property name="@DROP@.master.bundle.copy"
+              value="${@DROP@.master.bundle.dir}/${@DROP@.bundle.name}"/>
+    <property name="@DROP@.master.bundle.url"
+              value="${@DROP@.master.bundle.url.base}/${@DROP@.bundle.name}"/>
+
+    <!-- Location where the copied bundle lands. -->
+    <property name="@DROP@.bundle.copy"
+              value="${drop.dir}/bundles/${@DROP@.bundle.name}"/>
+
+    <!-- Root of exploded area. -->
+    <property name="@DROP@.root.dir" value="${drop.dir}/@DROP@"/>
+    <property name="@DROP@.src.dir" value="${@DROP@.root.dir}/src"/>
+
+    <!-- To see if the drop areas are ready. (ignoring bundles) -->
+    <target name="-@DROP@-ready">
+        <condition property="@DROP@.ready">
+            <and>
+                <available file="${@DROP@.root.dir}" type="dir"/>
+                <available file="${@DROP@.root.dir}/PATCHED" type="file"/>
+            </and>
+        </condition>
+    </target>
+
+    <!-- Copy over bundles from some shared master area. -->
+    <condition property="@DROP@.master.bundle.copy.exists">
+        <available file="${@DROP@.master.bundle.copy}" type="file"/>
+    </condition>
+    <target name="-@DROP@-copy-bundle"
+	    depends="init, -@DROP@-ready"
+            if="@DROP@.master.bundle.copy.exists"
+            unless="@DROP@.ready">
+        <echo message="Copying from ${@DROP@.master.bundle.copy}"/>
+        <dirname property="@DROP@.bundle.dirname" file="${@DROP@.bundle.copy}"/>
+        <mkdir dir="${@DROP@.bundle.dirname}"/>
+        <delete file="${@DROP@.bundle.copy}.temp"/>
+        <delete file="${@DROP@.bundle.copy}"/>
+        <copy file="${@DROP@.master.bundle.copy}" tofile="${@DROP@.bundle.copy}.temp"/>
+        <move file="${@DROP@.bundle.copy}.temp" tofile="${@DROP@.bundle.copy}"/>
+        <property name="@DROP@.master.bundle.found" value="true"/>
+    </target>
+
+    <!-- Determine if the master url download should be used. -->
+    <target name="-@DROP@-url-should-be-used" unless="@DROP@.url.should.be.used">
+        <condition property="@DROP@.url.should.be.used">
+            <and>
+                <http url="${@DROP@.master.bundle.url.base}"/>
+                <not>
+                    <isset property="@DROP@.master.bundle.copy.exists"/>
+                </not>
+            </and>
+        </condition>
+    </target>
+
+    <!-- Download bundles from a url. -->
+    <target name="-@DROP@-url-bundle"
+	    depends="init, -@DROP@-ready, -@DROP@-url-should-be-used"
+            if="@DROP@.url.should.be.used"
+            unless="@DROP@.ready">
+        <echo message="Downloading from ${@DROP@.master.bundle.url}"/>
+        <dirname property="@DROP@.bundle.dirname" file="${@DROP@.bundle.copy}"/>
+        <mkdir dir="${@DROP@.bundle.dirname}"/>
+        <delete file="${@DROP@.bundle.copy}.temp"/>
+        <delete file="${@DROP@.bundle.copy}"/>
+        <get src="${@DROP@.master.bundle.url}" dest="${@DROP@.bundle.copy}.temp"/>
+        <move file="${@DROP@.bundle.copy}.temp" tofile="${@DROP@.bundle.copy}"/>
+        <property name="@DROP@.master.bundle.found" value="true"/>
+    </target>
+    
+    <!-- Fill in the drop zones, but just when needed. -->
+    <target name="@DROP@-update"
+            depends="init, 
+		     -@DROP@-copy-bundle,
+		     -@DROP@-url-bundle,
+                     -@DROP@-ready"
+            if="@DROP@.master.bundle.found"
+            unless="@DROP@.ready">
+        <delete dir="${@DROP@.root.dir}"/>
+        <delete dir="${@DROP@.root.dir}-temp"/>
+        <mkdir dir="${@DROP@.root.dir}-temp"/>
+        <unzip src="${@DROP@.bundle.copy}" dest="${@DROP@.root.dir}-temp"/>
+        <move file="${@DROP@.root.dir}-temp" tofile="${@DROP@.root.dir}"/>
+        <touch>
+            <fileset dir="${@DROP@.root.dir}"/>
+        </touch>
+        <condition property="patch.utility" value="gpatch" else="patch">
+            <os name="SunOS"/>
+        </condition>
+        <apply executable="${patch.utility}"
+		   dir="${@DROP@.root.dir}"
+	           parallel="false"
+	           failonerror="true"
+	           verbose="true">
+            <arg value="-l"/>
+            <arg value="-p0"/>
+            <arg value="-i"/>
+            <filelist dir="${patches.dir}/@DROP@" files="${@DROP@.patch.list}"/>
+        </apply>
+        <echo file="${@DROP@.root.dir}/PATCHED"
+	      message="Patches have been applied."/>
+    </target>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/build.properties	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,103 @@
+#
+# Copyright 2007-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.
+#
+
+# Base locations where bundles are located
+slashjava=/java
+devtools=${slashjava}/devtools
+
+# This is the JDK used to build and run the bootstrap version of javac.
+# The bootstrap javac is used to compile both boostrap versions of the
+# other tools, and product versions of all the tools.
+# Override this path as needed, either on the command line or in 
+# one of the standard user build.properties files (see build.xml)
+javac.jar=${bootstrap.dir}/lib/javac.jar
+
+# options for the <javac> tasks used to compile the tools
+javac.source = 7
+javac.target = 7
+javac.debug = true
+javac.no.jdk.warnings = -XDignore.symbol.file=true
+# set the following to -version to verify the versions of javac being used
+javac.version.opt = 
+# in time, there should be no exceptions to -Xlint:all
+#javac.lint.opts = -Xlint:all,-unchecked,-deprecation,-fallthrough,-cast,-serial
+javac.lint.opts=
+
+# JVM memory size
+javac.memoryInitialSize = 256m
+javac.memoryMaximumSize = 512m
+
+#------------------------------------------------------------
+
+# Root of output directories
+output.dir=.
+
+# Built files
+build.dir=${output.dir}/build
+build.classes.dir=${build.dir}/classes
+
+# Distributed results
+dist.dir=${output.dir}/dist
+dist.lib.dir=${dist.dir}/lib
+dist.classes.jar=${dist.lib.dir}/classes.jar
+dist.src.zip=${dist.lib.dir}/src.zip
+
+# Where all drop sources live
+drop.dir=./drop
+
+# Where patches to drop bundle sources live
+patches.dir=patches
+
+# Original source area
+orig.dir=src
+orig.src.dir=${orig.dir}/share/classes
+
+# Sanity information
+sanity.info= Sanity Settings:${line.separator}\
+  ant.home=${ant.home}${line.separator}\
+  ant.version=${ant.version}${line.separator}\
+  ant.java.version=${ant.java.version}${line.separator}\
+  java.home=${java.home}${line.separator}\
+  java.version=${java.version}${line.separator}\
+  os.name=${os.name}${line.separator}\
+  os.arch=${os.arch}${line.separator}\
+  os.version=${os.version}${line.separator}\
+  bootstrap.dir=${bootstrap.dir}${line.separator}\
+  javac.jar=${javac.jar}${line.separator}\
+  javac.memoryInitialSize=${javac.memoryInitialSize}${line.separator}\
+  javac.memoryMaximumSize=${javac.memoryMaximumSize}${line.separator}\
+  javac.source=${javac.source}${line.separator}\
+  javac.debug=${javac.debug}${line.separator}\
+  javac.target=${javac.target}${line.separator}\
+  javac.version.opt=${javac.version.opt}${line.separator}\
+  javac.lint.opts=${javac.lint.opts}${line.separator}\
+  javac.no.jdk.warnings=${javac.no.jdk.warnings}${line.separator}\
+  output.dir=${output.dir}${line.separator}\
+  build.dir=${build.dir}${line.separator}\
+  dist.dir=${dist.dir}${line.separator}\
+  drop.dir=${drop.dir}${line.separator}\
+${line.separator}
+
+#------------------------------------------------------------
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/build.xml	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,163 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+
+<project name="jaxp" default="all" basedir=".">
+   
+    <!-- For 'ant -p' or 'ant -projecthelp' -->
+    
+    <description>
+    Ant build script for the ${ant.project.name} part of the jdk.
+
+    Input Properties: (see build.properties for the ant defaults)
+      bootstrap.dir        - dir with lib/javac.jar, added to javac bootclasspath
+      javac.debug          - true or false for debug classfiles
+      javac.target         - classfile version target
+      javac.source         - source version
+    </description>
+
+    <!-- Mac is special, need to downgrade these before build.properties. -->
+    <condition property="javac.source" value="1.5">
+        <os family="mac"/>
+    </condition>
+    <condition property="javac.target" value="1.5">
+        <os family="mac"/>
+    </condition>
+
+    <!-- Project build properties. -->
+    <property file="build.properties"/>
+
+    <!-- Get shared targets. -->
+    <import file="build-defs.xml"/>
+
+    <!-- Initialization of directories needed for build. -->
+    <target name="init">
+        <mkdir dir="${build.dir}"/>
+        <mkdir dir="${build.classes.dir}"/>
+        <mkdir dir="${dist.dir}"/>
+        <mkdir dir="${dist.lib.dir}"/>
+    </target>
+    
+    <!-- Sanity checks and settings -->
+    <target name="sanity"
+	    depends="-javac-jar-exists"
+            description="Display settings of configuration values">
+        <echo message="${sanity.info}"/>
+    </target>
+
+     <!-- Check for bootstrap javac.jar file, warn if missing. -->
+    <condition property="javac.jar.exists">
+        <available file="${javac.jar}" type="file"/>
+    </condition>
+    <target name="-javac-jar-exists"
+            unless="javac.jar.exists">
+        <echo message="WARNING: Cannot find ${javac.jar}"/>
+    </target>
+
+    <!-- Creation of distribution files to jdk build process. -->
+    <target name="dist"
+	    depends="init, -init-src-dirs, build, -dist-classes-jar, -dist-src-zip"
+            description="Create all built distribution files.">
+    </target>
+    <target name="-dist-classes-jar-uptodate"
+	    depends="init, -init-src-dirs">
+        <condition property="dist.classes.jar.uptodate">
+            <and>
+                <available file="${dist.classes.jar}" type="file"/>
+                <uptodate targetfile="${dist.classes.jar}">
+                    <srcfiles dir="${build.classes.dir}" includes="**"/>
+                </uptodate>
+            </and>
+        </condition>
+    </target>
+    <target name="-dist-classes-jar"
+	    depends="init, -init-src-dirs, -dist-classes-jar-uptodate"
+            unless="dist.classes.jar.uptodate">
+        <delete file="${dist.classes.jar}"/>
+        <jar file="${dist.classes.jar}" basedir="${build.classes.dir}"/>
+    </target>
+
+    <target name="-build-prep"
+	    depends="init, -init-src-dirs, -drop-build-prep">
+    </target>
+
+    <!-- Build (compilation) of sources to class files. -->
+    <target name="build"
+	    depends="init, -init-src-dirs, -build-prep">
+        <javac fork="true"
+             destdir="${build.classes.dir}"
+             memoryInitialSize="${javac.memoryInitialSize}"
+             memoryMaximumSize="${javac.memoryMaximumSize}"
+             source="${javac.source}"
+	     debug="${javac.debug}"
+             target="${javac.target}">
+            <compilerarg value="-J-Xbootclasspath/p:${javac.jar}"/>
+            <compilerarg line="${javac.version.opt} ${javac.lint.opts} ${javac.no.jdk.warnings}"/>
+            <src refid="src.dir.id"/>
+        </javac>
+    </target>
+
+    <!-- Test. (FIXME: Need to know how to run tests.) -->
+    <target name="test"
+	    depends="init, -init-src-dirs, dist">
+        <echo message="FIXME: How do you run the tests"/>
+    </target>
+    
+    <!-- Populate source area if needed. -->
+    <target name="source"
+            depends="init, -init-src-dirs"
+            description="Populate all source file directories">
+    </target>
+
+    <!-- Clean up compiled files. -->
+    <target name="clean"
+            description="Delete all generated files">
+        <delete dir="${build.dir}"/>
+        <delete dir="${dist.dir}"/>
+    </target>
+
+    <!-- Clean up compiled files and all imported source files. -->
+    <target name="clobber"
+	    depends="clean"
+            description="Delete all generated files, including imported sources">
+        <delete dir="${drop.dir}"/>
+    </target>
+
+    <target name="-banner">
+        <echo message="+---------------------------------------+"/>
+        <echo message="+ Starting ant project ${ant.project.name} +"/>
+        <echo message="+---------------------------------------+"/>
+    </target>
+   
+    <!-- Do everything but test. -->
+    <target name="all"
+	    depends="-banner, sanity, dist"
+            description="Build everything.">
+        <echo message="+---------------------------------------+"/>
+        <echo message="+ Finishing ant project ${ant.project.name}"/>
+        <echo message="+---------------------------------------+"/>
+    </target>
+
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/jaxp.properties	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,36 @@
+#
+# Copyright 2007-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.
+#
+
+drops.master.copy.base=${devtools}/share/jdk7-drops
+drops.master.url.base=http://kenai.com/projects/jdk7-drops/downloads/download
+
+jaxp_src.bundle.name=jdk7-jaxp-2009_09_28.zip
+jaxp_src.master.bundle.dir=${drops.master.copy.base}
+#jaxp_src.bundle.url.base=https://jaxp.dev.java.net/files/documents/913/142147
+jaxp_src.master.bundle.url.base=${drops.master.url.base}
+
+jaxp_tests.bundle.name=jdk7-jaxp-tests-2009_08_28.zip
+jaxp_tests.master.bundle.dir=${drops.master.copy.base}
+jaxp_tests.master.bundle.url.base=${drops.master.url.base}
--- a/jaxp/make/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/jaxp/make/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -23,7 +23,7 @@
 # have any questions.
 #
 
-# Makefile for jaxp: wrapper around Ant build.xml file
+# Makefile wrapper around Ant build.xml file
 
 #
 # On Solaris, the 'make' utility from Sun will not work with these makefiles.
@@ -41,38 +41,12 @@
   ANT_OPTIONS += -verbose
 endif
 
-ifdef JDK_VERSION
-  ANT_OPTIONS += -Djdk.version=$(JDK_VERSION)
-endif 
-
-ifdef FULL_VERSION
-  ANT_OPTIONS += -Dfull.version='$(FULL_VERSION)' # will contain spaces
-endif 
-
-ifdef MILESTONE
-  ANT_OPTIONS += -Dmilestone=$(MILESTONE)
-endif
-
-ifdef BUILD_NUMBER
-  ANT_OPTIONS += -Dbuild.number=$(BUILD_NUMBER)
-else
-  ifdef JDK_BUILD_NUMBER
-    ANT_OPTIONS += -Dbuild.number=$(JDK_BUILD_NUMBER)
-  endif
-endif
-
-ifeq ($(VARIANT), DBG)
-  ANT_OPTIONS += -Djavac.debug=true
-else
-  ifeq ($(VARIANT), OPT)
+ifeq ($(VARIANT), OPT)
+  ifneq ($(DEBUG_CLASSFILES), true)
     ANT_OPTIONS += -Djavac.debug=false
   endif
 endif
 
-ifeq ($(DEBUG_CLASSFILES), true)
-  ANT_OPTIONS += -Djavac.debug=true
-endif
-
 # Note: jdk/make/common/Defs.gmk uses LANGUAGE_VERSION (-source NN)
 # and the somewhat misnamed CLASS_VERSION (-target NN)
 ifdef TARGET_CLASS_VERSION
@@ -81,7 +55,7 @@
   ifdef JAVAC_TARGET_ARG
     ANT_OPTIONS += -Djavac.target=$(JAVAC_TARGET_ARG)
   endif
-endif 
+endif
 
 ifdef SOURCE_LANGUAGE_VERSION
   ANT_OPTIONS += -Djavac.source=$(SOURCE_LANGUAGE_VERSION)
@@ -91,24 +65,53 @@
   endif
 endif 
 
-ifdef ALT_BOOTDIR
-  ANT_JAVA_HOME = JAVA_HOME=$(ALT_BOOTDIR)
+# Figure out the platform we are using
+_SYSTEM_UNAME := $(shell uname)
+_PLATFORM_KIND = unix
+ifeq ($(_SYSTEM_UNAME), Windows_NT)
+  _PLATFORM_KIND = windows
+endif
+ifneq (,$(findstring CYGWIN,$(_SYSTEM_UNAME)))
+  _PLATFORM_KIND = windows
 endif
 
+# Where is /java in case we need it
+ifdef ALT_SLASH_JAVA
+  _SLASHJAVA = $(ALT_SLASH_JAVA)
+else
+  ifeq ($(_PLATFORM_KIND), windows)
+    _SLASHJAVA=J:/
+  else
+    _SLASHJAVA=/java
+  endif
+endif
+
+# Where is /java/devtools in case we need it
+ifdef ALT_JDK_DEVTOOLS_DIR
+  _DEVTOOLS = $(ALT_JDK_DEVTOOLS_DIR)
+else
+  _DEVTOOLS = $(_SLASHJAVA)/devtools
+endif
+
+# Add in path to devtools
+ANT_OPTIONS += -Ddevtools=$(_DEVTOOLS)
+
 ifdef ALT_OUTPUTDIR
   OUTPUTDIR = $(ALT_OUTPUTDIR)
-  ANT_OPTIONS += -Dbuild.dir=$(ALT_OUTPUTDIR)/build
-  ANT_OPTIONS += -Ddist.dir=$(ALT_OUTPUTDIR)/dist
+  ANT_OPTIONS += -Doutput.dir=$(ALT_OUTPUTDIR)
 else
   OUTPUTDIR = ..
 endif
 
 ifdef ALT_LANGTOOLS_DIST
+  ifdef ALT_BOOTDIR
+    ANT_JAVA_HOME = JAVA_HOME=$(ALT_BOOTDIR)
+  endif
   ANT_OPTIONS += -Dbootstrap.dir=$(ALT_LANGTOOLS_DIST)/bootstrap
-endif
-
-ifdef FINDBUGS_HOME
-  ANT_OPTIONS += -Dfindbugs.home=$(FINDBUGS_HOME)
+else
+  ifdef ALT_JDK_IMPORT_PATH
+    ANT_JAVA_HOME = JAVA_HOME=$(ALT_JDK_IMPORT_PATH)
+  endif
 endif
 
 ifdef ANT_HOME
@@ -124,26 +127,67 @@
 endif
 
 # Default target and expected 'do everything' target
-all: build
-
-# Standard make clobber target
-clobber: clean
+default: all
 
 # All ant targets of interest
-ANT_TARGETS = build clean sanity # for now
+ANT_TARGETS = all source build dist clobber clean sanity
 
 # Create a make target for each
 $(ANT_TARGETS):
-	$(ANT_JAVA_HOME) $(ANT) -version
-	$(ANT_JAVA_HOME) $(ANT) $(ANT_OPTIONS) $@
+	cd .. && $(ANT_JAVA_HOME) $(ANT) -version
+	cd .. && $(ANT_JAVA_HOME) $(ANT) $(ANT_OPTIONS) $@
+
+# Help target
+define helpenvline
+@echo "    $1";echo "        $2"
+endef
+help:
+	@echo "----------------------------------------------------------"
+	@echo " "
+	@echo "Help information for this Makefile:"
+	@echo " "
+	@echo "  Targets (see ant project information for descriptions):"
+	@echo "    $(ANT_TARGETS)"
+	@echo " "
+	@echo "  Environment or command line variables (all optional):"
+	$(call helpenvline, ALT_BOOTDIR,\
+	       "JAVA_HOME to use when running ant")
+	$(call helpenvline, ALT_LANGTOOLS_DIST,\
+	       "path to langtools repository dist directory")
+	$(call helpenvline, ALT_OUTPUTDIR,\
+	       "path to root of output")
+	$(call helpenvline, DEBUG_CLASSFILES,\
+	       "if set makes sure ant property javac.debug is true")
+	$(call helpenvline, JAVAC_SOURCE_ARG,\
+	       "if SOURCE_LANGUAGE_VERSION not set uses this to set ant property javac.source")
+	$(call helpenvline, JAVAC_TARGET_ARG,\
+	       "if TARGET_CLASS_VERSION not set uses this to set ant property javac.target")
+	$(call helpenvline, SOURCE_LANGUAGE_VERSION,\
+	       "if set uses this to set ant property javac.source")
+	$(call helpenvline, QUIET,\
+	       "if set will pass -quiet to ant")
+	$(call helpenvline, TARGET_CLASS_VERSION,\
+	       "JAVA_HOME to use when running ant")
+	$(call helpenvline, VARIANT,\
+	       "if set to OPT means optimized build will set javac.debug to false")
+	$(call helpenvline, VERBOSE,\
+	       "if set will pass -verbose to ant")
+	@echo " "
+	@echo "----------------------------------------------------------"
+	@echo " "
+	@echo "Ant project file help information:"
+	@echo " "
+	@$(ANT_JAVA_HOME) cd .. && $(ANT) $(ANT_OPTIONS) -p
+	@echo " "
+	@echo "----------------------------------------------------------"
 
 # Targets for Sun's internal JPRT build system
 JPRT_ARCHIVE_BUNDLE=$(OUTPUTDIR)/jprt.zip
 jprt_build_product jprt_build_debug jprt_build_fastdebug: all
 	$(RM) $(JPRT_ARCHIVE_BUNDLE)
 	( cd $(OUTPUTDIR)/dist && \
-	  zip -q -r $(JPRT_ARCHIVE_BUNDLE) . )
+	   zip -q -r $(JPRT_ARCHIVE_BUNDLE) . )
 
 # Declare these phony (not filenames)
-.PHONY: $(ANT_TARGETS) all clobber \
+.PHONY: $(ANT_TARGETS) \
 	jprt_build_product jprt_build_debug jprt_build_fastdebug
--- a/jaxp/make/build.properties	Mon Sep 28 19:38:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-#
-# Copyright 2007-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.
-#
-
-# This is the JDK used to build and run the bootstrap version of javac.
-# The bootstrap javac is used to compile both boostrap versions of the
-# other tools, and product versions of all the tools.
-# Override this path as needed, either on the command line or in 
-# one of the standard user build.properties files (see build.xml)
-
-# options for the <javac> tasks used to compile the tools
-javac.source = 7
-javac.target = 7
-javac.debug = true
-javac.no.jdk.warnings = -XDignore.symbol.file=true
-# set the following to -version to verify the versions of javac being used
-javac.version.opt = 
-# in time, there should be no exceptions to -Xlint:all
-javac.lint.opts = -Xlint:all,-unchecked,-deprecation,-fallthrough,-cast,-serial -Werror
-
-# JVM memory size
-javac.memoryInitialSize = 128m
-javac.memoryMaximumSize = 256m
-
-#------------------------------------------------------------
--- a/jaxp/make/build.xml	Mon Sep 28 19:38:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-<?xml version="1.0"?>
-<!--
- Copyright 2007-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.
--->
-
-<!--
- This is the main build file for the complete jaxp workspace.
- -->
-
-<project name="jaxp" default="all" basedir=".">
-
-    <!-- Convenient shorthands for standard locations within the workspace. -->
-    <property file="build.properties"/>
-    <property name="topdir" value=".."/>
-    <property name="build.dir" location="${topdir}/build"/>
-    <property name="build.classes.dir" location="${build.dir}/classes"/>
-    <property name="build.gensrc.dir" location="${build.dir}/gensrc"/>
-    <property name="build.toolclasses.dir" location="${build.dir}/toolclasses"/>
-    <property name="dist.dir" location="${topdir}/dist"/>
-    <property name="dist.lib.dir" location="${dist.dir}/lib"/>
-    <property name="make.dir" location="${topdir}/make"/>
-    <property name="make.tools.dir" location="${make.dir}/tools"/>
-    <property name="src.dir" location="${topdir}/src"/>
-    <property name="src.classes.dir" location="${src.dir}/share/classes"/>
-    <property environment="env"/>
-
-    <target name="build" depends="banner, build-classes, build-tools">
-	<mkdir dir="${dist.lib.dir}"/>
-	<jar file="${dist.lib.dir}/classes.jar" basedir="${build.classes.dir}"/>
-	<zip file="${dist.lib.dir}/src.zip" basedir="${src.classes.dir}"/>
-    </target>
-
-    <!-- Debug information -->
-    <target name="sanity"
-        description="display settings of configuration values">
-	<echo level="info">ant.home = ${ant.home}</echo>
-	<echo level="info">java.home = ${env.JAVA_HOME}</echo>
-	<echo level="info">bootstrap.dir = ${bootstrap.dir}</echo>
-    </target>
-
-    <target name="build-tools" depends="-defs-pstrip">
-        <mkdir dir="${build.dir}"/>
-        <mkdir dir="${build.classes.dir}"/>
-	    <pstrip srcdir="${src.classes.dir}"
-                    destdir="${build.classes.dir}"
-		    includes="**/*.properties"/>
-    </target>
-
-    <target name="-defs-pstrip">
-      <mkdir dir="${build.toolclasses.dir}"/>
-      <javac srcdir="${make.tools.dir}/StripProperties"
-		destdir="${build.toolclasses.dir}/"
-		classpath="${ant.home}/lib/ant.jar"/>
-      <taskdef name="pstrip"
-		 classname="StripPropertiesTask"
-		 classpath="${build.toolclasses.dir}/"/>
-    </target>
-
-    <target name="build-classes" depends="sanity">
-      <mkdir dir="${build.dir}"/>
-      <mkdir dir="${build.classes.dir}"/>
-      <javac fork="true"
-             srcdir="${src.classes.dir}"
-             destdir="${build.classes.dir}"
-             memoryInitialSize="${javac.memoryInitialSize}"
-             memoryMaximumSize="${javac.memoryMaximumSize}"
-	     source="${javac.source}"
-	     debug="${javac.debug}"
-             target="${javac.target}">
-         <compilerarg value="-J-Xbootclasspath/p:${bootstrap.dir}/lib/javac.jar"/>
-         <compilerarg line="${javac.version.opt}"/>
-      </javac>
-    </target>
-
-    <target name="clean" description="Delete all generated files">
-	<delete dir="${build.dir}"/>
-	<delete dir="${dist.dir}"/>
-    </target>
-
-    <target name="banner">
-      <echo>+---------------------------------------+</echo>
-      <echo>+    Building JAXP Component            +</echo>
-      <echo>+---------------------------------------+</echo>
-    </target>
-
-</project>
--- a/jaxp/make/jprt.properties	Mon Sep 28 19:38:55 2009 -0700
+++ b/jaxp/make/jprt.properties	Wed Jul 05 17:01:09 2017 +0200
@@ -34,8 +34,8 @@
 solaris_x64_5.10,\
 linux_i586_2.6,\
 linux_x64_2.6,\
-windows_i586,\
-windows_x64
+windows_i586_5.0,\
+windows_x64_5.2
 
 # The different build flavors we want
 jprt.build.flavors=product,fastdebug
@@ -49,7 +49,6 @@
 # Standard list of jprt test targets for this workspace
 jprt.test.targets=
 
-# Directories needed to build
-jprt.bundle.src.dirs=make src
+# Directories needing to exclude from source bundles
 jprt.bundle.exclude.src.dirs=build dist
 
--- a/jaxp/make/tools/StripProperties/StripProperties.java	Mon Sep 28 19:38:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,329 +0,0 @@
-/*
- * Copyright 2001 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.
- */
-
-import java.io.BufferedInputStream;
-import java.io.BufferedWriter;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Properties;
-
-/**
- * Reads a properties file from standard input and writes an equivalent
- * properties file without comments to standard output.
- */
-public class StripProperties {
-
-    public static void main(String[] args) {
-        StripProperties sp = new StripProperties();
-        boolean ok = sp.run(args);
-        if ( !ok ) {
-            System.exit(1);
-        }
-    }
-
-    static interface Log {
-        void info(String msg);
-        void verbose(String msg);
-        void error(String msg, Exception e);
-    }
-
-    private String propfiles[];
-    private String outfiles[] ;
-    private int stripCount = 0;
-    private boolean quiet = false;
-    private Log log;
-
-    public void setLog(Log log) {
-        this.log = log;
-    }
-
-    private boolean parseOptions(String args[]) {
-        boolean ok = true;
-        if ( stripCount > 0 ) {
-            String new_propfiles[] = new String[stripCount + args.length];
-            String new_outfiles[]  = new String[stripCount + args.length];
-            System.arraycopy(propfiles, 0, new_propfiles, 0, stripCount);
-            System.arraycopy(outfiles, 0, new_outfiles, 0, stripCount);
-            propfiles = new_propfiles;
-            outfiles  = new_outfiles;
-        } else {
-            propfiles = new String[args.length];
-            outfiles  = new String[args.length];
-        }
-
-        for ( int i = 0; i < args.length ; i++ ) {
-            if ( "-strip".equals(args[i]) && i+2 < args.length ) {
-                propfiles[stripCount] = args[++i];
-                outfiles[stripCount]    = args[++i];
-                stripCount++;
-            } else if ( "-optionsfile".equals(args[i]) && i+1 < args.length ) {
-                String filename = args[++i];
-                FileInputStream finput = null;
-                byte contents[] = null;
-                try {
-                    finput = new FileInputStream(filename);
-                    int byteCount = finput.available();
-                    if ( byteCount <= 0 ) {
-                        log.error("The -optionsfile file is empty", null);
-                        ok = false;
-                    } else {
-                        contents = new byte[byteCount];
-                        int bytesRead = finput.read(contents);
-                        if ( byteCount != bytesRead ) {
-                            log.error("Cannot read all of -optionsfile file", null);
-                            ok = false;
-                        }
-                    }
-                } catch ( IOException e ) {
-                    log.error("cannot open " + filename, e);
-                    ok = false;
-                }
-                if ( finput != null ) {
-                    try {
-                        finput.close();
-                    } catch ( IOException e ) {
-                        ok = false;
-                        log.error("cannot close " + filename, e);
-                    }
-                }
-                if ( ok = true && contents != null ) {
-                    String tokens[] = (new String(contents)).split("\\s+");
-                    if ( tokens.length > 0 ) {
-                        ok = parseOptions(tokens);
-                    }
-                }
-                if ( !ok ) {
-                    break;
-                }
-        } else if ( "-quiet".equals(args[i]) ) {
-                quiet = true;
-        } else {
-                log.error("argument error", null);
-                ok = false;
-        }
-        }
-        return ok;
-    }
-
-    private boolean stripFiles(String propertiesPath, String outputPath) {
-        boolean ok = true;
-        Properties prop = new Properties();
-        InputStream in = null;
-        try {
-                in = new BufferedInputStream(new FileInputStream(propertiesPath));
-                prop.load(in);
-        } catch ( FileNotFoundException e ) {
-                log.error("Cannot access file " + propertiesPath, e);
-                ok = false;
-        } catch ( IOException e ) {
-                log.error("IO exception processing file " + propertiesPath, e);
-                ok = false;
-        }
-        if ( in != null ) {
-                try {
-                    in.close();
-                } catch ( IOException e ) {
-                    log.error("IO exception closing file " + propertiesPath, e);
-                    ok = false;
-                }
-        }
-
-        OutputStream out = null;
-        try {
-                out = new FileOutputStream(outputPath);
-                storeProperties(prop, out);
-                out.flush();
-        } catch ( IOException e ) {
-                log.error("IO exception processing file " + outputPath, e);
-                e.printStackTrace();
-                ok = false;
-        }
-        if ( out != null ) {
-           try {
-                    out.close();
-           } catch ( IOException e ) {
-                    log.error("IO exception closing file " + outputPath, e);
-                    ok = false;
-           }
-        }
-        return ok;
-    }
-
-    /**
-     * Strip the properties filenames supplied, replacing their contents.
-     * @param args Names of properties files to process and replace contents
-     */
-    public boolean run(String args[]) {
-        if (log == null) {
-            log = new Log() {
-                public void error(String msg, Exception e) {
-                    System.err.println("ERROR: StripProperties: " + msg);
-                    if ( e != null ) {
-                        System.err.println("EXCEPTION: " + e.toString());
-                        e.printStackTrace();
-                    }
-                }
-                public void info(String msg) {
-                    System.out.println(msg);
-                }
-                public void verbose(String msg) {
-                    if (!quiet)
-                        System.out.println(msg);
-                }
-            };
-        }
-
-        boolean ok = true;
-        ok = parseOptions(args);
-        if ( ok && stripCount == 0 ) {
-                log.error("options parsed but no files to compile", null);
-                ok = false;
-        }
-        /* Need at least one file. */
-        if ( !ok ) {
-            //usage(log);
-        } else {
-            /* Process files */
-            for ( int i = 0; i < stripCount && ok ; i++ ) {
-                    ok = stripFiles(propfiles[i], outfiles[i]);
-            }
-        }
-        return ok;
-    }
-
-    // --- code below here is adapted from java.util.Properties ---
-
-    private static final String specialSaveChars = "=: \t\r\n\f#!";
-
-    /*
-     * Converts unicodes to encoded &#92;uxxxx
-     * and writes out any of the characters in specialSaveChars
-     * with a preceding slash
-     */
-    private static String saveConvert(String theString, boolean escapeSpace) {
-        int len = theString.length();
-        StringBuffer outBuffer = new StringBuffer(len*2);
-
-        for(int x=0; x<len; x++) {
-            char aChar = theString.charAt(x);
-            switch(aChar) {
-                case ' ':
-                    if (x == 0 || escapeSpace) {
-                        outBuffer.append('\\');
-                    }
-                    outBuffer.append(' ');
-                    break;
-                case '\\':
-                    outBuffer.append('\\');
-                    outBuffer.append('\\');
-                    break;
-                case '\t':
-                    outBuffer.append('\\');
-                    outBuffer.append('t');
-                    break;
-                case '\n':
-                    outBuffer.append('\\');
-                    outBuffer.append('n');
-                    break;
-                case '\r':
-                    outBuffer.append('\\');
-                    outBuffer.append('r');
-                    break;
-                case '\f':
-                    outBuffer.append('\\');
-                    outBuffer.append('f');
-                    break;
-                default:
-                    if ((aChar < 0x0020) || (aChar == 0x007e) || (aChar > 0x00ff)) {
-                        outBuffer.append('\\');
-                        outBuffer.append('u');
-                        outBuffer.append(toHex((aChar >> 12) & 0xF));
-                        outBuffer.append(toHex((aChar >>  8) & 0xF));
-                        outBuffer.append(toHex((aChar >>  4) & 0xF));
-                        outBuffer.append(toHex( aChar        & 0xF));
-                    } else {
-                        if (specialSaveChars.indexOf(aChar) != -1) {
-                            outBuffer.append('\\');
-                        }
-                        outBuffer.append(aChar);
-                    }
-            }
-        }
-        return outBuffer.toString();
-    }
-
-    /**
-     * Writes the content of <code>properties</code> to <code>out</code>.
-     * The format is that of Properties.store with the following modifications:
-     * <ul>
-     * <li>No header or date is written
-     * <li>Latin-1 characters are written as single bytes, not escape sequences
-     * <li>Line breaks are indicated by a single \n independent of platform
-     * <ul>
-     */
-    private static void storeProperties(Properties properties, OutputStream out)
-    throws IOException {
-        BufferedWriter awriter;
-        awriter = new BufferedWriter(new OutputStreamWriter(out, "8859_1"));
-        for (Enumeration e = properties.keys(); e.hasMoreElements();) {
-            String key = (String)e.nextElement();
-            String val = (String)properties.get(key);
-            key = saveConvert(key, true);
-
-            /* No need to escape embedded and trailing spaces for value, hence
-             * pass false to flag.
-             */
-            val = saveConvert(val, false);
-            writeln(awriter, key + "=" + val);
-        }
-        awriter.flush();
-    }
-
-    private static void writeln(BufferedWriter bw, String s) throws IOException {
-        bw.write(s);
-        bw.write("\n");
-    }
-
-    /**
-     * Convert a nibble to a hex character
-     * @param   nibble  the nibble to convert.
-     */
-    private static char toHex(int nibble) {
-        return hexDigit[(nibble & 0xF)];
-    }
-
-    /** A table of hex digits */
-    private static final char[] hexDigit = {
-        '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
-    };
-}
--- a/jaxp/make/tools/StripProperties/StripPropertiesTask.java	Mon Sep 28 19:38:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright 2007 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.
- */
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.DirectoryScanner;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.taskdefs.MatchingTask;
-
-public class StripPropertiesTask extends MatchingTask {
-    public void setSrcDir(File srcDir) {
-        this.srcDir = srcDir;
-    }
-
-    public void setDestDir(File destDir) {
-        this.destDir = destDir;
-    }
-
-    public void execute() {
-        StripProperties.Log log = new StripProperties.Log() {
-            public void error(String msg, Exception e) {
-                log(msg, Project.MSG_ERR);
-            }
-            public void info(String msg) {
-                log(msg, Project.MSG_INFO);
-            }
-            public void verbose(String msg) {
-                log(msg, Project.MSG_VERBOSE);
-            }
-        };
-        List<String> mainOpts = new ArrayList<String>();
-        int count = 0;
-        DirectoryScanner s = getDirectoryScanner(srcDir);
-        for (String path: s.getIncludedFiles()) {
-            if (path.endsWith(".properties")) {
-                File srcFile = new File(srcDir, path);
-                File destFile = new File(destDir, path);
-                // Arguably, the comparison in the next line should be ">", not ">="
-                // but that assumes the resolution of the last modified time is fine
-                // grained enough; in practice, it is better to use ">=".
-                if (destFile.exists() && destFile.lastModified() >= srcFile.lastModified())
-                    continue;
-                destFile.getParentFile().mkdirs();
-                mainOpts.add("-strip");
-                mainOpts.add(srcFile.getPath());
-                mainOpts.add(destFile.getPath());
-                count++;
-            }
-        }
-        if (mainOpts.size() > 0) {
-            log("Generating " + count + " resource files to " + destDir, Project.MSG_INFO);
-            StripProperties sp = new StripProperties();
-            sp.setLog(log);
-            boolean ok = sp.run((String[])mainOpts.toArray(new String[mainOpts.size()]));
-            if (!ok)
-                throw new BuildException("StripProperties failed.");
-        }
-    }
-
-    private File srcDir;
-    private File destDir;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/nbproject/findbugs.settings	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,72 @@
+#FindBugs User Preferences
+#Tue Jun 30 18:33:11 PDT 2009
+detectorAbnormalFinallyBlockReturn=AbnormalFinallyBlockReturn|false
+detectorAbstractClassEmptyMethods=AbstractClassEmptyMethods|false
+detectorAbstractOverriddenMethod=AbstractOverriddenMethod|false
+detectorArrayBasedCollections=ArrayBasedCollections|false
+detectorArrayWrappedCallByReference=ArrayWrappedCallByReference|false
+detectorBloatedAssignmentScope=BloatedAssignmentScope|false
+detectorBloatedSynchronizedBlock=BloatedSynchronizedBlock|false
+detectorClassEnvy=ClassEnvy|false
+detectorCollectStatistics=CollectStatistics|false
+detectorConfusingAutoboxedOverloading=ConfusingAutoboxedOverloading|false
+detectorConstantListIndex=ConstantListIndex|false
+detectorCopiedOverriddenMethod=CopiedOverriddenMethod|false
+detectorCustomBuiltXML=CustomBuiltXML|false
+detectorCyclomaticComplexity=CyclomaticComplexity|false
+detectorDateComparison=DateComparison|false
+detectorDeclaredRuntimeException=DeclaredRuntimeException|false
+detectorDeletingWhileIterating=DeletingWhileIterating|false
+detectorDubiousListCollection=DubiousListCollection|false
+detectorFieldCouldBeLocal=FieldCouldBeLocal|false
+detectorFinalParameters=FinalParameters|false
+detectorFloatingPointLoops=FloatingPointLoops|false
+detectorInefficientStringBuffering=InefficientStringBuffering|false
+detectorInheritanceTypeChecking=InheritanceTypeChecking|false
+detectorJDBCVendorReliance=JDBCVendorReliance|false
+detectorListIndexedIterating=ListIndexedIterating|false
+detectorLiteralStringComparison=LiteralStringComparison|false
+detectorLocalSynchronizedCollection=LocalSynchronizedCollection|false
+detectorLostExceptionStackTrace=LostExceptionStackTrace|false
+detectorManualArrayCopy=ManualArrayCopy|false
+detectorMethodReturnsConstant=MethodReturnsConstant|false
+detectorNeedlessAutoboxing=NeedlessAutoboxing|false
+detectorNeedlessCustomSerialization=NeedlessCustomSerialization|false
+detectorNeedlessInstanceRetrieval=NeedlessInstanceRetrieval|false
+detectorNeedlessMemberCollectionSynchronization=NeedlessMemberCollectionSynchronization|false
+detectorNonCollectionMethodUse=NonCollectionMethodUse|false
+detectorNonOwnedSynchronization=NonOwnedSynchronization|false
+detectorNonRecycleableTaglibs=NonRecycleableTaglibs|false
+detectorOrphanedDOMNode=OrphanedDOMNode|false
+detectorOverlyConcreteParameter=OverlyConcreteParameter|false
+detectorParallelLists=ParallelLists|false
+detectorPartiallyConstructedObjectAccess=PartiallyConstructedObjectAccess|false
+detectorPossibleIncompleteSerialization=PossibleIncompleteSerialization|false
+detectorPossibleMemoryBloat=PossibleMemoryBloat|false
+detectorPossiblyRedundantMethodCalls=PossiblyRedundantMethodCalls|false
+detectorSQLInLoop=SQLInLoop|false
+detectorSection508Compliance=Section508Compliance|false
+detectorSillynessPotPourri=SillynessPotPourri|false
+detectorSloppyClassReflection=SloppyClassReflection|false
+detectorSluggishGui=SluggishGui|false
+detectorSpoiledChildInterfaceImplementor=SpoiledChildInterfaceImplementor|false
+detectorSpuriousThreadStates=SpuriousThreadStates|false
+detectorStaticArrayCreatedInMethod=StaticArrayCreatedInMethod|false
+detectorStaticMethodInstanceInvocation=StaticMethodInstanceInvocation|false
+detectorSuspiciousComparatorReturnValues=SuspiciousComparatorReturnValues|false
+detectorSuspiciousJDKVersionUse=SuspiciousJDKVersionUse|false
+detectorSuspiciousWaitOnConcurrentObject=SuspiciousWaitOnConcurrentObject|false
+detectorSyncCollectionIterators=SyncCollectionIterators|false
+detectorTailRecursion=TailRecursion|false
+detectorUnnecessaryStoreBeforeReturn=UnnecessaryStoreBeforeReturn|false
+detectorUnrelatedCollectionContents=UnrelatedCollectionContents|false
+detectorUnrelatedReturnValues=UnrelatedReturnValues|false
+detectorUseAddAll=UseAddAll|false
+detectorUseCharacterParameterizedMethod=UseCharacterParameterizedMethod|false
+detectorUseEnumCollections=UseEnumCollections|false
+detectorUseSplit=UseSplit|false
+detectorUseToArray=UseToArray|false
+detector_threshold=2
+effort=default
+filter_settings=Medium|BAD_PRACTICE,CORRECTNESS,I18N,MALICIOUS_CODE,MT_CORRECTNESS,PERFORMANCE,SECURITY,STYLE|false
+filter_settings_neg=|
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/nbproject/project.xml	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.netbeans.org/ns/project/1">
+    <type>org.netbeans.modules.ant.freeform</type>
+    <configuration>
+        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/1">
+            <name>jaxp</name>
+        </general-data>
+        <general-data xmlns="http://www.netbeans.org/ns/freeform-project/2">
+            <!-- Do not use Project Properties customizer when editing this file manually. -->
+            <name>jaxp</name>
+            <properties/>
+            <folders>
+                <source-folder>
+                    <label>jaxp</label>
+                    <location>.</location>
+                    <encoding>UTF-8</encoding>
+                </source-folder>
+            </folders>
+            <ide-actions>
+                <action name="build">
+                    <target>build</target>
+                </action>
+                <action name="clean">
+                    <target>clean</target>
+                </action>
+                <action name="rebuild">
+                    <target>clean</target>
+                    <target>build</target>
+                </action>
+            </ide-actions>
+            <view>
+                <items>
+                    <source-file>
+                        <location>build.xml</location>
+                    </source-file>
+                </items>
+                <context-menu>
+                    <ide-action name="build"/>
+                    <ide-action name="rebuild"/>
+                    <ide-action name="clean"/>
+                </context-menu>
+            </view>
+            <subprojects/>
+        </general-data>
+        <java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/1"/>
+        <preferences xmlns="http://www.netbeans.org/ns/auxiliary-configuration-preferences/1">
+            <module name="org-netbeans-modules-editor-indent"/>
+        </preferences>
+    </configuration>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/nbproject/sqe.properties	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,2 @@
+#Path to FindbugsSettingsFile (relative)
+findbugs.settings.file=findbugs.settings
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/patches/jaxp_src/README	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,5 @@
+
+This directory will hold any patches that need to be applied to the drop files.
+
+The patch order is defined in the ant build script properties.
+
--- a/jaxp/src/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jaxp/src/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
+ * Portions Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
  */
 
 /*
--- a/jdk/.hgtags	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/.hgtags	Wed Jul 05 17:01:09 2017 +0200
@@ -46,3 +46,4 @@
 226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69
 893bcca951b747ddcf6986362b877f0e1dbb835b jdk7-b70
 b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71
+460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72
--- a/jdk/make/java/java/FILES_java.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/make/java/java/FILES_java.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -454,6 +454,8 @@
     sun/misc/JavaLangAccess.java \
     sun/misc/JavaIOAccess.java \
     sun/misc/JavaIOFileDescriptorAccess.java \
-    sun/misc/JavaNioAccess.java
+    sun/misc/JavaNioAccess.java \
+    sun/misc/Perf.java \
+    sun/misc/PerfCounter.java
 
 FILES_java = $(JAVA_JAVA_java)
--- a/jdk/make/java/logging/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/make/java/logging/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -31,7 +31,7 @@
 #
 # Files to compile.
 #
-AUTO_FILES_JAVA_DIRS = java/util/logging
+AUTO_FILES_JAVA_DIRS = java/util/logging sun/util/logging
 
 #
 # Resources
@@ -46,7 +46,6 @@
 include $(BUILDDIR)/common/Classes.gmk
 
 properties: $(LIBDIR)/logging.properties
-
 $(LIBDIR)/logging.properties: $(SHARE_SRC)/lib/logging.properties
 	$(install-file)
 
--- a/jdk/make/sun/net/FILES_java.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/make/sun/net/FILES_java.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -86,9 +86,11 @@
 	sun/net/www/protocol/http/AuthCache.java \
 	sun/net/www/protocol/http/AuthCacheImpl.java \
 	sun/net/www/protocol/http/AuthCacheValue.java \
+	sun/net/www/protocol/http/AuthScheme.java \
 	sun/net/www/protocol/http/BasicAuthentication.java \
 	sun/net/www/protocol/http/DigestAuthentication.java \
 	sun/net/www/protocol/http/NTLMAuthentication.java \
+	sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
 	sun/net/www/protocol/http/NegotiateAuthentication.java \
 	sun/net/www/protocol/http/NegotiatorImpl.java \
 	sun/net/www/protocol/http/NegotiateCallbackHandler.java \
@@ -123,8 +125,7 @@
 	sun/net/idn/UCharacterEnums.java \
 	sun/net/idn/UCharacterDirection.java \
 	sun/net/idn/StringPrepDataReader.java \
-	sun/net/idn/StringPrep.java \
-	sun/net/www/protocol/http/InMemoryCookieStore.java
+	sun/net/idn/StringPrep.java
 
 ifeq ($(PLATFORM), windows)
     FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java 
--- a/jdk/make/sun/security/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/make/sun/security/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -60,8 +60,15 @@
   endif
 endif
 
-SUBDIRS = ec other action util tools jgss krb5 smartcardio $(PKCS11) \
-          $(JGSS_WRAPPER) $(MSCAPI)
+# Build in-tree elliptic curve crypto provider only when
+# DISABLE_INTREE_EC is not set
+INTREE_EC = ec
+ifdef DISABLE_INTREE_EC
+  INTREE_EC =
+endif
+
+SUBDIRS = $(INTREE_EC) other action util tools jgss krb5 smartcardio \
+	  $(PKCS11) $(JGSS_WRAPPER) $(MSCAPI)
 
 all build clean clobber::
 	$(SUBDIRS-loop)
--- a/jdk/make/sun/security/ec/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/make/sun/security/ec/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -24,7 +24,7 @@
 #
 
 #
-# Makefile for building sunec.jar and sunecc native library.
+# Makefile for building sunec.jar and sunec native library.
 #
 # This file was derived from make/com/sun/crypto/provider/Makefile.
 #
@@ -121,7 +121,15 @@
 #
 AUTO_FILES_JAVA_DIRS = $(PKGDIR)
 
-include $(BUILDDIR)/common/Classes.gmk
+#
+# Exclude the sources that get built by ../other/Makefile
+#
+AUTO_JAVA_PRUNE = \
+    ECKeyFactory.java \
+    ECParameters.java \
+    ECPrivateKeyImpl.java \
+    ECPublicKeyImpl.java \
+    NamedCurve.java
 
 #
 # Some licensees do not get the native ECC sources, but we still need to
@@ -130,7 +138,7 @@
 #
 
 NATIVE_ECC_AVAILABLE := $(shell \
-    if [ -d $(SHARE_SRC)/native/$(PKGDIR) ] ; then \
+    if [ -d $(SHARE_SRC)/native/$(PKGDIR)/impl ] ; then \
 	$(ECHO) true; \
     else \
 	$(ECHO) false; \
@@ -138,7 +146,7 @@
 
 ifeq ($(NATIVE_ECC_AVAILABLE), true)
 
-  LIBRARY = sunecc
+  LIBRARY = sunec
 
   #
   # Java files that define native methods
@@ -166,12 +174,12 @@
   #
   vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)
 
-  vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
+  vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/impl
 
   #
   # Find include files
   #
-  OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)
+  OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)/impl
 
   #
   # Compiler flags
@@ -191,6 +199,10 @@
 
   include $(BUILDDIR)/common/Library.gmk
 
+else # NATIVE_ECC_AVAILABLE
+
+  include $(BUILDDIR)/common/Classes.gmk
+
 endif # NATIVE_ECC_AVAILABLE
 
 #
--- a/jdk/make/sun/security/other/Makefile	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/make/sun/security/other/Makefile	Wed Jul 05 17:01:09 2017 +0200
@@ -45,6 +45,16 @@
     com/sun/net/ssl/internal/ssl
 
 #
+# EC classes used by the packages above
+#
+FILES_java += \
+    sun/security/ec/ECKeyFactory.java \
+    sun/security/ec/ECParameters.java \
+    sun/security/ec/ECPrivateKeyImpl.java \
+    sun/security/ec/ECPublicKeyImpl.java \
+    sun/security/ec/NamedCurve.java
+
+#
 # Rules
 #
 include $(BUILDDIR)/common/Classes.gmk
--- a/jdk/src/share/bin/java.h	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/bin/java.h	Wed Jul 05 17:01:09 2017 +0200
@@ -187,9 +187,6 @@
  *
  */
 typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env,
-                                                const char *name,
-                                                jboolean init,
-                                                jobject loader,
-                                                jboolean throwError));
+                                                  const char *name));
 jclass FindBootStrapClass(JNIEnv *env, const char *classname);
 #endif /* _JAVA_H_ */
--- a/jdk/src/share/bin/parse_manifest.c	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/bin/parse_manifest.c	Wed Jul 05 17:01:09 2017 +0200
@@ -59,7 +59,7 @@
     char        *out;
     z_stream    zs;
 
-    if (entry->csize == 0xffffffff || entry->isize == 0xffffffff)
+    if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 )
         return (NULL);
     if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0)
         return (NULL);
--- a/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java	Wed Jul 05 17:01:09 2017 +0200
@@ -133,7 +133,7 @@
      * This method returns an enumerated handle of the keys
      * which correspond to values translated to various locales.
      *
-     * @returns an enumerated keys which have messages tranlated to
+     * @return an enumeration of keys which have messages tranlated to
      * corresponding locales.
      */
     public Enumeration getKeys() {
@@ -146,7 +146,7 @@
      * returns the corresponding value reading it
      * from the Resource Bundle loaded earlier.
      *
-     * @returns value in locale specific language
+     * @return value in locale specific language
      * according to the key passed.
      */
     public Object handleGetObject(String key) {
--- a/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/JoinRowSetImpl.java	Wed Jul 05 17:01:09 2017 +0200
@@ -3737,7 +3737,6 @@
     * Returns a result set containing the original value of the current
     * row only.
     *
-    * @return the original result set of the row
     * @throws SQLException if there is no current row
     * @see #setOriginalRow
     */
--- a/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java	Wed Jul 05 17:01:09 2017 +0200
@@ -46,6 +46,17 @@
  */
 public class WebRowSetXmlReader implements XmlReader, Serializable {
 
+
+    private JdbcRowSetResourceBundle resBundle;
+
+    public WebRowSetXmlReader(){
+        try {
+           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+        } catch(IOException ioe) {
+            throw new RuntimeException(ioe);
+        }
+    }
+
     /**
      * Parses the given <code>WebRowSet</code> object, getting its input from
      * the given <code>java.io.Reader</code> object.  The parser will send
@@ -69,17 +80,6 @@
      *            reader for the given rowset
      * @see XmlReaderContentHandler
      */
-
-    private JdbcRowSetResourceBundle resBundle;
-
-    public WebRowSetXmlReader(){
-        try {
-           resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
-        } catch(IOException ioe) {
-            throw new RuntimeException(ioe);
-        }
-    }
-
     public void readXML(WebRowSet caller, java.io.Reader reader) throws SQLException {
         try {
             // Crimson Parser(as in J2SE 1.4.1 is NOT able to handle
--- a/jdk/src/share/classes/java/lang/Class.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/lang/Class.java	Wed Jul 05 17:01:09 2017 +0200
@@ -565,8 +565,9 @@
      *          represented by this object.
      */
     public String getName() {
+        String name = this.name;
         if (name == null)
-            name = getName0();
+            this.name = name = getName0();
         return name;
     }
 
--- a/jdk/src/share/classes/java/lang/ClassLoader.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/lang/ClassLoader.java	Wed Jul 05 17:01:09 2017 +0200
@@ -380,16 +380,28 @@
             // First, check if the class has already been loaded
             Class c = findLoadedClass(name);
             if (c == null) {
+                long t0 = System.nanoTime();
                 try {
                     if (parent != null) {
                         c = parent.loadClass(name, false);
                     } else {
-                        c = findBootstrapClass0(name);
+                        c = findBootstrapClassOrNull(name);
                     }
                 } catch (ClassNotFoundException e) {
+                    // ClassNotFoundException thrown if class not found
+                    // from the non-null parent class loader
+                }
+
+                if (c == null) {
                     // If still not found, then invoke findClass in order
                     // to find the class.
+                    long t1 = System.nanoTime();
                     c = findClass(name);
+
+                    // this is the defining class loader; record the stats
+                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
+                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
+                    sun.misc.PerfCounter.getFindClasses().increment();
                 }
             }
             if (resolve) {
@@ -1008,22 +1020,29 @@
         if (system == null) {
             if (!checkName(name))
                 throw new ClassNotFoundException(name);
-            return findBootstrapClass(name);
+            Class cls = findBootstrapClass(name);
+            if (cls == null) {
+                throw new ClassNotFoundException(name);
+            }
+            return cls;
         }
         return system.loadClass(name);
     }
 
-    private Class findBootstrapClass0(String name)
-        throws ClassNotFoundException
+    /**
+     * Returns a class loaded by the bootstrap class loader;
+     * or return null if not found.
+     */
+    private Class findBootstrapClassOrNull(String name)
     {
         check();
-        if (!checkName(name))
-            throw new ClassNotFoundException(name);
+        if (!checkName(name)) return null;
+
         return findBootstrapClass(name);
     }
 
-    private native Class findBootstrapClass(String name)
-        throws ClassNotFoundException;
+    // return null if not found
+    private native Class findBootstrapClass(String name);
 
     // Check to make sure the class loader has been initialized.
     private void check() {
--- a/jdk/src/share/classes/java/net/CookieManager.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/net/CookieManager.java	Wed Jul 05 17:01:09 2017 +0200
@@ -157,7 +157,7 @@
 
         // if not specify CookieStore to use, use default one
         if (store == null) {
-            cookieJar = new sun.net.www.protocol.http.InMemoryCookieStore();
+            cookieJar = new InMemoryCookieStore();
         } else {
             cookieJar = store;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/net/InMemoryCookieStore.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,393 @@
+/*
+ * Copyright 2005-2008 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 java.net;
+
+import java.net.URI;
+import java.net.CookieStore;
+import java.net.HttpCookie;
+import java.net.URISyntaxException;
+import java.util.List;
+import java.util.Map;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * A simple in-memory java.net.CookieStore implementation
+ *
+ * @author Edward Wang
+ * @since 1.6
+ */
+class InMemoryCookieStore implements CookieStore {
+    // the in-memory representation of cookies
+    private List<HttpCookie> cookieJar = null;
+
+    // the cookies are indexed by its domain and associated uri (if present)
+    // CAUTION: when a cookie removed from main data structure (i.e. cookieJar),
+    //          it won't be cleared in domainIndex & uriIndex. Double-check the
+    //          presence of cookie when retrieve one form index store.
+    private Map<String, List<HttpCookie>> domainIndex = null;
+    private Map<URI, List<HttpCookie>> uriIndex = null;
+
+    // use ReentrantLock instead of syncronized for scalability
+    private ReentrantLock lock = null;
+
+
+    /**
+     * The default ctor
+     */
+    public InMemoryCookieStore() {
+        cookieJar = new ArrayList<HttpCookie>();
+        domainIndex = new HashMap<String, List<HttpCookie>>();
+        uriIndex = new HashMap<URI, List<HttpCookie>>();
+
+        lock = new ReentrantLock(false);
+    }
+
+    /**
+     * Add one cookie into cookie store.
+     */
+    public void add(URI uri, HttpCookie cookie) {
+        // pre-condition : argument can't be null
+        if (cookie == null) {
+            throw new NullPointerException("cookie is null");
+        }
+
+
+        lock.lock();
+        try {
+            // remove the ole cookie if there has had one
+            cookieJar.remove(cookie);
+
+            // add new cookie if it has a non-zero max-age
+            if (cookie.getMaxAge() != 0) {
+                cookieJar.add(cookie);
+                // and add it to domain index
+                if (cookie.getDomain() != null) {
+                    addIndex(domainIndex, cookie.getDomain(), cookie);
+                }
+                // add it to uri index, too
+                addIndex(uriIndex, getEffectiveURI(uri), cookie);
+            }
+        } finally {
+            lock.unlock();
+        }
+    }
+
+
+    /**
+     * Get all cookies, which:
+     *  1) given uri domain-matches with, or, associated with
+     *     given uri when added to the cookie store.
+     *  3) not expired.
+     * See RFC 2965 sec. 3.3.4 for more detail.
+     */
+    public List<HttpCookie> get(URI uri) {
+        // argument can't be null
+        if (uri == null) {
+            throw new NullPointerException("uri is null");
+        }
+
+        List<HttpCookie> cookies = new ArrayList<HttpCookie>();
+        boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
+        lock.lock();
+        try {
+            // check domainIndex first
+            getInternal1(cookies, domainIndex, uri.getHost(), secureLink);
+            // check uriIndex then
+            getInternal2(cookies, uriIndex, getEffectiveURI(uri), secureLink);
+        } finally {
+            lock.unlock();
+        }
+
+        return cookies;
+    }
+
+    /**
+     * Get all cookies in cookie store, except those have expired
+     */
+    public List<HttpCookie> getCookies() {
+        List<HttpCookie> rt;
+
+        lock.lock();
+        try {
+            Iterator<HttpCookie> it = cookieJar.iterator();
+            while (it.hasNext()) {
+                if (it.next().hasExpired()) {
+                    it.remove();
+                }
+            }
+        } finally {
+            rt = Collections.unmodifiableList(cookieJar);
+            lock.unlock();
+        }
+
+        return rt;
+    }
+
+    /**
+     * Get all URIs, which are associated with at least one cookie
+     * of this cookie store.
+     */
+    public List<URI> getURIs() {
+        List<URI> uris = new ArrayList<URI>();
+
+        lock.lock();
+        try {
+            Iterator<URI> it = uriIndex.keySet().iterator();
+            while (it.hasNext()) {
+                URI uri = it.next();
+                List<HttpCookie> cookies = uriIndex.get(uri);
+                if (cookies == null || cookies.size() == 0) {
+                    // no cookies list or an empty list associated with
+                    // this uri entry, delete it
+                    it.remove();
+                }
+            }
+        } finally {
+            uris.addAll(uriIndex.keySet());
+            lock.unlock();
+        }
+
+        return uris;
+    }
+
+
+    /**
+     * Remove a cookie from store
+     */
+    public boolean remove(URI uri, HttpCookie ck) {
+        // argument can't be null
+        if (ck == null) {
+            throw new NullPointerException("cookie is null");
+        }
+
+        boolean modified = false;
+        lock.lock();
+        try {
+            modified = cookieJar.remove(ck);
+        } finally {
+            lock.unlock();
+        }
+
+        return modified;
+    }
+
+
+    /**
+     * Remove all cookies in this cookie store.
+     */
+    public boolean removeAll() {
+        lock.lock();
+        try {
+            cookieJar.clear();
+            domainIndex.clear();
+            uriIndex.clear();
+        } finally {
+            lock.unlock();
+        }
+
+        return true;
+    }
+
+
+    /* ---------------- Private operations -------------- */
+
+
+    /*
+     * This is almost the same as HttpCookie.domainMatches except for
+     * one difference: It won't reject cookies when the 'H' part of the
+     * domain contains a dot ('.').
+     * I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
+     * and the cookie domain is .domain.com, then it should be rejected.
+     * However that's not how the real world works. Browsers don't reject and
+     * some sites, like yahoo.com do actually expect these cookies to be
+     * passed along.
+     * And should be used for 'old' style cookies (aka Netscape type of cookies)
+     */
+    private boolean netscapeDomainMatches(String domain, String host)
+    {
+        if (domain == null || host == null) {
+            return false;
+        }
+
+        // if there's no embedded dot in domain and domain is not .local
+        boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
+        int embeddedDotInDomain = domain.indexOf('.');
+        if (embeddedDotInDomain == 0) {
+            embeddedDotInDomain = domain.indexOf('.', 1);
+        }
+        if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
+            return false;
+        }
+
+        // if the host name contains no dot and the domain name is .local
+        int firstDotInHost = host.indexOf('.');
+        if (firstDotInHost == -1 && isLocalDomain) {
+            return true;
+        }
+
+        int domainLength = domain.length();
+        int lengthDiff = host.length() - domainLength;
+        if (lengthDiff == 0) {
+            // if the host name and the domain name are just string-compare euqal
+            return host.equalsIgnoreCase(domain);
+        } else if (lengthDiff > 0) {
+            // need to check H & D component
+            String H = host.substring(0, lengthDiff);
+            String D = host.substring(lengthDiff);
+
+            return (D.equalsIgnoreCase(domain));
+        } else if (lengthDiff == -1) {
+            // if domain is actually .host
+            return (domain.charAt(0) == '.' &&
+                    host.equalsIgnoreCase(domain.substring(1)));
+        }
+
+        return false;
+    }
+
+    private void getInternal1(List<HttpCookie> cookies, Map<String, List<HttpCookie>> cookieIndex,
+            String host, boolean secureLink) {
+        // Use a separate list to handle cookies that need to be removed so
+        // that there is no conflict with iterators.
+        ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
+        for (Map.Entry<String, List<HttpCookie>> entry : cookieIndex.entrySet()) {
+            String domain = entry.getKey();
+            List<HttpCookie> lst = entry.getValue();
+            for (HttpCookie c : lst) {
+                if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
+                        (c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
+                    if ((cookieJar.indexOf(c) != -1)) {
+                        // the cookie still in main cookie store
+                        if (!c.hasExpired()) {
+                            // don't add twice and make sure it's the proper
+                            // security level
+                            if ((secureLink || !c.getSecure()) &&
+                                    !cookies.contains(c)) {
+                                cookies.add(c);
+                            }
+                        } else {
+                            toRemove.add(c);
+                        }
+                    } else {
+                        // the cookie has beed removed from main store,
+                        // so also remove it from domain indexed store
+                        toRemove.add(c);
+                    }
+                }
+            }
+            // Clear up the cookies that need to be removed
+            for (HttpCookie c : toRemove) {
+                lst.remove(c);
+                cookieJar.remove(c);
+
+            }
+            toRemove.clear();
+        }
+    }
+
+    // @param cookies           [OUT] contains the found cookies
+    // @param cookieIndex       the index
+    // @param comparator        the prediction to decide whether or not
+    //                          a cookie in index should be returned
+    private <T> void getInternal2(List<HttpCookie> cookies,
+                                Map<T, List<HttpCookie>> cookieIndex,
+                                Comparable<T> comparator, boolean secureLink)
+    {
+        for (T index : cookieIndex.keySet()) {
+            if (comparator.compareTo(index) == 0) {
+                List<HttpCookie> indexedCookies = cookieIndex.get(index);
+                // check the list of cookies associated with this domain
+                if (indexedCookies != null) {
+                    Iterator<HttpCookie> it = indexedCookies.iterator();
+                    while (it.hasNext()) {
+                        HttpCookie ck = it.next();
+                        if (cookieJar.indexOf(ck) != -1) {
+                            // the cookie still in main cookie store
+                            if (!ck.hasExpired()) {
+                                // don't add twice
+                                if ((secureLink || !ck.getSecure()) &&
+                                        !cookies.contains(ck))
+                                    cookies.add(ck);
+                            } else {
+                                it.remove();
+                                cookieJar.remove(ck);
+                            }
+                        } else {
+                            // the cookie has beed removed from main store,
+                            // so also remove it from domain indexed store
+                            it.remove();
+                        }
+                    }
+                } // end of indexedCookies != null
+            } // end of comparator.compareTo(index) == 0
+        } // end of cookieIndex iteration
+    }
+
+    // add 'cookie' indexed by 'index' into 'indexStore'
+    private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
+                              T index,
+                              HttpCookie cookie)
+    {
+        if (index != null) {
+            List<HttpCookie> cookies = indexStore.get(index);
+            if (cookies != null) {
+                // there may already have the same cookie, so remove it first
+                cookies.remove(cookie);
+
+                cookies.add(cookie);
+            } else {
+                cookies = new ArrayList<HttpCookie>();
+                cookies.add(cookie);
+                indexStore.put(index, cookies);
+            }
+        }
+    }
+
+
+    //
+    // for cookie purpose, the effective uri should only be http://host
+    // the path will be taken into account when path-match algorithm applied
+    //
+    private URI getEffectiveURI(URI uri) {
+        URI effectiveURI = null;
+        try {
+            effectiveURI = new URI("http",
+                                   uri.getHost(),
+                                   null,  // path component
+                                   null,  // query component
+                                   null   // fragment component
+                                  );
+        } catch (URISyntaxException ignored) {
+            effectiveURI = uri;
+        }
+
+        return effectiveURI;
+    }
+}
--- a/jdk/src/share/classes/java/net/URLClassLoader.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/net/URLClassLoader.java	Wed Jul 05 17:01:09 2017 +0200
@@ -340,6 +340,7 @@
      * used.
      */
     private Class defineClass(String name, Resource res) throws IOException {
+        long t0 = System.nanoTime();
         int i = name.lastIndexOf('.');
         URL url = res.getCodeSourceURL();
         if (i != -1) {
@@ -370,12 +371,14 @@
             // Use (direct) ByteBuffer:
             CodeSigner[] signers = res.getCodeSigners();
             CodeSource cs = new CodeSource(url, signers);
+            sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
             return defineClass(name, bb, cs);
         } else {
             byte[] b = res.getBytes();
             // must read certificates AFTER reading bytes.
             CodeSigner[] signers = res.getCodeSigners();
             CodeSource cs = new CodeSource(url, signers);
+            sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0);
             return defineClass(name, b, 0, b.length, cs);
         }
     }
--- a/jdk/src/share/classes/java/net/doc-files/net-properties.html	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/net/doc-files/net-properties.html	Wed Jul 05 17:01:09 2017 +0200
@@ -71,12 +71,12 @@
 	<LI><P>HTTP</P>
 	<P>The following proxy settings are used by the HTTP protocol handler.</P>
 	<UL>
-		<LI><P><B>http.proxyHost</FONT></B> (default: &lt;none&gt;)<BR>
+		<LI><P><B>http.proxyHost</B> (default: &lt;none&gt;)<BR>
 	        The hostname, or address, of the proxy server 
 		</P>
 		<LI><P><B>http.proxyPort</B> (default: 80)<BR>
 	        The port number of the proxy server.</P>
-		<LI><P><B>http.nonProxyHosts</B> (default: &lt;none&gt;)<BR>
+		<LI><P><B>http.nonProxyHosts</B> (default:  localhost|127.*|[::1])<BR>
 	        Indicates the hosts that should be accessed without going
 	        through the proxy. Typically this defines internal hosts.
 	        The value of this property is a list of hosts,
@@ -86,7 +86,8 @@
 		will indicate that every hosts in the foo.com domain and the
 		localhost should be accessed directly even if a proxy server is
 		specified.</P>
-	</UL>
+                <P>The default value excludes all common variations of the loopback address.</P>
+        </UL>
 	<LI><P>HTTPS<BR>This is HTTP over SSL, a secure version of HTTP
 	mainly used when confidentiality (like on payment sites) is needed.</P>
 	<P>The following proxy settings are used by the HTTPS protocol handler.</P>
@@ -107,7 +108,7 @@
 		</P>
 		<LI><P><B>ftp.proxyPort</B> (default: 80)<BR>
 	        The port number of the proxy server.</P>
-		<LI><P><B>ftp.nonProxyHosts</B> (default: &lt;none&gt;)<BR>
+		<LI><P><B>ftp.nonProxyHosts</B> (default: localhost|127.*|[::1])<BR>
 	        Indicates the hosts that should be accessed without going
 	        through the proxy. Typically this defines internal hosts.
 	        The value of this property is a list of hosts, separated by
@@ -117,6 +118,7 @@
 		will indicate that every hosts in the foo.com domain and the
 		localhost should be accessed directly even if a proxy server is
 		specified.</P>
+                <P>The default value excludes all common variations of the loopback address.</P>
 	</UL>
 	<LI><P>SOCKS<BR>This is another type of proxy. It allows for lower
 	level type of tunneling since it works at the TCP level. In effect,
--- a/jdk/src/share/classes/java/nio/file/FileTreeWalker.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/nio/file/FileTreeWalker.java	Wed Jul 05 17:01:09 2017 +0200
@@ -41,8 +41,12 @@
     private final boolean detectCycles;
     private final LinkOption[] linkOptions;
     private final FileVisitor<? super Path> visitor;
+    private final int maxDepth;
 
-    FileTreeWalker(Set<FileVisitOption> options, FileVisitor<? super Path> visitor) {
+    FileTreeWalker(Set<FileVisitOption> options,
+                   FileVisitor<? super Path> visitor,
+                   int maxDepth)
+    {
         boolean fl = false;
         boolean dc = false;
         for (FileVisitOption option: options) {
@@ -58,18 +62,15 @@
         this.linkOptions = (fl) ? new LinkOption[0] :
             new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
         this.visitor = visitor;
+        this.maxDepth = maxDepth;
     }
 
     /**
      * Walk file tree starting at the given file
      */
-    void walk(Path start, int maxDepth) {
-        // don't use attributes of starting file as they may be stale
-        if (start instanceof BasicFileAttributesHolder) {
-            ((BasicFileAttributesHolder)start).invalidate();
-        }
+    void walk(Path start) {
         FileVisitResult result = walk(start,
-                                      maxDepth,
+                                      0,
                                       new ArrayList<AncestorDirectory>());
         if (result == null) {
             throw new NullPointerException("Visitor returned 'null'");
@@ -89,12 +90,15 @@
                                  List<AncestorDirectory> ancestors)
     {
         // depth check
-        if (depth-- < 0)
+        if (depth > maxDepth)
             return FileVisitResult.CONTINUE;
 
         // if attributes are cached then use them if possible
         BasicFileAttributes attrs = null;
-        if (file instanceof BasicFileAttributesHolder) {
+        if ((depth > 0) &&
+            (file instanceof BasicFileAttributesHolder) &&
+            (System.getSecurityManager() == null))
+        {
             BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get();
             if (!followLinks || !cached.isSymbolicLink())
                 attrs = cached;
@@ -120,6 +124,10 @@
                     }
                 }
             } catch (SecurityException x) {
+                // If access to starting file is denied then SecurityException
+                // is thrown, otherwise the file is ignored.
+                if (depth == 0)
+                    throw x;
                 return FileVisitResult.CONTINUE;
             }
         }
@@ -196,7 +204,7 @@
                 try {
                     for (Path entry: stream) {
                         inAction = true;
-                        result = walk(entry, depth, ancestors);
+                        result = walk(entry, depth+1, ancestors);
                         inAction = false;
 
                         // returning null will cause NPE to be thrown
--- a/jdk/src/share/classes/java/nio/file/Files.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/nio/file/Files.java	Wed Jul 05 17:01:09 2017 +0200
@@ -223,7 +223,7 @@
     {
         if (maxDepth < 0)
             throw new IllegalArgumentException("'maxDepth' is negative");
-        new FileTreeWalker(options, visitor).walk(start, maxDepth);
+        new FileTreeWalker(options, visitor, maxDepth).walk(start);
     }
 
     /**
--- a/jdk/src/share/classes/java/util/Currency.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/Currency.java	Wed Jul 05 17:01:09 2017 +0200
@@ -35,12 +35,12 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.logging.Level;
-import java.util.logging.Logger;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 import java.util.spi.CurrencyNameProvider;
 import java.util.spi.LocaleServiceProvider;
 import sun.util.LocaleServiceProviderPool;
+import sun.util.logging.PlatformLogger;
 import sun.util.resources.LocaleData;
 import sun.util.resources.OpenListResourceBundle;
 
@@ -244,7 +244,7 @@
                         }
                     }
                 } catch (IOException e) {
-                    log(Level.INFO, "currency.properties is ignored because of an IOException", e);
+                    info("currency.properties is ignored because of an IOException", e);
                 }
                 return null;
             }
@@ -686,7 +686,7 @@
                 .append("The entry in currency.properties for ")
                 .append(ctry).append(" is ignored because of the invalid country code.")
                 .toString();
-            log(Level.INFO, message, null);
+            info(message, null);
             return;
         }
 
@@ -698,7 +698,7 @@
                 .append(ctry)
                 .append(" is ignored because the value format is not recognized.")
                 .toString();
-            log(Level.INFO, message, null);
+            info(message, null);
             return;
         }
 
@@ -726,13 +726,13 @@
         setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
     }
 
-    private static void log(Level level, String message, Throwable t) {
-        Logger logger = Logger.getLogger("java.util.Currency");
-        if (logger.isLoggable(level)) {
+    private static void info(String message, Throwable t) {
+        PlatformLogger logger = PlatformLogger.getLogger("java.util.Currency");
+        if (logger.isLoggable(PlatformLogger.INFO)) {
             if (t != null) {
-                logger.log(level, message, t);
+                logger.info(message, t);
             } else {
-                logger.log(level, message);
+                logger.info(message);
             }
         }
     }
--- a/jdk/src/share/classes/java/util/jar/Attributes.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/jar/Attributes.java	Wed Jul 05 17:01:09 2017 +0200
@@ -34,7 +34,7 @@
 import java.util.Collection;
 import java.util.AbstractSet;
 import java.util.Iterator;
-import java.util.logging.Logger;
+import sun.util.logging.PlatformLogger;
 import java.util.Comparator;
 import sun.misc.ASCIICaseInsensitiveComparator;
 
@@ -419,7 +419,7 @@
             }
             try {
                 if ((putValue(name, value) != null) && (!lineContinued)) {
-                    Logger.getLogger("java.util.jar").warning(
+                    PlatformLogger.getLogger("java.util.jar").warning(
                                      "Duplicate name in Manifest: " + name
                                      + ".\n"
                                      + "Ensure that the manifest does not "
--- a/jdk/src/share/classes/java/util/logging/ErrorManager.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/ErrorManager.java	Wed Jul 05 17:01:09 2017 +0200
@@ -28,7 +28,7 @@
 
 /**
  * ErrorManager objects can be attached to Handlers to process
- * any error that occur on a Handler during Logging.
+ * any error that occurs on a Handler during Logging.
  * <p>
  * When processing logging output, if a Handler encounters problems
  * then rather than throwing an Exception back to the issuer of
@@ -72,7 +72,7 @@
     /**
      * The error method is called when a Handler failure occurs.
      * <p>
-     * This method may be overriden in subclasses.  The default
+     * This method may be overridden in subclasses.  The default
      * behavior in this base class is that the first call is
      * reported to System.err, and subsequent calls are ignored.
      *
--- a/jdk/src/share/classes/java/util/logging/FileHandler.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/FileHandler.java	Wed Jul 05 17:01:09 2017 +0200
@@ -39,7 +39,7 @@
  * For a rotating set of files, as each file reaches a given size
  * limit, it is closed, rotated out, and a new file opened.
  * Successively older files are named by adding "0", "1", "2",
- * etc into the base filename.
+ * etc. into the base filename.
  * <p>
  * By default buffering is enabled in the IO libraries but each log
  * record is flushed out when it is complete.
@@ -391,7 +391,7 @@
             // Generate a lock file name from the "unique" int.
             lockFileName = generate(pattern, 0, unique).toString() + ".lck";
             // Now try to lock that filename.
-            // Because some systems (e.g. Solaris) can only do file locks
+            // Because some systems (e.g., Solaris) can only do file locks
             // between processes (and not within a process), we first check
             // if we ourself already have the file locked.
             synchronized(locks) {
--- a/jdk/src/share/classes/java/util/logging/Formatter.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/Formatter.java	Wed Jul 05 17:01:09 2017 +0200
@@ -52,7 +52,7 @@
      * Format the given log record and return the formatted string.
      * <p>
      * The resulting formatted String will normally include a
-     * localized and formated version of the LogRecord's message field.
+     * localized and formatted version of the LogRecord's message field.
      * It is recommended to use the {@link Formatter#formatMessage}
      * convenience method to localize and format the message field.
      *
@@ -66,7 +66,7 @@
      * Return the header string for a set of formatted records.
      * <p>
      * This base class returns an empty string, but this may be
-     * overriden by subclasses.
+     * overridden by subclasses.
      *
      * @param   h  The target handler (can be null)
      * @return  header string
@@ -79,7 +79,7 @@
      * Return the tail string for a set of formatted records.
      * <p>
      * This base class returns an empty string, but this may be
-     * overriden by subclasses.
+     * overridden by subclasses.
      *
      * @param   h  The target handler (can be null)
      * @return  tail string
--- a/jdk/src/share/classes/java/util/logging/Handler.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/Handler.java	Wed Jul 05 17:01:09 2017 +0200
@@ -274,7 +274,7 @@
      * <tt>Level</tt> and  whether it satisfies any <tt>Filter</tt>.  It also
      * may make other <tt>Handler</tt> specific checks that might prevent a
      * handler from logging the <tt>LogRecord</tt>. It will return false if
-     * the <tt>LogRecord</tt> is Null.
+     * the <tt>LogRecord</tt> is null.
      * <p>
      * @param record  a <tt>LogRecord</tt>
      * @return true if the <tt>LogRecord</tt> would be logged.
--- a/jdk/src/share/classes/java/util/logging/Level.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/Level.java	Wed Jul 05 17:01:09 2017 +0200
@@ -110,7 +110,7 @@
      * Typically INFO messages will be written to the console
      * or its equivalent.  So the INFO level should only be
      * used for reasonably significant messages that will
-     * make sense to end users and system admins.
+     * make sense to end users and system administrators.
      * This level is initialized to <CODE>800</CODE>.
      */
     public static final Level INFO = new Level("INFO", 800, defaultBundle);
@@ -245,6 +245,8 @@
     }
 
     /**
+     * Returns a string representation of this Level.
+     *
      * @return the non-localized name of the Level, for example "INFO".
      */
     public final String toString() {
@@ -299,14 +301,14 @@
      * @throws IllegalArgumentException if the value is not valid.
      * Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
      * and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
-     * Known names are the levels defined by this class (i.e. <CODE>FINE</CODE>,
+     * Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
      * <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
      * appropriate package access, or new levels defined or created
      * by subclasses.
      *
      * @return The parsed value. Passing an integer that corresponds to a known name
-     * (eg 700) will return the associated name (eg <CODE>CONFIG</CODE>).
-     * Passing an integer that does not (eg 1) will return a new level name
+     * (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
+     * Passing an integer that does not (e.g., 1) will return a new level name
      * initialized to that value.
      */
     public static synchronized Level parse(String name) throws IllegalArgumentException {
--- a/jdk/src/share/classes/java/util/logging/LogManager.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java	Wed Jul 05 17:01:09 2017 +0200
@@ -283,6 +283,10 @@
                         AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                                 public Object run() throws Exception {
                                     readConfiguration();
+
+                                    // Platform loggers begin to delegate to java.util.logging.Logger
+                                    sun.util.logging.PlatformLogger.redirectPlatformLoggers();
+
                                     return null;
                                 }
                             });
--- a/jdk/src/share/classes/java/util/logging/LogRecord.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogRecord.java	Wed Jul 05 17:01:09 2017 +0200
@@ -188,7 +188,7 @@
    }
 
     /**
-     * Get the source Logger name's
+     * Get the source Logger's name.
      *
      * @return source logger name (may be null)
      */
@@ -197,7 +197,7 @@
     }
 
     /**
-     * Set the source Logger name.
+     * Set the source Logger's name.
      *
      * @param name   the source logger name (may be null)
      */
@@ -530,6 +530,7 @@
         int depth = access.getStackTraceDepth(throwable);
 
         String logClassName = "java.util.logging.Logger";
+        String plogClassName = "sun.util.logging.PlatformLogger";
         boolean lookingForLogger = true;
         for (int ix = 0; ix < depth; ix++) {
             // Calling getStackTraceElement directly prevents the VM
@@ -539,15 +540,18 @@
             String cname = frame.getClassName();
             if (lookingForLogger) {
                 // Skip all frames until we have found the first logger frame.
-                if (cname.equals(logClassName)) {
+                if (cname.equals(logClassName) || cname.startsWith(plogClassName)) {
                     lookingForLogger = false;
                 }
             } else {
-                if (!cname.equals(logClassName)) {
-                    // We've found the relevant frame.
-                    setSourceClassName(cname);
-                    setSourceMethodName(frame.getMethodName());
-                    return;
+                if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) {
+                    // skip reflection call
+                    if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) {
+                       // We've found the relevant frame.
+                       setSourceClassName(cname);
+                       setSourceMethodName(frame.getMethodName());
+                       return;
+                    }
                 }
             }
         }
--- a/jdk/src/share/classes/java/util/logging/Logger.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/Logger.java	Wed Jul 05 17:01:09 2017 +0200
@@ -66,7 +66,7 @@
  * effective level from its parent.
  * <p>
  * On each logging call the Logger initially performs a cheap
- * check of the request level (e.g. SEVERE or FINE) against the
+ * check of the request level (e.g., SEVERE or FINE) against the
  * effective log level of the logger.  If the request level is
  * lower than the log level, the logging call returns immediately.
  * <p>
@@ -230,7 +230,7 @@
      * Protected method to construct a logger for a named subsystem.
      * <p>
      * The logger will be initially configured with a null Level
-     * and with useParentHandlers true.
+     * and with useParentHandlers set to true.
      *
      * @param   name    A name for the logger.  This should
      *                          be a dot-separated name and should normally
@@ -240,7 +240,7 @@
      * @param   resourceBundleName  name of ResourceBundle to be used for localizing
      *                          messages for this logger.  May be null if none
      *                          of the messages require localization.
-     * @throws MissingResourceException if the ResourceBundleName is non-null and
+     * @throws MissingResourceException if the resourceBundleName is non-null and
      *             no corresponding resource can be found.
      */
     protected Logger(String name, String resourceBundleName) {
@@ -285,7 +285,7 @@
      * <p>
      * If a new logger is created its log level will be configured
      * based on the LogManager configuration and it will configured
-     * to also send logging output to its parent's handlers.  It will
+     * to also send logging output to its parent's Handlers.  It will
      * be registered in the LogManager global namespace.
      *
      * @param   name            A name for the logger.  This should
@@ -308,7 +308,7 @@
      * <p>
      * If a new logger is created its log level will be configured
      * based on the LogManager and it will configured to also send logging
-     * output to its parent loggers Handlers.  It will be registered in
+     * output to its parent's Handlers.  It will be registered in
      * the LogManager global namespace.
      * <p>
      * If the named Logger already exists and does not yet have a
@@ -326,7 +326,8 @@
      *                          messages for this logger. May be <CODE>null</CODE> if none of
      *                          the messages require localization.
      * @return a suitable Logger
-     * @throws MissingResourceException if the named ResourceBundle cannot be found.
+     * @throws MissingResourceException if the resourceBundleName is non-null and
+     *             no corresponding resource can be found.
      * @throws IllegalArgumentException if the Logger already exists and uses
      *             a different resource bundle name.
      * @throws NullPointerException if the name is null.
@@ -395,7 +396,8 @@
      *                          messages for this logger.
      *          May be null if none of the messages require localization.
      * @return a newly created private Logger
-     * @throws MissingResourceException if the named ResourceBundle cannot be found.
+     * @throws MissingResourceException if the resourceBundleName is non-null and
+     *             no corresponding resource can be found.
      */
     public static synchronized Logger getAnonymousLogger(String resourceBundleName) {
         LogManager manager = LogManager.getLogManager();
@@ -514,7 +516,7 @@
      * level then the given message is forwarded to all the
      * registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      */
     public void log(Level level, String msg) {
@@ -532,7 +534,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      * @param   param1  parameter to the message
      */
@@ -553,7 +555,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      * @param   params  array of parameters to the message
      */
@@ -578,7 +580,7 @@
      * processed specially by output Formatters and is not treated
      * as a formatting parameter to the LogRecord message property.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   msg     The string message (or a key in the message catalog)
      * @param   thrown  Throwable associated with log message.
      */
@@ -603,7 +605,7 @@
      * level then the given message is forwarded to all the
      * registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg     The string message (or a key in the message catalog)
@@ -626,7 +628,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg      The string message (or a key in the message catalog)
@@ -653,7 +655,7 @@
      * level then a corresponding LogRecord is created and forwarded
      * to all the registered output Handler objects.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg     The string message (or a key in the message catalog)
@@ -684,7 +686,7 @@
      * processed specially by output Formatters and is not treated
      * as a formatting parameter to the LogRecord message property.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   msg     The string message (or a key in the message catalog)
@@ -731,7 +733,7 @@
      * resource bundle name is null, or an empty String or invalid
      * then the msg string is not localized.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -762,7 +764,7 @@
      * resource bundle name is null, or an empty String or invalid
      * then the msg string is not localized.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -795,7 +797,7 @@
      * resource bundle name is null, or an empty String or invalid
      * then the msg string is not localized.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -832,7 +834,7 @@
      * processed specially by output Formatters and is not treated
      * as a formatting parameter to the LogRecord message property.
      * <p>
-     * @param   level   One of the message level identifiers, e.g. SEVERE
+     * @param   level   One of the message level identifiers, e.g., SEVERE
      * @param   sourceClass    name of class that issued the logging request
      * @param   sourceMethod   name of method that issued the logging request
      * @param   bundleName     name of resource bundle to localize msg,
@@ -1214,7 +1216,7 @@
 
     /**
      * Specify whether or not this logger should send its output
-     * to it's parent Logger.  This means that any LogRecords will
+     * to its parent Logger.  This means that any LogRecords will
      * also be written to the parent's Handlers, and potentially
      * to its parent, recursively up the namespace.
      *
--- a/jdk/src/share/classes/java/util/logging/LoggingMXBean.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/LoggingMXBean.java	Wed Jul 05 17:01:09 2017 +0200
@@ -105,8 +105,8 @@
      *
      * @param loggerName The name of the <tt>Logger</tt> to be set.
      *                   Must be non-null.
-     * @param levelName The name of the level to set the specified logger to,
-     *                 or <tt>null</tt> if to set the level to inherit
+     * @param levelName The name of the level to set on the specified logger,
+     *                 or <tt>null</tt> if setting the level to inherit
      *                 from its nearest ancestor.
      *
      * @throws IllegalArgumentException if the specified logger
--- a/jdk/src/share/classes/java/util/logging/MemoryHandler.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/MemoryHandler.java	Wed Jul 05 17:01:09 2017 +0200
@@ -136,7 +136,7 @@
      * @param size    the number of log records to buffer (must be greater than zero)
      * @param pushLevel  message level to push on
      *
-     * @throws IllegalArgumentException is size is <= 0
+     * @throws IllegalArgumentException if size is <= 0
      */
     public MemoryHandler(Handler target, int size, Level pushLevel) {
         if (target == null || pushLevel == null) {
@@ -258,7 +258,7 @@
      * This method checks if the <tt>LogRecord</tt> has an appropriate level and
      * whether it satisfies any <tt>Filter</tt>.  However it does <b>not</b>
      * check whether the <tt>LogRecord</tt> would result in a "push" of the
-     * buffer contents. It will return false if the <tt>LogRecord</tt> is Null.
+     * buffer contents. It will return false if the <tt>LogRecord</tt> is null.
      * <p>
      * @param record  a <tt>LogRecord</tt>
      * @return true if the <tt>LogRecord</tt> would be logged.
--- a/jdk/src/share/classes/java/util/logging/StreamHandler.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/logging/StreamHandler.java	Wed Jul 05 17:01:09 2017 +0200
@@ -220,7 +220,7 @@
      * <p>
      * This method checks if the <tt>LogRecord</tt> has an appropriate level and
      * whether it satisfies any <tt>Filter</tt>.  It will also return false if
-     * no output stream has been assigned yet or the LogRecord is Null.
+     * no output stream has been assigned yet or the LogRecord is null.
      * <p>
      * @param record  a <tt>LogRecord</tt>
      * @return true if the <tt>LogRecord</tt> would be logged.
--- a/jdk/src/share/classes/java/util/zip/ZipEntry.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/zip/ZipEntry.java	Wed Jul 05 17:01:09 2017 +0200
@@ -253,14 +253,10 @@
      * the first 0xFFFF bytes are output to the ZIP file entry.
      *
      * @param comment the comment string
-     * @exception IllegalArgumentException if the length of the specified
-     *            comment string is greater than 0xFFFF bytes
+     *
      * @see #getComment()
      */
     public void setComment(String comment) {
-        if (comment != null && comment.length() > 0xffff) {
-            throw new IllegalArgumentException("invalid entry comment length");
-        }
         this.comment = comment;
     }
 
--- a/jdk/src/share/classes/java/util/zip/ZipFile.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/java/util/zip/ZipFile.java	Wed Jul 05 17:01:09 2017 +0200
@@ -195,7 +195,10 @@
         if (charset == null)
             throw new NullPointerException("charset is null");
         this.zc = ZipCoder.get(charset);
+        long t0 = System.nanoTime();
         jzfile = open(name, mode, file.lastModified());
+        sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0);
+        sun.misc.PerfCounter.getZipFileCount().increment();
         this.name = name;
         this.total = getTotal(jzfile);
     }
--- a/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/javax/sql/rowset/BaseRowSet.java	Wed Jul 05 17:01:09 2017 +0200
@@ -168,8 +168,8 @@
  * The majority of methods for setting placeholder parameters take two parameters,
  *  with the first parameter
  * indicating which placeholder parameter is to be set, and the second parameter
- * giving the value to be set.  Methods such as <code>getInt</code>,
- * <code>getString</code>, <code>getBoolean</code>, and <code>getLong</code> fall into
+ * giving the value to be set.  Methods such as <code>setInt</code>,
+ * <code>setString</code>, <code>setBoolean</code>, and <code>setLong</code> fall into
  * this category.  After these methods have been called, a call to the method
  * <code>getParams</code> will return an array with the values that have been set. Each
  * element in the array is an <code>Object</code> instance representing the
@@ -3259,9 +3259,9 @@
     * @param x the parameter value
     * @exception SQLException if a database access error occurs or
     * this method is called on a closed <code>CallableStatement</code>
-    * @see #getBoolean
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
+    * @see #getParams
     * @since 1.4
     */
    public void setBoolean(String parameterName, boolean x) throws SQLException{
@@ -3281,7 +3281,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getByte
+    * @see #getParams
     * @since 1.4
     */
    public void setByte(String parameterName, byte x) throws SQLException{
@@ -3301,7 +3301,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getShort
+    * @see #getParams
     * @since 1.4
     */
    public void setShort(String parameterName, short x) throws SQLException{
@@ -3320,7 +3320,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getInt
+    * @see #getParams
     * @since 1.4
     */
    public void setInt(String parameterName, int x) throws SQLException{
@@ -3339,7 +3339,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getLong
+    * @see #getParams
     * @since 1.4
     */
    public void setLong(String parameterName, long x) throws SQLException{
@@ -3358,7 +3358,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getFloat
+    * @see #getParams
     * @since 1.4
     */
    public void setFloat(String parameterName, float x) throws SQLException{
@@ -3377,7 +3377,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getDouble
+    * @see #getParams
     * @since 1.4
     */
    public void setDouble(String parameterName, double x) throws SQLException{
@@ -3398,7 +3398,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getBigDecimal
+    * @see #getParams
     * @since 1.4
     */
    public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{
@@ -3421,7 +3421,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getString
+    * @see #getParams
     * @since 1.4
     */
    public void setString(String parameterName, String x) throws SQLException{
@@ -3443,7 +3443,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getBytes
+    * @see #getParams
     * @since 1.4
     */
    public void setBytes(String parameterName, byte x[]) throws SQLException{
@@ -3464,7 +3464,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTimestamp
+    * @see #getParams
     * @since 1.4
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x)
@@ -3712,7 +3712,7 @@
     * or  <code>STRUCT</code> data type and the JDBC driver does not support
     * this data type
     * @see Types
-    * @see #getObject
+    * @see #getParams
     * @since 1.4
     */
    public void setObject(String parameterName, Object x, int targetSqlType, int scale)
@@ -3740,7 +3740,7 @@
     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
     * or  <code>STRUCT</code> data type and the JDBC driver does not support
     * this data type
-    * @see #getObject
+    * @see #getParams
     * @since 1.4
     */
    public void setObject(String parameterName, Object x, int targetSqlType)
@@ -3782,7 +3782,7 @@
    *            <code>Object</code> parameter is ambiguous
    * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
    * this method
-   * @see #getObject
+   * @see #getParams
    * @since 1.4
    */
   public void setObject(String parameterName, Object x) throws SQLException{
@@ -4064,7 +4064,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getDate
+    * @see #getParams
     * @since 1.4
     */
    public void setDate(String parameterName, java.sql.Date x)
@@ -4091,7 +4091,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getDate
+    * @see #getParams
     * @since 1.4
     */
    public void setDate(String parameterName, java.sql.Date x, Calendar cal)
@@ -4111,7 +4111,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTime
+    * @see #getParams
     * @since 1.4
     */
    public void setTime(String parameterName, java.sql.Time x)
@@ -4138,7 +4138,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTime
+    * @see #getParams
     * @since 1.4
     */
    public void setTime(String parameterName, java.sql.Time x, Calendar cal)
@@ -4165,7 +4165,7 @@
     * this method is called on a closed <code>CallableStatement</code>
     * @exception SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
-    * @see #getTimestamp
+    * @see #getParams
     * @since 1.4
     */
    public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/misc/PerfCounter.java	Wed Jul 05 17:01:09 2017 +0200
@@ -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.misc;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.LongBuffer;
+import java.security.AccessController;
+
+/**
+ * Performance counter support for internal JRE classes.
+ * This class defines a fixed list of counters for the platform
+ * to use as an interim solution until RFE# 6209222 is implemented.
+ * The perf counters will be created in the jvmstat perf buffer
+ * that the HotSpot VM creates. The default size is 32K and thus
+ * the number of counters is bounded.  You can alter the size
+ * with -XX:PerfDataMemorySize=<bytes> option. If there is
+ * insufficient memory in the jvmstat perf buffer, the C heap memory
+ * will be used and thus the application will continue to run if
+ * the counters added exceeds the buffer size but the counters
+ * will be missing.
+ *
+ * See HotSpot jvmstat implementation for certain circumstances
+ * that the jvmstat perf buffer is not supported.
+ *
+ */
+public class PerfCounter {
+    private static final Perf perf =
+        AccessController.doPrivileged(new Perf.GetPerfAction());
+
+    // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp
+    private final static int V_Constant  = 1;
+    private final static int V_Monotonic = 2;
+    private final static int V_Variable  = 3;
+    private final static int U_None      = 1;
+
+    private final String name;
+    private final LongBuffer lb;
+
+    private PerfCounter(String name, int type) {
+        this.name = name;
+        ByteBuffer bb = perf.createLong(name, U_None, type, 0L);
+        bb.order(ByteOrder.nativeOrder());
+        this.lb = bb.asLongBuffer();
+    }
+
+    static PerfCounter newPerfCounter(String name) {
+        return new PerfCounter(name, V_Variable);
+    }
+
+    static PerfCounter newConstantPerfCounter(String name) {
+        PerfCounter c = new PerfCounter(name, V_Constant);
+        return c;
+    }
+
+    /**
+     * Returns the current value of the perf counter.
+     */
+    public synchronized long get() {
+        return lb.get(0);
+    }
+
+    /**
+     * Sets the value of the perf counter to the given newValue.
+     */
+    public synchronized void set(long newValue) {
+        lb.put(0, newValue);
+    }
+
+    /**
+     * Adds the given value to the perf counter.
+     */
+    public synchronized void add(long value) {
+        long res = get() + value;
+        lb.put(0, res);
+    }
+
+    /**
+     * Increments the perf counter with 1.
+     */
+    public void increment() {
+        add(1);
+    }
+
+    /**
+     * Adds the given interval to the perf counter.
+     */
+    public void addTime(long interval) {
+        add(interval);
+    }
+
+    /**
+     * Adds the elapsed time from the given start time (ns) to the perf counter.
+     */
+    public void addElapsedTimeFrom(long startTime) {
+        add(System.nanoTime() - startTime);
+    }
+
+    @Override
+    public String toString() {
+        return name + " = " + get();
+    }
+
+    static class CoreCounters {
+        static final PerfCounter pdt   = newPerfCounter("sun.classloader.parentDelegationTime");
+        static final PerfCounter lc    = newPerfCounter("sun.classloader.findClasses");
+        static final PerfCounter lct   = newPerfCounter("sun.classloader.findClassTime");
+        static final PerfCounter rcbt  = newPerfCounter("sun.urlClassLoader.readClassBytesTime");
+        static final PerfCounter zfc   = newPerfCounter("sun.zip.zipFiles");
+        static final PerfCounter zfot  = newPerfCounter("sun.zip.zipFile.openTime");
+    }
+
+    static class WindowsClientCounters {
+        static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available");
+    }
+
+    /**
+     * Number of findClass calls
+     */
+    public static PerfCounter getFindClasses() {
+        return CoreCounters.lc;
+    }
+
+    /**
+     * Time (ns) spent in finding classes that includes
+     * lookup and read class bytes and defineClass
+     */
+    public static PerfCounter getFindClassTime() {
+        return CoreCounters.lct;
+    }
+
+    /**
+     * Time (ns) spent in finding classes
+     */
+    public static PerfCounter getReadClassBytesTime() {
+        return CoreCounters.rcbt;
+    }
+
+    /**
+     * Time (ns) spent in the parent delegation to
+     * the parent of the defining class loader
+     */
+    public static PerfCounter getParentDelegationTime() {
+        return CoreCounters.pdt;
+    }
+
+    /**
+     * Number of zip files opened.
+     */
+    public static PerfCounter getZipFileCount() {
+        return CoreCounters.zfc;
+    }
+
+    /**
+     * Time (ns) spent in opening the zip files that
+     * includes building the entries hash table
+     */
+    public static PerfCounter getZipFileOpenTime() {
+        return CoreCounters.zfot;
+    }
+
+    /**
+     * D3D graphic pipeline available
+     */
+    public static PerfCounter getD3DAvailable() {
+        return WindowsClientCounters.d3dAvailable;
+    }
+}
--- a/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/spi/DefaultProxySelector.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2008 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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,11 +25,9 @@
 
 package sun.net.spi;
 
-import sun.net.www.http.*;
 import sun.net.NetProperties;
 import java.net.*;
 import java.util.*;
-import java.util.regex.*;
 import java.io.*;
 import sun.misc.RegexpPool;
 import java.security.AccessController;
@@ -102,17 +100,22 @@
      */
 
     static class NonProxyInfo {
+        // Default value for nonProxyHosts, this provides backward compatibility
+        // by excluding localhost and its litteral notations.
+        static final String defStringVal = "localhost|127.*|[::1]";
+
         String hostsSource;
         RegexpPool hostsPool;
-        String property;
+        final String property;
+        final String defaultVal;
+        static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal);
+        static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal);
 
-        static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null);
-        static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null);
-
-        NonProxyInfo(String p, String s, RegexpPool pool) {
+        NonProxyInfo(String p, String s, RegexpPool pool, String d) {
             property = p;
             hostsSource = s;
             hostsPool = pool;
+            defaultVal = d;
         }
     }
 
@@ -130,7 +133,6 @@
         }
         String protocol = uri.getScheme();
         String host = uri.getHost();
-        int port = uri.getPort();
 
         if (host == null) {
             // This is a hack to ensure backward compatibility in two
@@ -149,11 +151,6 @@
                 }
                 i = auth.lastIndexOf(':');
                 if (i >= 0) {
-                    try {
-                        port = Integer.parseInt(auth.substring(i+1));
-                    } catch (NumberFormatException e) {
-                        port = -1;
-                    }
                     auth = auth.substring(0,i);
                 }
                 host = auth;
@@ -165,13 +162,6 @@
         }
         List<Proxy> proxyl = new ArrayList<Proxy>(1);
 
-        // special case localhost and loopback addresses to
-        // not go through proxy
-        if (isLoopback(host)) {
-            proxyl.add(Proxy.NO_PROXY);
-            return proxyl;
-        }
-
         NonProxyInfo pinfo = null;
 
         if ("http".equalsIgnoreCase(protocol)) {
@@ -244,9 +234,14 @@
                                 nphosts = NetProperties.get(nprop.property);
                                 synchronized (nprop) {
                                     if (nphosts == null) {
-                                        nprop.hostsSource = null;
-                                        nprop.hostsPool = null;
-                                    } else {
+                                        if (nprop.defaultVal != null) {
+                                            nphosts = nprop.defaultVal;
+                                        } else {
+                                            nprop.hostsSource = null;
+                                            nprop.hostsPool = null;
+                                        }
+                                    }
+                                    if (nphosts != null) {
                                         if (!nphosts.equals(nprop.hostsSource)) {
                                             RegexpPool pool = new RegexpPool();
                                             StringTokenizer st = new StringTokenizer(nphosts, "|", false);
@@ -334,107 +329,6 @@
         }
     }
 
-    private boolean isLoopback(String host) {
-        if (host == null || host.length() == 0)
-            return false;
-
-        if (host.equalsIgnoreCase("localhost"))
-            return true;
-
-        /* The string could represent a numerical IP address.
-         * For IPv4 addresses, check whether it starts with 127.
-         * For IPv6 addresses, check whether it is ::1 or its equivalent.
-         * Don't check IPv4-mapped or IPv4-compatible addresses
-         */
-
-        if (host.startsWith("127.")) {
-            // possible IPv4 loopback address
-            int p = 4;
-            int q;
-            int n = host.length();
-            // Per RFC2732: At most three digits per byte
-            // Further constraint: Each element fits in a byte
-            if ((q = scanByte(host, p, n)) <= p) return false;   p = q;
-            if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0;  p = q;
-            if ((q = scanByte(host, p, n)) <= p) return false;   p = q;
-            if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0;  p = q;
-            if ((q = scanByte(host, p, n)) <= p) return false;
-            return q == n && number > 0;
-        }
-
-        if (host.endsWith(":1")) {
-            final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1");
-            return p6.matcher(host).matches();
-        }
-        return false;
-    }
-
-    // Character-class masks, in reverse order from RFC2396 because
-    // initializers for static fields cannot make forward references.
-
-    // Compute a low-order mask for the characters
-    // between first and last, inclusive
-    private static long lowMask(char first, char last) {
-        long m = 0;
-        int f = Math.max(Math.min(first, 63), 0);
-        int l = Math.max(Math.min(last, 63), 0);
-        for (int i = f; i <= l; i++)
-            m |= 1L << i;
-        return m;
-    }
-    // digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
-    //            "8" | "9"
-    private static final long L_DIGIT = lowMask('0', '9');
-    private static final long H_DIGIT = 0L;
-
-    // Scan a string of decimal digits whose value fits in a byte
-    //
-    private int number;
-    private int scanByte(String input, int start, int n)
-    {
-        int p = start;
-        int q = scan(input, p, n, L_DIGIT, H_DIGIT);
-        if (q <= p) return q;
-        number = Integer.parseInt(input.substring(p, q));
-        if (number > 255) return p;
-        return q;
-    }
-
-    // Scan a specific char: If the char at the given start position is
-    // equal to c, return the index of the next char; otherwise, return the
-    // start position.
-    //
-    private int scan(String input, int start, int end, char c) {
-        if ((start < end) && (input.charAt(start) == c))
-            return start + 1;
-        return start;
-    }
-
-    // Scan chars that match the given mask pair
-    //
-    private int scan(String input, int start, int n, long lowMask, long highMask)
-    {
-        int p = start;
-        while (p < n) {
-            char c = input.charAt(p);
-            if (match(c, lowMask, highMask)) {
-                p++;
-                continue;
-            }
-            break;
-        }
-        return p;
-    }
-
-    // Tell whether the given character is permitted by the given mask pair
-    private boolean match(char c, long lowMask, long highMask) {
-        if (c < 64)
-            return ((1L << c) & lowMask) != 0;
-        if (c < 128)
-            return ((1L << (c - 64)) & highMask) != 0;
-        return false;
-    }
-
     private native static boolean init();
     private native Proxy getSystemProxy(String protocol, String host);
 }
--- a/jdk/src/share/classes/sun/net/www/http/HttpCapture.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/HttpCapture.java	Wed Jul 05 17:01:09 2017 +0200
@@ -24,14 +24,12 @@
  */
 
 package sun.net.www.http;
+
 import java.io.*;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import java.util.regex.*;
 import sun.net.NetProperties;
-import java.util.regex.*;
+import sun.util.logging.PlatformLogger;
 
 /**
  * Main class of the HTTP traffic capture tool.
@@ -62,76 +60,6 @@
     private static boolean initialized = false;
     private static volatile ArrayList<Pattern> patterns = null;
     private static volatile ArrayList<String> capFiles = null;
-    /* Logging is done in an ugly way so that it does not require the presence
-     * the java.util.logging package. If the Logger class is not available, then
-     * logging is turned off. This is for helping the modularization effort.
-     */
-    private static Object logger = null;
-    private static boolean logging = false;
-
-    static {
-        Class cl;
-        try {
-            cl = Class.forName("java.util.logging.Logger");
-        } catch (ClassNotFoundException ex) {
-            cl = null;
-        }
-        if (cl != null) {
-            try {
-                Method m = cl.getMethod("getLogger", String.class);
-                logger = m.invoke(null, "sun.net.www.protocol.http.HttpURLConnection");
-                logging = true;
-            } catch (NoSuchMethodException noSuchMethodException) {
-            } catch (SecurityException securityException) {
-            } catch (IllegalAccessException illegalAccessException) {
-            } catch (IllegalArgumentException illegalArgumentException) {
-            } catch (InvocationTargetException invocationTargetException) {
-            }
-        }
-    }
-
-    public static void fine(String s) {
-        if (logging) {
-            ((Logger)logger).fine(s);
-        }
-    }
-
-    public static void finer(String s) {
-        if (logging) {
-            ((Logger)logger).finer(s);
-        }
-    }
-
-    public static void finest(String s) {
-        if (logging) {
-            ((Logger)logger).finest(s);
-        }
-    }
-
-    public static void severe(String s) {
-        if (logging) {
-            ((Logger)logger).finest(s);
-        }
-    }
-
-    public static void info(String s) {
-        if (logging) {
-            ((Logger)logger).info(s);
-        }
-    }
-
-    public static void warning(String s) {
-        if (logging) {
-            ((Logger)logger).warning(s);
-        }
-    }
-
-    public static boolean isLoggable(String level) {
-        if (!logging) {
-            return false;
-        }
-        return ((Logger)logger).isLoggable(Level.parse(level));
-    }
 
     private static synchronized void init() {
         initialized = true;
@@ -187,7 +115,7 @@
             out = new BufferedWriter(new FileWriter(file, true));
             out.write("URL: " + url + "\n");
         } catch (IOException ex) {
-            Logger.getLogger(HttpCapture.class.getName()).log(Level.SEVERE, null, ex);
+            PlatformLogger.getLogger(HttpCapture.class.getName()).severe(null, ex);
         }
     }
 
--- a/jdk/src/share/classes/sun/net/www/http/HttpClient.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/HttpClient.java	Wed Jul 05 17:01:09 2017 +0200
@@ -35,6 +35,7 @@
 import sun.net.www.MeteredStream;
 import sun.net.www.ParseUtil;
 import sun.net.www.protocol.http.HttpURLConnection;
+import sun.util.logging.PlatformLogger;
 
 /**
  * @author Herb Jellinek
@@ -804,8 +805,9 @@
 
             if (isKeepingAlive())   {
                 // Wrap KeepAliveStream if keep alive is enabled.
-                if (HttpCapture.isLoggable("FINEST")) {
-                    HttpCapture.finest("KeepAlive stream used: " + url);
+                PlatformLogger logger = HttpURLConnection.getHttpLogger();
+                if (logger.isLoggable(PlatformLogger.FINEST)) {
+                    logger.finest("KeepAlive stream used: " + url);
                 }
                 serverInput = new KeepAliveStream(serverInput, pi, cl, this);
                 failedOnce = false;
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveCache.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,12 +25,11 @@
 
 package sun.net.www.http;
 
-import java.io.InputStream;
 import java.io.IOException;
 import java.io.NotSerializableException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.net.URL;
-import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * A class that implements a cache of idle Http connections for keep-alive
@@ -39,7 +38,7 @@
  * @author Dave Brown
  */
 public class KeepAliveCache
-    extends ConcurrentHashMap<KeepAliveKey, ClientVector>
+    extends HashMap<KeepAliveKey, ClientVector>
     implements Runnable {
     private static final long serialVersionUID = -2937172892064557949L;
 
@@ -163,8 +162,8 @@
      * Errs on the side of caution (leave connections idle for a relatively
      * short time).
      */
+    @Override
     public void run() {
-        int total_cache;
         do {
             try {
                 Thread.sleep(LIFETIME);
@@ -311,6 +310,7 @@
     /**
      * Determine whether or not two objects of this type are equal
      */
+    @Override
     public boolean equals(Object obj) {
         if ((obj instanceof KeepAliveKey) == false)
             return false;
@@ -325,6 +325,7 @@
      * The hashCode() for this object is the string hashCode() of
      * concatenation of the protocol, host name and port.
      */
+    @Override
     public int hashCode() {
         String str = protocol+host+port;
         return this.obj == null? str.hashCode() :
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStream.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,10 +25,7 @@
 
 package sun.net.www.http;
 
-import java.net.URL;
-import java.net.HttpURLConnection;
 import java.io.*;
-import java.util.StringTokenizer;
 import sun.net.ProgressSource;
 import sun.net.www.MeteredStream;
 
@@ -50,9 +47,8 @@
     // has this KeepAliveStream been put on the queue for asynchronous cleanup.
     protected boolean queuedForCleanup = false;
 
-    private static KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner();
-    private static Thread cleanerThread = null;
-    private static boolean startCleanupThread;
+    private static final KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner();
+    private static Thread cleanerThread; // null
 
     /**
      * Constructor
@@ -155,43 +151,46 @@
         }
     }
 
-    private static synchronized void queueForCleanup(KeepAliveCleanerEntry kace) {
-        if(queue != null && !kace.getQueuedForCleanup()) {
-            if (!queue.offer(kace)) {
-                kace.getHttpClient().closeServer();
-                return;
+    private static void queueForCleanup(KeepAliveCleanerEntry kace) {
+        synchronized(queue) {
+            if(!kace.getQueuedForCleanup()) {
+                if (!queue.offer(kace)) {
+                    kace.getHttpClient().closeServer();
+                    return;
+                }
+
+                kace.setQueuedForCleanup();
+                queue.notifyAll();
+            }
+
+            boolean startCleanupThread = (cleanerThread == null);
+            if (!startCleanupThread) {
+                if (!cleanerThread.isAlive()) {
+                    startCleanupThread = true;
+                }
             }
 
-            kace.setQueuedForCleanup();
-        }
-
-        startCleanupThread = (cleanerThread == null);
-        if (!startCleanupThread) {
-            if (!cleanerThread.isAlive()) {
-                startCleanupThread = true;
-            }
-        }
+            if (startCleanupThread) {
+                java.security.AccessController.doPrivileged(
+                    new java.security.PrivilegedAction<Void>() {
+                    public Void run() {
+                        // We want to create the Keep-Alive-SocketCleaner in the
+                        // system threadgroup
+                        ThreadGroup grp = Thread.currentThread().getThreadGroup();
+                        ThreadGroup parent = null;
+                        while ((parent = grp.getParent()) != null) {
+                            grp = parent;
+                        }
 
-        if (startCleanupThread) {
-            java.security.AccessController.doPrivileged(
-                new java.security.PrivilegedAction<Void>() {
-                public Void run() {
-                    // We want to create the Keep-Alive-SocketCleaner in the
-                    // system threadgroup
-                    ThreadGroup grp = Thread.currentThread().getThreadGroup();
-                    ThreadGroup parent = null;
-                    while ((parent = grp.getParent()) != null) {
-                        grp = parent;
+                        cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner");
+                        cleanerThread.setDaemon(true);
+                        cleanerThread.setPriority(Thread.MAX_PRIORITY - 2);
+                        cleanerThread.start();
+                        return null;
                     }
-
-                    cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner");
-                    cleanerThread.setDaemon(true);
-                    cleanerThread.setPriority(Thread.MAX_PRIORITY - 2);
-                    cleanerThread.start();
-                    return null;
-                }
-            });
-        }
+                });
+            }
+        } // queue
     }
 
     protected long remainingToRead() {
--- a/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,9 +25,8 @@
 
 package sun.net.www.http;
 
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
 import java.io.IOException;
+import java.util.LinkedList;
 import sun.net.NetProperties;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -44,7 +43,9 @@
  */
 
 @SuppressWarnings("serial")  // never serialized
-public class KeepAliveStreamCleaner extends LinkedBlockingQueue<KeepAliveCleanerEntry> implements Runnable
+class KeepAliveStreamCleaner
+    extends LinkedList<KeepAliveCleanerEntry>
+    implements Runnable
 {
     // maximum amount of remaining data that we will try to cleanup
     protected static int MAX_DATA_REMAINING = 512;
@@ -78,23 +79,39 @@
     }
 
 
-    public KeepAliveStreamCleaner()
-    {
-        super(MAX_CAPACITY);
+    @Override
+    public boolean offer(KeepAliveCleanerEntry e) {
+        if (size() >= MAX_CAPACITY)
+            return false;
+
+        return super.offer(e);
     }
 
-    public KeepAliveStreamCleaner(int capacity)
-    {
-        super(capacity);
-    }
-
+    @Override
     public void run()
     {
         KeepAliveCleanerEntry kace = null;
 
         do {
             try {
-                kace = poll((long)TIMEOUT, TimeUnit.MILLISECONDS);
+                synchronized(this) {
+                    long before = System.currentTimeMillis();
+                    long timeout = TIMEOUT;
+                    while ((kace = poll()) == null) {
+                        this.wait(timeout);
+
+                        long after = System.currentTimeMillis();
+                        long elapsed = after - before;
+                        if (elapsed > timeout) {
+                            /* one last try */
+                            kace = poll();
+                            break;
+                        }
+                        before = after;
+                        timeout -= elapsed;
+                    }
+                }
+
                 if(kace == null)
                     break;
 
--- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthCache.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthCache.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,14 +25,6 @@
 
 package sun.net.www.protocol.http;
 
-import java.io.IOException;
-import java.net.URL;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Enumeration;
-import java.util.HashMap;
-
 /**
  * @author Michael McMahon
  *
@@ -49,7 +41,7 @@
      * A:[B:]C:D:E[:F]   Between 4 and 6 fields separated by ":"
      *          where the fields have the following meaning:
      * A is "s" or "p" for server or proxy authentication respectively
-     * B is optional and is "D", "B", or "N" for digest, basic or ntlm auth.
+     * B is optional and is the {@link AuthScheme}, e.g. BASIC, DIGEST, NTLM, etc
      * C is either "http" or "https"
      * D is the hostname
      * E is the port number
--- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,15 +25,8 @@
 
 package sun.net.www.protocol.http;
 
-import java.io.IOException;
 import java.io.Serializable;
-import java.net.*;
-import java.util.Hashtable;
-import java.util.LinkedList;
-import java.util.ListIterator;
-import java.util.Enumeration;
-import java.util.HashMap;
-
+import java.net.PasswordAuthentication;
 
 /**
  * AuthCacheValue: interface to minimise exposure to authentication cache
@@ -62,8 +55,16 @@
 
     AuthCacheValue() {}
 
+    /**
+     * Proxy or Server
+     */
     abstract Type getAuthType ();
 
+    /**
+     * Authentication scheme
+     */
+    abstract AuthScheme getAuthScheme();
+
    /**
     * name of server/proxy
     */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthScheme.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,38 @@
+/*
+ * 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.www.protocol.http;
+
+/* Authentication schemes supported by the http implementation. New schemes, if
+ * supported, should be defined here.
+ */
+public enum AuthScheme {
+    BASIC,
+    DIGEST,
+    NTLM,
+    NEGOTIATE,
+    KERBEROS,
+    UNKNOWN;
+}
+
--- a/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java	Wed Jul 05 17:01:09 2017 +0200
@@ -85,6 +85,11 @@
             AuthCacheValue.Type.Server:
             AuthCacheValue.Type.Proxy;
     }
+
+    AuthScheme getAuthScheme() {
+        return authScheme;
+    }
+
     public String getHost() {
         return host;
     }
@@ -151,7 +156,7 @@
     }
 
     //public String toString () {
-        //return ("{"+type+":"+authType+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
+        //return ("{"+type+":"+authScheme+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}");
     //}
 
     // REMIND:  This cache just grows forever.  We should put in a bounded
@@ -160,8 +165,8 @@
     /** The type (server/proxy) of authentication this is.  Used for key lookup */
     char type;
 
-    /** The authentication type (basic/digest). Also used for key lookup */
-    char authType;
+    /** The authentication scheme (basic/digest). Also used for key lookup */
+    AuthScheme authScheme;
 
     /** The protocol/scheme (i.e. http or https ). Need to keep the caches
      *  logically separate for the two protocols. This field is only used
@@ -183,9 +188,9 @@
     String path;
 
     /** Use this constructor only for proxy entries */
-    AuthenticationInfo(char type, char authType, String host, int port, String realm) {
+    AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
         this.type = type;
-        this.authType = authType;
+        this.authScheme = authScheme;
         this.protocol = "";
         this.host = host.toLowerCase();
         this.port = port;
@@ -206,9 +211,9 @@
      * Constructor used to limit the authorization to the path within
      * the URL. Use this constructor for origin server entries.
      */
-    AuthenticationInfo(char type, char authType, URL url, String realm) {
+    AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
         this.type = type;
-        this.authType = authType;
+        this.authScheme = authScheme;
         this.protocol = url.getProtocol().toLowerCase();
         this.host = url.getHost().toLowerCase();
         this.port = url.getPort();
@@ -264,12 +269,12 @@
      * In this case we do not use the path because the protection space
      * is identified by the host:port:realm only
      */
-    static AuthenticationInfo getServerAuth(URL url, String realm, char atype) {
+    static AuthenticationInfo getServerAuth(URL url, String realm, AuthScheme scheme) {
         int port = url.getPort();
         if (port == -1) {
             port = url.getDefaultPort();
         }
-        String key = SERVER_AUTHENTICATION + ":" + atype + ":" + url.getProtocol().toLowerCase()
+        String key = SERVER_AUTHENTICATION + ":" + scheme + ":" + url.getProtocol().toLowerCase()
                      + ":" + url.getHost().toLowerCase() + ":" + port + ":" + realm;
         AuthenticationInfo cached = getAuth(key, null);
         if ((cached == null) && requestIsInProgress (key)) {
@@ -308,8 +313,8 @@
      * Used in response to a challenge. Note, the protocol field is always
      * blank for proxies.
      */
-    static AuthenticationInfo getProxyAuth(String host, int port, String realm, char atype) {
-        String key = PROXY_AUTHENTICATION + ":" + atype + "::" + host.toLowerCase()
+    static AuthenticationInfo getProxyAuth(String host, int port, String realm, AuthScheme scheme) {
+        String key = PROXY_AUTHENTICATION + ":" + scheme + "::" + host.toLowerCase()
                         + ":" + port + ":" + realm;
         AuthenticationInfo cached = (AuthenticationInfo) cache.get(key, null);
         if ((cached == null) && requestIsInProgress (key)) {
@@ -409,7 +414,7 @@
         // This must be kept in sync with the getXXXAuth() methods in this
         // class.
         if (includeRealm) {
-            return type + ":" + authType + ":" + protocol + ":"
+            return type + ":" + authScheme + ":" + protocol + ":"
                         + host + ":" + port + ":" + realm;
         } else {
             return type + ":" + protocol + ":" + host + ":" + port;
--- a/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java	Wed Jul 05 17:01:09 2017 +0200
@@ -44,8 +44,6 @@
 
     private static final long serialVersionUID = 100L;
 
-    static final char BASIC_AUTH = 'B';
-
     /** The authentication string for this host, port, and realm.  This is
         a simple BASE64 encoding of "login:password".    */
     String auth;
@@ -56,7 +54,7 @@
     public BasicAuthentication(boolean isProxy, String host, int port,
                                String realm, PasswordAuthentication pw) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, host, port, realm);
+              AuthScheme.BASIC, host, port, realm);
         String plain = pw.getUserName() + ":";
         byte[] nameBytes = null;
         try {
@@ -86,7 +84,7 @@
     public BasicAuthentication(boolean isProxy, String host, int port,
                                String realm, String auth) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, host, port, realm);
+              AuthScheme.BASIC, host, port, realm);
         this.auth = "Basic " + auth;
     }
 
@@ -96,7 +94,7 @@
     public BasicAuthentication(boolean isProxy, URL url, String realm,
                                    PasswordAuthentication pw) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, url, realm);
+              AuthScheme.BASIC, url, realm);
         String plain = pw.getUserName() + ":";
         byte[] nameBytes = null;
         try {
@@ -126,7 +124,7 @@
     public BasicAuthentication(boolean isProxy, URL url, String realm,
                                    String auth) {
         super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
-              BASIC_AUTH, url, realm);
+              AuthScheme.BASIC, url, realm);
         this.auth = "Basic " + auth;
     }
 
--- a/jdk/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java	Wed Jul 05 17:01:09 2017 +0200
@@ -38,7 +38,6 @@
 import java.security.NoSuchAlgorithmException;
 import static sun.net.www.protocol.http.HttpURLConnection.HTTP_CONNECT;
 
-
 /**
  * DigestAuthentication: Encapsulate an http server authentication using
  * the "Digest" scheme, as described in RFC2069 and updated in RFC2617
@@ -50,8 +49,6 @@
 
     private static final long serialVersionUID = 100L;
 
-    static final char DIGEST_AUTH = 'D';
-
     private String authMethod;
 
     // Authentication parameters defined in RFC2617.
@@ -178,7 +175,10 @@
     public DigestAuthentication(boolean isProxy, URL url, String realm,
                                 String authMethod, PasswordAuthentication pw,
                                 Parameters params) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,url, realm);
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              AuthScheme.DIGEST,
+              url,
+              realm);
         this.authMethod = authMethod;
         this.pw = pw;
         this.params = params;
@@ -187,7 +187,11 @@
     public DigestAuthentication(boolean isProxy, String host, int port, String realm,
                                 String authMethod, PasswordAuthentication pw,
                                 Parameters params) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,host, port, realm);
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              AuthScheme.DIGEST,
+              host,
+              port,
+              realm);
         this.authMethod = authMethod;
         this.pw = pw;
         this.params = params;
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java	Wed Jul 05 17:01:09 2017 +0200
@@ -49,8 +49,10 @@
 
     @Override
     public String format(LogRecord record) {
-        if (!"sun.net.www.http.HttpCapture".equalsIgnoreCase(record.getSourceClassName())) {
-            // Don't change format for stuff that doesn't concern us
+        String sourceClassName = record.getSourceClassName();
+        if (sourceClassName == null ||
+            !(sourceClassName.startsWith("sun.net.www.protocol.http") ||
+              sourceClassName.startsWith("sun.net.www.http"))) {
             return super.format(record);
         }
         String src = record.getMessage();
--- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java	Wed Jul 05 17:01:09 2017 +0200
@@ -57,11 +57,17 @@
 import sun.net.www.http.PosterOutputStream;
 import sun.net.www.http.ChunkedInputStream;
 import sun.net.www.http.ChunkedOutputStream;
-import sun.net.www.http.HttpCapture;
+import sun.util.logging.PlatformLogger;
 import java.text.SimpleDateFormat;
 import java.util.TimeZone;
 import java.net.MalformedURLException;
 import java.nio.ByteBuffer;
+import static sun.net.www.protocol.http.AuthScheme.BASIC;
+import static sun.net.www.protocol.http.AuthScheme.DIGEST;
+import static sun.net.www.protocol.http.AuthScheme.NTLM;
+import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
+import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
+import static sun.net.www.protocol.http.AuthScheme.UNKNOWN;
 
 /**
  * A class to represent an HTTP connection to a remote object.
@@ -231,9 +237,11 @@
     boolean             needToCheck = true;
     private boolean doingNTLM2ndStage = false; /* doing the 2nd stage of an NTLM server authentication */
     private boolean doingNTLMp2ndStage = false; /* doing the 2nd stage of an NTLM proxy authentication */
-    /* try auth without calling Authenticator */
-    private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth();
-    private boolean tryTransparentNTLMProxy = NTLMAuthentication.supportsTransparentAuth();
+
+    /* try auth without calling Authenticator. Used for transparent NTLM authentication */
+    private boolean tryTransparentNTLMServer = true;
+    private boolean tryTransparentNTLMProxy = true;
+
     /* Used by Windows specific code */
     Object authObj;
 
@@ -284,6 +292,10 @@
     private int connectTimeout = -1;
     private int readTimeout = -1;
 
+    /* Logging support */
+    private static final PlatformLogger logger =
+            PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
+
     /*
      * privileged request password authentication
      *
@@ -301,20 +313,25 @@
         return java.security.AccessController.doPrivileged(
             new java.security.PrivilegedAction<PasswordAuthentication>() {
                 public PasswordAuthentication run() {
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Requesting Authentication: host =" + host + " url = " + url);
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Requesting Authentication: host =" + host + " url = " + url);
                     }
                     PasswordAuthentication pass = Authenticator.requestPasswordAuthentication(
                         host, addr, port, protocol,
                         prompt, scheme, url, authType);
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null"));
                     }
                     return pass;
                 }
             });
     }
 
+    /* Logging support */
+    public static PlatformLogger getHttpLogger() {
+        return logger;
+    }
+
     /*
      * checks the validity of http message header and throws
      * IllegalArgumentException if invalid.
@@ -463,8 +480,8 @@
 
             setRequests=true;
         }
-        if (HttpCapture.isLoggable("FINE")) {
-            HttpCapture.fine(requests.toString());
+        if (logger.isLoggable(PlatformLogger.FINE)) {
+            logger.fine(requests.toString());
         }
         http.writeRequests(requests, poster);
         if (ps.checkError()) {
@@ -728,9 +745,9 @@
                         && !(cachedResponse instanceof SecureCacheResponse)) {
                         cachedResponse = null;
                     }
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Cache Request for " + uri + " / " + getRequestMethod());
-                        HttpCapture.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Cache Request for " + uri + " / " + getRequestMethod());
+                        logger.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null"));
                     }
                     if (cachedResponse != null) {
                         cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders());
@@ -769,8 +786,8 @@
                              });
                 if (sel != null) {
                     URI uri = sun.net.www.ParseUtil.toURI(url);
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("ProxySelector Request for " + uri);
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("ProxySelector Request for " + uri);
                     }
                     Iterator<Proxy> it = sel.select(uri).iterator();
                     Proxy p;
@@ -786,9 +803,9 @@
                                 http = getNewHttpClient(url, p, connectTimeout, false);
                                 http.setReadTimeout(readTimeout);
                             }
-                            if (HttpCapture.isLoggable("FINEST")) {
+                            if (logger.isLoggable(PlatformLogger.FINEST)) {
                                 if (p != null) {
-                                    HttpCapture.finest("Proxy used: " + p.toString());
+                                    logger.finest("Proxy used: " + p.toString());
                                 }
                             }
                             break;
@@ -1018,15 +1035,15 @@
 
             URI uri = ParseUtil.toURI(url);
             if (uri != null) {
-                if (HttpCapture.isLoggable("FINEST")) {
-                    HttpCapture.finest("CookieHandler request for " + uri);
+                if (logger.isLoggable(PlatformLogger.FINEST)) {
+                    logger.finest("CookieHandler request for " + uri);
                 }
                 Map<String, List<String>> cookies
                     = cookieHandler.get(
                         uri, requests.getHeaders(EXCLUDE_HEADERS));
                 if (!cookies.isEmpty()) {
-                    if (HttpCapture.isLoggable("FINEST")) {
-                        HttpCapture.finest("Cookies retrieved: " + cookies.toString());
+                    if (logger.isLoggable(PlatformLogger.FINEST)) {
+                        logger.finest("Cookies retrieved: " + cookies.toString());
                     }
                     for (Map.Entry<String, List<String>> entry :
                              cookies.entrySet()) {
@@ -1157,8 +1174,8 @@
                     writeRequests();
                 }
                 http.parseHTTP(responses, pi, this);
-                if (HttpCapture.isLoggable("FINE")) {
-                    HttpCapture.fine(responses.toString());
+                if (logger.isLoggable(PlatformLogger.FINE)) {
+                    logger.fine(responses.toString());
                 }
                 inputStream = http.getInputStream();
 
@@ -1270,7 +1287,7 @@
                     String raw = srvHdr.raw();
                     if (!doingNTLM2ndStage) {
                         if ((serverAuthentication != null)&&
-                            !(serverAuthentication instanceof NTLMAuthentication)) {
+                            serverAuthentication.getAuthScheme() != NTLM) {
                             if (serverAuthentication.isAuthorizationStale (raw)) {
                                 /* we can retry with the current credentials */
                                 disconnectInternal();
@@ -1523,8 +1540,8 @@
      */
     private AuthenticationInfo
         resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) {
-        if ((proxyAuthentication != null )&& ! (proxyAuthentication instanceof
-                                                        NTLMAuthentication)) {
+        if ((proxyAuthentication != null )&&
+             proxyAuthentication.getAuthScheme() != NTLM) {
             String raw = auth.raw();
             if (proxyAuthentication.isAuthorizationStale (raw)) {
                 /* we can retry with the current credentials */
@@ -1602,8 +1619,8 @@
                 http.parseHTTP(responses, null, this);
 
                 /* Log the response to the CONNECT */
-                if (HttpCapture.isLoggable("FINE")) {
-                    HttpCapture.fine(responses.toString());
+                if (logger.isLoggable(PlatformLogger.FINE)) {
+                    logger.fine(responses.toString());
                 }
 
                 statusLine = responses.getValue(0);
@@ -1730,8 +1747,8 @@
         setPreemptiveProxyAuthentication(requests);
 
          /* Log the CONNECT request */
-        if (HttpCapture.isLoggable("FINE")) {
-            HttpCapture.fine(requests.toString());
+        if (logger.isLoggable(PlatformLogger.FINE)) {
+            logger.fine(requests.toString());
         }
 
         http.writeRequests(requests, null);
@@ -1776,28 +1793,31 @@
             HeaderParser p = authhdr.headerParser();
             String realm = p.findValue("realm");
             String scheme = authhdr.scheme();
-            char schemeID;
+            AuthScheme authScheme = UNKNOWN;
             if ("basic".equalsIgnoreCase(scheme)) {
-                schemeID = BasicAuthentication.BASIC_AUTH;
+                authScheme = BASIC;
             } else if ("digest".equalsIgnoreCase(scheme)) {
-                schemeID = DigestAuthentication.DIGEST_AUTH;
+                authScheme = DIGEST;
             } else if ("ntlm".equalsIgnoreCase(scheme)) {
-                schemeID = NTLMAuthentication.NTLM_AUTH;
+                authScheme = NTLM;
                 doingNTLMp2ndStage = true;
             } else if ("Kerberos".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.KERBEROS_AUTH;
+                authScheme = KERBEROS;
                 doingNTLMp2ndStage = true;
             } else if ("Negotiate".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.NEGOTIATE_AUTH;
+                authScheme = NEGOTIATE;
                 doingNTLMp2ndStage = true;
-            } else {
-                schemeID = 0;
             }
+
             if (realm == null)
                 realm = "";
-            ret = AuthenticationInfo.getProxyAuth(host, port, realm, schemeID);
+            ret = AuthenticationInfo.getProxyAuth(host,
+                                                  port,
+                                                  realm,
+                                                  authScheme);
             if (ret == null) {
-                if (schemeID == BasicAuthentication.BASIC_AUTH) {
+                switch (authScheme) {
+                case BASIC:
                     InetAddress addr = null;
                     try {
                         final String finalHost = host;
@@ -1818,9 +1838,9 @@
                     if (a != null) {
                         ret = new BasicAuthentication(true, host, port, realm, a);
                     }
-                } else if (schemeID == DigestAuthentication.DIGEST_AUTH) {
-                    PasswordAuthentication a =
-                        privilegedRequestPasswordAuthentication(
+                    break;
+                case DIGEST:
+                    a = privilegedRequestPasswordAuthentication(
                                     host, null, port, url.getProtocol(),
                                     realm, scheme, url, RequestorType.PROXY);
                     if (a != null) {
@@ -1829,29 +1849,49 @@
                         ret = new DigestAuthentication(true, host, port, realm,
                                                             scheme, a, params);
                     }
-                } else if (schemeID == NTLMAuthentication.NTLM_AUTH) {
-                    PasswordAuthentication a = null;
-                    if (!tryTransparentNTLMProxy) {
-                        a = privilegedRequestPasswordAuthentication(
-                                            host, null, port, url.getProtocol(),
-                                            "", scheme, url, RequestorType.PROXY);
+                    break;
+                case NTLM:
+                    if (NTLMAuthenticationProxy.proxy.supported) {
+                        /* tryTransparentNTLMProxy will always be true the first
+                         * time around, but verify that the platform supports it
+                         * otherwise don't try. */
+                        if (tryTransparentNTLMProxy) {
+                            tryTransparentNTLMProxy =
+                                    NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
+                        }
+                        a = null;
+                        if (tryTransparentNTLMProxy) {
+                            logger.finest("Trying Transparent NTLM authentication");
+                        } else {
+                            a = privilegedRequestPasswordAuthentication(
+                                                host, null, port, url.getProtocol(),
+                                                "", scheme, url, RequestorType.PROXY);
+                        }
+                        /* If we are not trying transparent authentication then
+                         * we need to have a PasswordAuthentication instance. For
+                         * transparent authentication (Windows only) the username
+                         * and password will be picked up from the current logged
+                         * on users credentials.
+                        */
+                        if (tryTransparentNTLMProxy ||
+                              (!tryTransparentNTLMProxy && a != null)) {
+                            ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a);
+                        }
+
+                        /* set to false so that we do not try again */
+                        tryTransparentNTLMProxy = false;
                     }
-                    /* If we are not trying transparent authentication then
-                     * we need to have a PasswordAuthentication instance. For
-                     * transparent authentication (Windows only) the username
-                     * and password will be picked up from the current logged
-                     * on users credentials.
-                    */
-                    if (tryTransparentNTLMProxy ||
-                          (!tryTransparentNTLMProxy && a != null)) {
-                        ret = new NTLMAuthentication(true, host, port, a);
-                    }
-
-                    tryTransparentNTLMProxy = false;
-                } else if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
+                    break;
+                case NEGOTIATE:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
-                } else if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
+                    break;
+                case KERBEROS:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
+                    break;
+                case UNKNOWN:
+                    logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
+                default:
+                    throw new AssertionError("should not reach here");
                 }
             }
             // For backwards compatibility, we also try defaultAuth
@@ -1875,8 +1915,8 @@
                 }
             }
         }
-        if (HttpCapture.isLoggable("FINER")) {
-            HttpCapture.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
+        if (logger.isLoggable(PlatformLogger.FINER)) {
+            logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
         }
         return ret;
     }
@@ -1896,27 +1936,26 @@
             HeaderParser p = authhdr.headerParser();
             String realm = p.findValue("realm");
             String scheme = authhdr.scheme();
-            char schemeID;
+            AuthScheme authScheme = UNKNOWN;
             if ("basic".equalsIgnoreCase(scheme)) {
-                schemeID = BasicAuthentication.BASIC_AUTH;
+                authScheme = BASIC;
             } else if ("digest".equalsIgnoreCase(scheme)) {
-                schemeID = DigestAuthentication.DIGEST_AUTH;
+                authScheme = DIGEST;
             } else if ("ntlm".equalsIgnoreCase(scheme)) {
-                schemeID = NTLMAuthentication.NTLM_AUTH;
+                authScheme = NTLM;
                 doingNTLM2ndStage = true;
             } else if ("Kerberos".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.KERBEROS_AUTH;
+                authScheme = KERBEROS;
                 doingNTLM2ndStage = true;
             } else if ("Negotiate".equalsIgnoreCase(scheme)) {
-                schemeID = NegotiateAuthentication.NEGOTIATE_AUTH;
+                authScheme = NEGOTIATE;
                 doingNTLM2ndStage = true;
-            } else {
-                schemeID = 0;
             }
+
             domain = p.findValue ("domain");
             if (realm == null)
                 realm = "";
-            ret = AuthenticationInfo.getServerAuth(url, realm, schemeID);
+            ret = AuthenticationInfo.getServerAuth(url, realm, authScheme);
             InetAddress addr = null;
             if (ret == null) {
                 try {
@@ -1931,13 +1970,14 @@
                 port = url.getDefaultPort();
             }
             if (ret == null) {
-                if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) {
+                switch(authScheme) {
+                case KERBEROS:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos"));
-                }
-                if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) {
+                    break;
+                case NEGOTIATE:
                     ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate"));
-                }
-                if (schemeID == BasicAuthentication.BASIC_AUTH) {
+                    break;
+                case BASIC:
                     PasswordAuthentication a =
                         privilegedRequestPasswordAuthentication(
                             url.getHost(), addr, port, url.getProtocol(),
@@ -1945,45 +1985,60 @@
                     if (a != null) {
                         ret = new BasicAuthentication(false, url, realm, a);
                     }
-                }
-
-                if (schemeID == DigestAuthentication.DIGEST_AUTH) {
-                    PasswordAuthentication a =
-                        privilegedRequestPasswordAuthentication(
+                    break;
+                case DIGEST:
+                    a = privilegedRequestPasswordAuthentication(
                             url.getHost(), addr, port, url.getProtocol(),
                             realm, scheme, url, RequestorType.SERVER);
                     if (a != null) {
                         digestparams = new DigestAuthentication.Parameters();
                         ret = new DigestAuthentication(false, url, realm, scheme, a, digestparams);
                     }
-                }
+                    break;
+                case NTLM:
+                    if (NTLMAuthenticationProxy.proxy.supported) {
+                        URL url1;
+                        try {
+                            url1 = new URL (url, "/"); /* truncate the path */
+                        } catch (Exception e) {
+                            url1 = url;
+                        }
 
-                if (schemeID == NTLMAuthentication.NTLM_AUTH) {
-                    URL url1;
-                    try {
-                        url1 = new URL (url, "/"); /* truncate the path */
-                    } catch (Exception e) {
-                        url1 = url;
+                        /* tryTransparentNTLMServer will always be true the first
+                         * time around, but verify that the platform supports it
+                         * otherwise don't try. */
+                        if (tryTransparentNTLMServer) {
+                            tryTransparentNTLMServer =
+                                    NTLMAuthenticationProxy.proxy.supportsTransparentAuth;
+                        }
+                        a = null;
+                        if (tryTransparentNTLMServer) {
+                            logger.finest("Trying Transparent NTLM authentication");
+                        } else {
+                            a = privilegedRequestPasswordAuthentication(
+                                url.getHost(), addr, port, url.getProtocol(),
+                                "", scheme, url, RequestorType.SERVER);
+                        }
+
+                        /* If we are not trying transparent authentication then
+                         * we need to have a PasswordAuthentication instance. For
+                         * transparent authentication (Windows only) the username
+                         * and password will be picked up from the current logged
+                         * on users credentials.
+                         */
+                        if (tryTransparentNTLMServer ||
+                              (!tryTransparentNTLMServer && a != null)) {
+                            ret = NTLMAuthenticationProxy.proxy.create(false, url1, a);
+                        }
+
+                        /* set to false so that we do not try again */
+                        tryTransparentNTLMServer = false;
                     }
-                    PasswordAuthentication a = null;
-                    if (!tryTransparentNTLMServer) {
-                        a = privilegedRequestPasswordAuthentication(
-                            url.getHost(), addr, port, url.getProtocol(),
-                            "", scheme, url, RequestorType.SERVER);
-                    }
-
-                    /* If we are not trying transparent authentication then
-                     * we need to have a PasswordAuthentication instance. For
-                     * transparent authentication (Windows only) the username
-                     * and password will be picked up from the current logged
-                     * on users credentials.
-                     */
-                    if (tryTransparentNTLMServer ||
-                          (!tryTransparentNTLMServer && a != null)) {
-                        ret = new NTLMAuthentication(false, url1, a);
-                    }
-
-                    tryTransparentNTLMServer = false;
+                    break;
+                case UNKNOWN:
+                    logger.finest("Unknown/Unsupported authentication scheme: " + scheme);
+                default:
+                    throw new AssertionError("should not reach here");
                 }
             }
 
@@ -2005,8 +2060,8 @@
                 }
             }
         }
-        if (HttpCapture.isLoggable("FINER")) {
-            HttpCapture.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
+        if (logger.isLoggable(PlatformLogger.FINER)) {
+            logger.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null"));
         }
         return ret;
     }
@@ -2081,8 +2136,8 @@
         if (streaming()) {
             throw new HttpRetryException (RETRY_MSG3, stat, loc);
         }
-        if (HttpCapture.isLoggable("FINE")) {
-            HttpCapture.fine("Redirected from " + url + " to " + locUrl);
+        if (logger.isLoggable(PlatformLogger.FINE)) {
+            logger.fine("Redirected from " + url + " to " + locUrl);
         }
 
         // clear out old response headers!!!!
--- a/jdk/src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java	Mon Sep 28 19:38:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,393 +0,0 @@
-/*
- * Copyright 2005-2008 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.www.protocol.http;
-
-import java.net.URI;
-import java.net.CookieStore;
-import java.net.HttpCookie;
-import java.net.URISyntaxException;
-import java.util.List;
-import java.util.Map;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * A simple in-memory java.net.CookieStore implementation
- *
- * @author Edward Wang
- * @since 1.6
- */
-public class InMemoryCookieStore implements CookieStore {
-    // the in-memory representation of cookies
-    private List<HttpCookie> cookieJar = null;
-
-    // the cookies are indexed by its domain and associated uri (if present)
-    // CAUTION: when a cookie removed from main data structure (i.e. cookieJar),
-    //          it won't be cleared in domainIndex & uriIndex. Double-check the
-    //          presence of cookie when retrieve one form index store.
-    private Map<String, List<HttpCookie>> domainIndex = null;
-    private Map<URI, List<HttpCookie>> uriIndex = null;
-
-    // use ReentrantLock instead of syncronized for scalability
-    private ReentrantLock lock = null;
-
-
-    /**
-     * The default ctor
-     */
-    public InMemoryCookieStore() {
-        cookieJar = new ArrayList<HttpCookie>();
-        domainIndex = new HashMap<String, List<HttpCookie>>();
-        uriIndex = new HashMap<URI, List<HttpCookie>>();
-
-        lock = new ReentrantLock(false);
-    }
-
-    /**
-     * Add one cookie into cookie store.
-     */
-    public void add(URI uri, HttpCookie cookie) {
-        // pre-condition : argument can't be null
-        if (cookie == null) {
-            throw new NullPointerException("cookie is null");
-        }
-
-
-        lock.lock();
-        try {
-            // remove the ole cookie if there has had one
-            cookieJar.remove(cookie);
-
-            // add new cookie if it has a non-zero max-age
-            if (cookie.getMaxAge() != 0) {
-                cookieJar.add(cookie);
-                // and add it to domain index
-                if (cookie.getDomain() != null) {
-                    addIndex(domainIndex, cookie.getDomain(), cookie);
-                }
-                // add it to uri index, too
-                addIndex(uriIndex, getEffectiveURI(uri), cookie);
-            }
-        } finally {
-            lock.unlock();
-        }
-    }
-
-
-    /**
-     * Get all cookies, which:
-     *  1) given uri domain-matches with, or, associated with
-     *     given uri when added to the cookie store.
-     *  3) not expired.
-     * See RFC 2965 sec. 3.3.4 for more detail.
-     */
-    public List<HttpCookie> get(URI uri) {
-        // argument can't be null
-        if (uri == null) {
-            throw new NullPointerException("uri is null");
-        }
-
-        List<HttpCookie> cookies = new ArrayList<HttpCookie>();
-        boolean secureLink = "https".equalsIgnoreCase(uri.getScheme());
-        lock.lock();
-        try {
-            // check domainIndex first
-            getInternal1(cookies, domainIndex, uri.getHost(), secureLink);
-            // check uriIndex then
-            getInternal2(cookies, uriIndex, getEffectiveURI(uri), secureLink);
-        } finally {
-            lock.unlock();
-        }
-
-        return cookies;
-    }
-
-    /**
-     * Get all cookies in cookie store, except those have expired
-     */
-    public List<HttpCookie> getCookies() {
-        List<HttpCookie> rt;
-
-        lock.lock();
-        try {
-            Iterator<HttpCookie> it = cookieJar.iterator();
-            while (it.hasNext()) {
-                if (it.next().hasExpired()) {
-                    it.remove();
-                }
-            }
-        } finally {
-            rt = Collections.unmodifiableList(cookieJar);
-            lock.unlock();
-        }
-
-        return rt;
-    }
-
-    /**
-     * Get all URIs, which are associated with at least one cookie
-     * of this cookie store.
-     */
-    public List<URI> getURIs() {
-        List<URI> uris = new ArrayList<URI>();
-
-        lock.lock();
-        try {
-            Iterator<URI> it = uriIndex.keySet().iterator();
-            while (it.hasNext()) {
-                URI uri = it.next();
-                List<HttpCookie> cookies = uriIndex.get(uri);
-                if (cookies == null || cookies.size() == 0) {
-                    // no cookies list or an empty list associated with
-                    // this uri entry, delete it
-                    it.remove();
-                }
-            }
-        } finally {
-            uris.addAll(uriIndex.keySet());
-            lock.unlock();
-        }
-
-        return uris;
-    }
-
-
-    /**
-     * Remove a cookie from store
-     */
-    public boolean remove(URI uri, HttpCookie ck) {
-        // argument can't be null
-        if (ck == null) {
-            throw new NullPointerException("cookie is null");
-        }
-
-        boolean modified = false;
-        lock.lock();
-        try {
-            modified = cookieJar.remove(ck);
-        } finally {
-            lock.unlock();
-        }
-
-        return modified;
-    }
-
-
-    /**
-     * Remove all cookies in this cookie store.
-     */
-    public boolean removeAll() {
-        lock.lock();
-        try {
-            cookieJar.clear();
-            domainIndex.clear();
-            uriIndex.clear();
-        } finally {
-            lock.unlock();
-        }
-
-        return true;
-    }
-
-
-    /* ---------------- Private operations -------------- */
-
-
-    /*
-     * This is almost the same as HttpCookie.domainMatches except for
-     * one difference: It won't reject cookies when the 'H' part of the
-     * domain contains a dot ('.').
-     * I.E.: RFC 2965 section 3.3.2 says that if host is x.y.domain.com
-     * and the cookie domain is .domain.com, then it should be rejected.
-     * However that's not how the real world works. Browsers don't reject and
-     * some sites, like yahoo.com do actually expect these cookies to be
-     * passed along.
-     * And should be used for 'old' style cookies (aka Netscape type of cookies)
-     */
-    private boolean netscapeDomainMatches(String domain, String host)
-    {
-        if (domain == null || host == null) {
-            return false;
-        }
-
-        // if there's no embedded dot in domain and domain is not .local
-        boolean isLocalDomain = ".local".equalsIgnoreCase(domain);
-        int embeddedDotInDomain = domain.indexOf('.');
-        if (embeddedDotInDomain == 0) {
-            embeddedDotInDomain = domain.indexOf('.', 1);
-        }
-        if (!isLocalDomain && (embeddedDotInDomain == -1 || embeddedDotInDomain == domain.length() - 1)) {
-            return false;
-        }
-
-        // if the host name contains no dot and the domain name is .local
-        int firstDotInHost = host.indexOf('.');
-        if (firstDotInHost == -1 && isLocalDomain) {
-            return true;
-        }
-
-        int domainLength = domain.length();
-        int lengthDiff = host.length() - domainLength;
-        if (lengthDiff == 0) {
-            // if the host name and the domain name are just string-compare euqal
-            return host.equalsIgnoreCase(domain);
-        } else if (lengthDiff > 0) {
-            // need to check H & D component
-            String H = host.substring(0, lengthDiff);
-            String D = host.substring(lengthDiff);
-
-            return (D.equalsIgnoreCase(domain));
-        } else if (lengthDiff == -1) {
-            // if domain is actually .host
-            return (domain.charAt(0) == '.' &&
-                    host.equalsIgnoreCase(domain.substring(1)));
-        }
-
-        return false;
-    }
-
-    private void getInternal1(List<HttpCookie> cookies, Map<String, List<HttpCookie>> cookieIndex,
-            String host, boolean secureLink) {
-        // Use a separate list to handle cookies that need to be removed so
-        // that there is no conflict with iterators.
-        ArrayList<HttpCookie> toRemove = new ArrayList<HttpCookie>();
-        for (Map.Entry<String, List<HttpCookie>> entry : cookieIndex.entrySet()) {
-            String domain = entry.getKey();
-            List<HttpCookie> lst = entry.getValue();
-            for (HttpCookie c : lst) {
-                if ((c.getVersion() == 0 && netscapeDomainMatches(domain, host)) ||
-                        (c.getVersion() == 1 && HttpCookie.domainMatches(domain, host))) {
-                    if ((cookieJar.indexOf(c) != -1)) {
-                        // the cookie still in main cookie store
-                        if (!c.hasExpired()) {
-                            // don't add twice and make sure it's the proper
-                            // security level
-                            if ((secureLink || !c.getSecure()) &&
-                                    !cookies.contains(c)) {
-                                cookies.add(c);
-                            }
-                        } else {
-                            toRemove.add(c);
-                        }
-                    } else {
-                        // the cookie has beed removed from main store,
-                        // so also remove it from domain indexed store
-                        toRemove.add(c);
-                    }
-                }
-            }
-            // Clear up the cookies that need to be removed
-            for (HttpCookie c : toRemove) {
-                lst.remove(c);
-                cookieJar.remove(c);
-
-            }
-            toRemove.clear();
-        }
-    }
-
-    // @param cookies           [OUT] contains the found cookies
-    // @param cookieIndex       the index
-    // @param comparator        the prediction to decide whether or not
-    //                          a cookie in index should be returned
-    private <T> void getInternal2(List<HttpCookie> cookies,
-                                Map<T, List<HttpCookie>> cookieIndex,
-                                Comparable<T> comparator, boolean secureLink)
-    {
-        for (T index : cookieIndex.keySet()) {
-            if (comparator.compareTo(index) == 0) {
-                List<HttpCookie> indexedCookies = cookieIndex.get(index);
-                // check the list of cookies associated with this domain
-                if (indexedCookies != null) {
-                    Iterator<HttpCookie> it = indexedCookies.iterator();
-                    while (it.hasNext()) {
-                        HttpCookie ck = it.next();
-                        if (cookieJar.indexOf(ck) != -1) {
-                            // the cookie still in main cookie store
-                            if (!ck.hasExpired()) {
-                                // don't add twice
-                                if ((secureLink || !ck.getSecure()) &&
-                                        !cookies.contains(ck))
-                                    cookies.add(ck);
-                            } else {
-                                it.remove();
-                                cookieJar.remove(ck);
-                            }
-                        } else {
-                            // the cookie has beed removed from main store,
-                            // so also remove it from domain indexed store
-                            it.remove();
-                        }
-                    }
-                } // end of indexedCookies != null
-            } // end of comparator.compareTo(index) == 0
-        } // end of cookieIndex iteration
-    }
-
-    // add 'cookie' indexed by 'index' into 'indexStore'
-    private <T> void addIndex(Map<T, List<HttpCookie>> indexStore,
-                              T index,
-                              HttpCookie cookie)
-    {
-        if (index != null) {
-            List<HttpCookie> cookies = indexStore.get(index);
-            if (cookies != null) {
-                // there may already have the same cookie, so remove it first
-                cookies.remove(cookie);
-
-                cookies.add(cookie);
-            } else {
-                cookies = new ArrayList<HttpCookie>();
-                cookies.add(cookie);
-                indexStore.put(index, cookies);
-            }
-        }
-    }
-
-
-    //
-    // for cookie purpose, the effective uri should only be http://host
-    // the path will be taken into account when path-match algorithm applied
-    //
-    private URI getEffectiveURI(URI uri) {
-        URI effectiveURI = null;
-        try {
-            effectiveURI = new URI("http",
-                                   uri.getHost(),
-                                   null,  // path component
-                                   null,  // query component
-                                   null   // fragment component
-                                  );
-        } catch (URISyntaxException ignored) {
-            effectiveURI = uri;
-        }
-
-        return effectiveURI;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,131 @@
+/*
+ * 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.www.protocol.http;
+
+import java.net.URL;
+import java.net.PasswordAuthentication;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * Proxy class for loading NTLMAuthentication, so as to remove static
+ * dependancy.
+ */
+class NTLMAuthenticationProxy {
+    private static Method supportsTA;
+    private static final String clazzStr = "sun.net.www.protocol.http.NTLMAuthentication";
+    private static final String supportsTAStr = "supportsTransparentAuth";
+
+    static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
+    static final boolean supported = proxy != null ? true : false;
+    static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth(supportsTA) : false;
+
+    private final Constructor<? extends AuthenticationInfo> threeArgCtr;
+    private final Constructor<? extends AuthenticationInfo> fiveArgCtr;
+
+    private NTLMAuthenticationProxy(Constructor<? extends AuthenticationInfo> threeArgCtr,
+                                    Constructor<? extends AuthenticationInfo> fiveArgCtr) {
+        this.threeArgCtr = threeArgCtr;
+        this.fiveArgCtr = fiveArgCtr;
+    }
+
+
+    AuthenticationInfo create(boolean isProxy,
+                              URL url,
+                              PasswordAuthentication pw) {
+        try {
+            return threeArgCtr.newInstance(isProxy, url, pw);
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+        }
+
+        return null;
+    }
+
+    AuthenticationInfo create(boolean isProxy,
+                              String host,
+                              int port,
+                              PasswordAuthentication pw) {
+        try {
+            return fiveArgCtr.newInstance(isProxy, host, port, pw);
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+        }
+
+        return null;
+    }
+
+    /* Returns true if the NTLM implementation supports transparent
+     * authentication (try with the current users credentials before
+     * prompting for username and password, etc).
+     */
+    private static boolean supportsTransparentAuth(Method method) {
+        try {
+            return (Boolean)method.invoke(null);
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+        }
+
+        return false;
+    }
+
+    /**
+     * Loads the NTLM authentiation implementation through reflection. If
+     * the class is present, then it must have the required constructors and
+     * method. Otherwise, it is considered an error.
+     */
+    @SuppressWarnings("unchecked")
+    private static NTLMAuthenticationProxy tryLoadNTLMAuthentication() {
+        Class<? extends AuthenticationInfo> cl;
+        Constructor<? extends AuthenticationInfo> threeArg, fiveArg;
+        try {
+            cl = (Class<? extends AuthenticationInfo>)Class.forName(clazzStr, true, null);
+            if (cl != null) {
+                threeArg = cl.getConstructor(boolean.class,
+                                             URL.class,
+                                             PasswordAuthentication.class);
+                fiveArg = cl.getConstructor(boolean.class,
+                                            String.class,
+                                            int.class,
+                                            PasswordAuthentication.class);
+                supportsTA = cl.getDeclaredMethod(supportsTAStr);
+                return new NTLMAuthenticationProxy(threeArg,
+                                                   fiveArg);
+            }
+        } catch (ClassNotFoundException cnfe) {
+            finest(cnfe);
+        } catch (ReflectiveOperationException roe) {
+            throw new AssertionError(roe);
+        }
+
+        return null;
+    }
+
+    static void finest(Exception e) {
+        PlatformLogger logger = HttpURLConnection.getHttpLogger();
+        logger.finest("NTLMAuthenticationProxy: " + e);
+    }
+}
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java	Wed Jul 05 17:01:09 2017 +0200
@@ -30,11 +30,14 @@
 import sun.net.www.HeaderParser;
 import sun.misc.BASE64Decoder;
 import sun.misc.BASE64Encoder;
+import sun.util.logging.PlatformLogger;
 
 import java.net.URL;
 import java.io.IOException;
 import java.net.Authenticator.RequestorType;
-
+import java.lang.reflect.Constructor;
+import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
+import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
 
 /**
  * NegotiateAuthentication:
@@ -49,9 +52,6 @@
 
     final private HttpCallerInfo hci;
 
-    static final char NEGOTIATE_AUTH = 'S';
-    static final char KERBEROS_AUTH = 'K';
-
     // These maps are used to manage the GSS availability for diffrent
     // hosts. The key for both maps is the host name.
     // <code>supported</code> is set when isSupported is checked,
@@ -68,11 +68,10 @@
     * @param hci a schemed object.
     */
     public NegotiateAuthentication(HttpCallerInfo hci) {
-        super(RequestorType.PROXY==hci.authType?
-                    PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
-                hci.scheme.equalsIgnoreCase("Negotiate")?
-                    NEGOTIATE_AUTH:KERBEROS_AUTH,
-                hci.url, "");
+        super(RequestorType.PROXY==hci.authType ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              hci.scheme.equalsIgnoreCase("Negotiate") ? NEGOTIATE : KERBEROS,
+              hci.url,
+              "");
         this.hci = hci;
     }
 
@@ -249,13 +248,41 @@
         // The current implementation will make sure NegotiatorImpl is not
         // directly referenced when compiling, thus smooth the way of building
         // the J2SE platform where HttpURLConnection is a bootstrap class.
+        //
+        // Makes NegotiatorImpl, and the security classes it references, a
+        // runtime dependency rather than a static one.
 
-        Class clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl");
-        java.lang.reflect.Constructor c = clazz.getConstructor(HttpCallerInfo.class);
-        return (Negotiator) (c.newInstance(hci));
+        Class clazz;
+        Constructor c;
+        try {
+            clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl", true, null);
+            c = clazz.getConstructor(HttpCallerInfo.class);
+        } catch (ClassNotFoundException cnfe) {
+            finest(cnfe);
+            throw cnfe;
+        } catch (ReflectiveOperationException roe) {
+            // if the class is there then something seriously wrong if
+            // the constructor is not.
+            throw new AssertionError(roe);
+        }
+
+        try {
+            return (Negotiator) (c.newInstance(hci));
+        } catch (ReflectiveOperationException roe) {
+            finest(roe);
+            Throwable t = roe.getCause();
+            if (t != null && t instanceof Exception)
+                finest((Exception)t);
+            throw roe;
+        }
     }
 
     abstract byte[] firstToken() throws IOException;
 
     abstract byte[] nextToken(byte[] in) throws IOException;
+
+    static void finest(Exception e) {
+        PlatformLogger logger = HttpURLConnection.getHttpLogger();
+        logger.finest("NegotiateAuthentication: " + e);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,74 @@
+/*
+ * 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.action;
+
+import java.security.Security;
+
+/**
+ * A convenience class for retrieving the boolean value of a security property
+ * as a privileged action.
+ *
+ * <p>An instance of this class can be used as the argument of
+ * <code>AccessController.doPrivileged</code>.
+ *
+ * <p>The following code retrieves the boolean value of the security
+ * property named <code>"prop"</code> as a privileged action: <p>
+ *
+ * <pre>
+ * boolean b = java.security.AccessController.doPrivileged
+ *              (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
+ * </pre>
+ *
+ */
+public class GetBooleanSecurityPropertyAction
+        implements java.security.PrivilegedAction<Boolean> {
+    private String theProp;
+
+    /**
+     * Constructor that takes the name of the security property whose boolean
+     * value needs to be determined.
+     *
+     * @param theProp the name of the security property
+     */
+    public GetBooleanSecurityPropertyAction(String theProp) {
+        this.theProp = theProp;
+    }
+
+    /**
+     * Determines the boolean value of the security property whose name was
+     * specified in the constructor.
+     *
+     * @return the <code>Boolean</code> value of the security property.
+     */
+    public Boolean run() {
+        boolean b = false;
+        try {
+            String value = Security.getProperty(theProp);
+            b = (value != null) && value.equalsIgnoreCase("true");
+        } catch (NullPointerException e) {}
+        return b;
+    }
+}
--- a/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java	Wed Jul 05 17:01:09 2017 +0200
@@ -39,21 +39,6 @@
  */
 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;
 
@@ -65,16 +50,12 @@
 
     /**
      * 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
+    @Override
     protected void engineInit(Key key, SecureRandom random)
             throws InvalidKeyException {
         if (!(key instanceof PrivateKey)) {
@@ -86,6 +67,7 @@
     }
 
     // see JCE spec
+    @Override
     protected void engineInit(Key key, AlgorithmParameterSpec params,
             SecureRandom random) throws InvalidKeyException,
             InvalidAlgorithmParameterException {
@@ -97,6 +79,7 @@
     }
 
     // see JCE spec
+    @Override
     protected Key engineDoPhase(Key key, boolean lastPhase)
             throws InvalidKeyException, IllegalStateException {
         if (privateKey == null) {
@@ -130,6 +113,7 @@
     }
 
     // see JCE spec
+    @Override
     protected byte[] engineGenerateSecret() throws IllegalStateException {
         if ((privateKey == null) || (publicValue == null)) {
             throw new IllegalStateException("Not initialized correctly");
@@ -150,6 +134,7 @@
     }
 
     // see JCE spec
+    @Override
     protected int engineGenerateSecret(byte[] sharedSecret, int
             offset) throws IllegalStateException, ShortBufferException {
         if (offset + secretLen > sharedSecret.length) {
@@ -162,6 +147,7 @@
     }
 
     // see JCE spec
+    @Override
     protected SecretKey engineGenerateSecret(String algorithm)
             throws IllegalStateException, NoSuchAlgorithmException,
             InvalidKeyException {
--- a/jdk/src/share/classes/sun/security/ec/ECDSASignature.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/ec/ECDSASignature.java	Wed Jul 05 17:01:09 2017 +0200
@@ -52,21 +52,6 @@
  */
 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;
 
@@ -88,24 +73,13 @@
      * @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) {
@@ -299,8 +273,8 @@
         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];
+        // seed is twice the key size (in bytes) plus 1
+        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
         if (random == null) {
             random = JCAUtil.getSecureRandom();
         }
@@ -356,6 +330,7 @@
 
     // Convert the concatenation of R and S into their DER encoding
     private byte[] encodeSignature(byte[] signature) throws SignatureException {
+
         try {
 
             int n = signature.length >> 1;
--- a/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java	Wed Jul 05 17:01:09 2017 +0200
@@ -46,20 +46,6 @@
  */
 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;
@@ -75,13 +61,8 @@
 
     /**
      * 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);
     }
@@ -133,8 +114,8 @@
         byte[] encodedParams =
             ECParameters.encodeParameters((ECParameterSpec)params);
 
-        // seed is twice the key size (in bytes)
-        byte[] seed = new byte[2 * ((keySize + 7) >> 3)];
+        // seed is twice the key size (in bytes) plus 1
+        byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2];
         if (random == null) {
             random = JCAUtil.getSecureRandom();
         }
--- a/jdk/src/share/classes/sun/security/ec/SunEC.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/ec/SunEC.java	Wed Jul 05 17:01:09 2017 +0200
@@ -39,7 +39,10 @@
  * 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.
+ * libsunec.so or sunec.dll in the JRE native libraries directory.
+ * If the native library is not present then this provider is registered
+ * with support for fewer ECC algorithms (KeyPairGenerator, Signature and
+ * KeyAgreement are omitted).
  *
  * @since   1.7
  */
@@ -47,6 +50,22 @@
 
     private static final long serialVersionUID = -2279741672933606418L;
 
+    // flag indicating whether the full EC implementation is present
+    // (when native library is absent then fewer EC algorithms are available)
+    private static boolean useFullImplementation = true;
+    static {
+        try {
+            AccessController.doPrivileged(new PrivilegedAction<Void>() {
+                public Void run() {
+                    System.loadLibrary("sunec"); // check for native library
+                    return null;
+                }
+            });
+        } catch (UnsatisfiedLinkError e) {
+            useFullImplementation = false;
+        }
+    }
+
     public SunEC() {
         super("SunEC", 1.7d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
 
@@ -54,10 +73,10 @@
         // 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);
+            SunECEntries.putEntries(this, useFullImplementation);
         } else {
             Map<Object, Object> map = new HashMap<Object, Object>();
-            SunECEntries.putEntries(map);
+            SunECEntries.putEntries(map, useFullImplementation);
             AccessController.doPrivileged(new PutAllAction(this, map));
         }
     }
--- a/jdk/src/share/classes/sun/security/ec/SunECEntries.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/ec/SunECEntries.java	Wed Jul 05 17:01:09 2017 +0200
@@ -38,7 +38,93 @@
         // empty
     }
 
-    static void putEntries(Map<Object, Object> map) {
+    static void putEntries(Map<Object, Object> map,
+        boolean useFullImplementation) {
+
+        /*
+         *  Key Factory engine
+         */
+        map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory");
+        map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC");
+
+        map.put("KeyFactory.EC ImplementedIn", "Software");
+
+        /*
+         * Algorithm Parameter engine
+         */
+        map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters");
+        map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC");
+
+        map.put("AlgorithmParameters.EC KeySize", "256");
+
+        map.put("AlgorithmParameters.EC ImplementedIn", "Software");
+
+        map.put("AlgorithmParameters.EC SupportedCurves",
+
+            // A list comprising lists of curve names and object identifiers.
+            // '[' ( <curve-name> ',' )+ <curve-object-identifier> ']' '|'
+
+            // SEC 2 prime curves
+            "[secp112r1,1.3.132.0.6]|" +
+            "[secp112r2,1.3.132.0.7]|" +
+            "[secp128r1,1.3.132.0.28]|" +
+            "[secp128r2,1.3.132.0.29]|" +
+            "[secp160k1,1.3.132.0.9]|" +
+            "[secp160r1,1.3.132.0.8]|" +
+            "[secp160r2,1.3.132.0.30]|" +
+            "[secp192k1,1.3.132.0.31]|" +
+            "[secp192r1,NIST P-192,X9.62 prime192v1,1.2.840.10045.3.1.1]|" +
+            "[secp224k1,1.3.132.0.32]|" +
+            "[secp224r1,NIST P-224,1.3.132.0.33]|" +
+            "[secp256k1,1.3.132.0.10]|" +
+            "[secp256r1,NIST P-256,X9.62 prime256v1,1.2.840.10045.3.1.7]|" +
+            "[secp384r1,NIST P-384,1.3.132.0.34]|" +
+            "[secp521r1,NIST P-521,1.3.132.0.35]|" +
+
+            // ANSI X9.62 prime curves
+            "[X9.62 prime192v2,1.2.840.10045.3.1.2]|" +
+            "[X9.62 prime192v3,1.2.840.10045.3.1.3]|" +
+            "[X9.62 prime239v1,1.2.840.10045.3.1.4]|" +
+            "[X9.62 prime239v2,1.2.840.10045.3.1.5]|" +
+            "[X9.62 prime239v3,1.2.840.10045.3.1.6]|" +
+
+            // SEC 2 binary curves
+            "[sect113r1,1.3.132.0.4]|" +
+            "[sect113r2,1.3.132.0.5]|" +
+            "[sect131r1,1.3.132.0.22]|" +
+            "[sect131r2,1.3.132.0.23]|" +
+            "[sect163k1,NIST K-163,1.3.132.0.1]|" +
+            "[sect163r1,1.3.132.0.2]|" +
+            "[sect163r2,NIST B-163,1.3.132.0.15]|" +
+            "[sect193r1,1.3.132.0.24]|" +
+            "[sect193r2,1.3.132.0.25]|" +
+            "[sect233k1,NIST K-233,1.3.132.0.26]|" +
+            "[sect233r1,NIST B-233,1.3.132.0.27]|" +
+            "[sect239k1,1.3.132.0.3]|" +
+            "[sect283k1,NIST K-283,1.3.132.0.16]|" +
+            "[sect283r1,NIST B-283,1.3.132.0.17]|" +
+            "[sect409k1,NIST K-409,1.3.132.0.36]|" +
+            "[sect409r1,NIST B-409,1.3.132.0.37]|" +
+            "[sect571k1,NIST K-571,1.3.132.0.38]|" +
+            "[sect571r1,NIST B-571,1.3.132.0.39]|" +
+
+            // ANSI X9.62 binary curves
+            "[X9.62 c2tnb191v1,1.2.840.10045.3.0.5]|" +
+            "[X9.62 c2tnb191v2,1.2.840.10045.3.0.6]|" +
+            "[X9.62 c2tnb191v3,1.2.840.10045.3.0.7]|" +
+            "[X9.62 c2tnb239v1,1.2.840.10045.3.0.11]|" +
+            "[X9.62 c2tnb239v2,1.2.840.10045.3.0.12]|" +
+            "[X9.62 c2tnb239v3,1.2.840.10045.3.0.13]|" +
+            "[X9.62 c2tnb359v1,1.2.840.10045.3.0.18]|" +
+            "[X9.62 c2tnb431r1,1.2.840.10045.3.0.20]");
+
+        /*
+         * Register the algorithms below only when the full ECC implementation
+         * is available
+         */
+        if (!useFullImplementation) {
+            return;
+        }
 
         /*
          * Signature engines
@@ -62,48 +148,31 @@
         map.put("Signature.SHA384withECDSA SupportedKeyClasses", ecKeyClasses);
         map.put("Signature.SHA512withECDSA SupportedKeyClasses", ecKeyClasses);
 
+        map.put("Signature.SHA1withECDSA KeySize", "256");
+
+        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");
+
         /*
          *  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");
+        map.put("KeyPairGenerator.EC KeySize", "256");
 
-        /*
-         * Algorithm Parameter engine
-         */
-        map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters");
-        map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC");
+        map.put("KeyPairGenerator.EC ImplementedIn", "Software");
 
         /*
          * 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/krb5/KrbKdcReq.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/krb5/KrbKdcReq.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Portions Copyright 2000-2006 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
@@ -149,6 +149,11 @@
                 send(realm,tempKdc,useTCP);
                 break;
             } catch (Exception e) {
+                if (DEBUG) {
+                    System.out.println(">>> KrbKdcReq send: error trying " +
+                            tempKdc);
+                    e.printStackTrace(System.out);
+                }
                 savedException = e;
             }
         }
@@ -179,10 +184,36 @@
         /*
          * Get port number for this KDC.
          */
-        StringTokenizer strTok = new StringTokenizer(tempKdc, ":");
-        String kdc = strTok.nextToken();
-        if (strTok.hasMoreTokens()) {
-            String portStr = strTok.nextToken();
+        String kdc = null;
+        String portStr = null;
+
+        if (tempKdc.charAt(0) == '[') {     // Explicit IPv6 in []
+            int pos = tempKdc.indexOf(']', 1);
+            if (pos == -1) {
+                throw new IOException("Illegal KDC: " + tempKdc);
+            }
+            kdc = tempKdc.substring(1, pos);
+            if (pos != tempKdc.length() - 1) {  // with port number
+                if (tempKdc.charAt(pos+1) != ':') {
+                    throw new IOException("Illegal KDC: " + tempKdc);
+                }
+                portStr = tempKdc.substring(pos+2);
+            }
+        } else {
+            int colon = tempKdc.indexOf(':');
+            if (colon == -1) {      // Hostname or IPv4 host only
+                kdc = tempKdc;
+            } else {
+                int nextColon = tempKdc.indexOf(':', colon+1);
+                if (nextColon > 0) {    // >=2 ":", IPv6 with no port
+                    kdc = tempKdc;
+                } else {                // 1 ":", hostname or IPv4 with port
+                    kdc = tempKdc.substring(0, colon);
+                    portStr = tempKdc.substring(colon+1);
+                }
+            }
+        }
+        if (portStr != null) {
             int tempPort = parsePositiveIntString(portStr);
             if (tempPort > 0)
                 port = tempPort;
--- a/jdk/src/share/classes/sun/security/provider/certpath/Builder.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/Builder.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2006 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
@@ -26,12 +26,14 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
+import java.security.AccessController;
 import java.security.GeneralSecurityException;
 import java.security.cert.*;
 import java.util.*;
 
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.action.GetBooleanAction;
 import sun.security.util.Debug;
 import sun.security.x509.GeneralNames;
 import sun.security.x509.GeneralNameInterface;
@@ -64,9 +66,8 @@
      * Authority Information Access extension shall be enabled. Currently
      * disabled by default for compatibility reasons.
      */
-    final static boolean USE_AIA =
-        DistributionPointFetcher.getBooleanProperty
-            ("com.sun.security.enableAIAcaIssuers", false);
+    final static boolean USE_AIA = AccessController.doPrivileged
+        (new GetBooleanAction("com.sun.security.enableAIAcaIssuers"));
 
     /**
      * Initialize the builder with the input parameters.
--- a/jdk/src/share/classes/sun/security/provider/certpath/CertId.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertId.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2005 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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,9 +25,11 @@
 
 package sun.security.provider.certpath;
 
-import java.io.*;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import sun.misc.HexDumpEncoder;
 import sun.security.x509.*;
@@ -54,21 +56,28 @@
 public class CertId {
 
     private static final boolean debug = false;
-    private AlgorithmId hashAlgId;
-    private byte[] issuerNameHash;
-    private byte[] issuerKeyHash;
-    private SerialNumber certSerialNumber;
+    private static final AlgorithmId SHA1_ALGID
+        = new AlgorithmId(AlgorithmId.SHA_oid);
+    private final AlgorithmId hashAlgId;
+    private final byte[] issuerNameHash;
+    private final byte[] issuerKeyHash;
+    private final SerialNumber certSerialNumber;
     private int myhash = -1; // hashcode for this CertId
 
     /**
      * Creates a CertId. The hash algorithm used is SHA-1.
      */
-    public CertId(X509CertImpl issuerCert, SerialNumber serialNumber)
-        throws Exception {
+    public CertId(X509Certificate issuerCert, SerialNumber serialNumber)
+        throws IOException {
 
         // compute issuerNameHash
-        MessageDigest md = MessageDigest.getInstance("SHA1");
-        hashAlgId = AlgorithmId.get("SHA1");
+        MessageDigest md = null;
+        try {
+            md = MessageDigest.getInstance("SHA1");
+        } catch (NoSuchAlgorithmException nsae) {
+            throw new IOException("Unable to create CertId", nsae);
+        }
+        hashAlgId = SHA1_ALGID;
         md.update(issuerCert.getSubjectX500Principal().getEncoded());
         issuerNameHash = md.digest();
 
@@ -90,6 +99,7 @@
                 encoder.encode(issuerNameHash));
             System.out.println("issuerKeyHash is " +
                 encoder.encode(issuerKeyHash));
+            System.out.println("SerialNumber is " + serialNumber.getNumber());
         }
     }
 
@@ -97,7 +107,6 @@
      * Creates a CertId from its ASN.1 DER encoding.
      */
     public CertId(DerInputStream derIn) throws IOException {
-
         hashAlgId = AlgorithmId.parse(derIn.getDerValue());
         issuerNameHash = derIn.getOctetString();
         issuerKeyHash = derIn.getOctetString();
@@ -157,7 +166,7 @@
      *
      * @return the hashcode value.
      */
-    public int hashCode() {
+    @Override public int hashCode() {
         if (myhash == -1) {
             myhash = hashAlgId.hashCode();
             for (int i = 0; i < issuerNameHash.length; i++) {
@@ -180,8 +189,7 @@
      * @param other the object to test for equality with this object.
      * @return true if the objects are considered equal, false otherwise.
      */
-    public boolean equals(Object other) {
-
+    @Override public boolean equals(Object other) {
         if (this == other) {
             return true;
         }
@@ -203,7 +211,7 @@
     /**
      * Create a string representation of the CertId.
      */
-    public String toString() {
+    @Override public String toString() {
         StringBuilder sb = new StringBuilder();
         sb.append("CertId \n");
         sb.append("Algorithm: " + hashAlgId.toString() +"\n");
--- a/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Wed Jul 05 17:01:09 2017 +0200
@@ -80,6 +80,7 @@
         { false, false, false, false, false, false, true };
     private static final boolean[] ALL_REASONS =
         {true, true, true, true, true, true, true, true, true};
+    private boolean mOnlyEECert = false;
 
     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
     // validity of CRLs
@@ -114,6 +115,12 @@
     CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
         Collection<X509Certificate> certs) throws CertPathValidatorException
     {
+        this(anchor, params, certs, false);
+    }
+
+    CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
+        Collection<X509Certificate> certs, boolean onlyEECert)
+        throws CertPathValidatorException {
         mAnchor = anchor;
         mParams = params;
         mStores = new ArrayList<CertStore>(params.getCertStores());
@@ -133,6 +140,7 @@
         }
         Date testDate = params.getDate();
         mCurrentTime = (testDate != null ? testDate : new Date());
+        mOnlyEECert = onlyEECert;
         init(false);
     }
 
@@ -264,6 +272,13 @@
                 " ---checking " + msg + "...");
         }
 
+        if (mOnlyEECert && currCert.getBasicConstraints() != -1) {
+            if (debug != null) {
+                debug.println("Skipping revocation check, not end entity cert");
+            }
+            return;
+        }
+
         // reject circular dependencies - RFC 3280 is not explicit on how
         // to handle this, so we feel it is safest to reject them until
         // the issue is resolved in the PKIX WG.
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Wed Jul 05 17:01:09 2017 +0200
@@ -32,7 +32,7 @@
 import java.security.cert.*;
 import javax.security.auth.x500.X500Principal;
 
-import sun.security.action.GetPropertyAction;
+import sun.security.action.GetBooleanAction;
 import sun.security.util.Debug;
 import sun.security.util.DerOutputStream;
 import sun.security.x509.*;
@@ -62,28 +62,8 @@
      * extension shall be enabled. Currently disabled by default for
      * compatibility and legal reasons.
      */
-    private final static boolean USE_CRLDP =
-        getBooleanProperty("com.sun.security.enableCRLDP", false);
-
-    /**
-     * Return the value of the boolean System property propName.
-     */
-    public static boolean getBooleanProperty(String propName,
-            boolean defaultValue) {
-        // if set, require value of either true or false
-        String b = AccessController.doPrivileged(
-                new GetPropertyAction(propName));
-        if (b == null) {
-            return defaultValue;
-        } else if (b.equalsIgnoreCase("false")) {
-            return false;
-        } else if (b.equalsIgnoreCase("true")) {
-            return true;
-        } else {
-            throw new RuntimeException("Value of " + propName
-            + " must either be 'true' or 'false'");
-        }
-    }
+    private final static boolean USE_CRLDP = AccessController.doPrivileged
+        (new GetBooleanAction("com.sun.security.enableCRLDP"));
 
     // singleton instance
     private static final DistributionPointFetcher INSTANCE =
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Wed Jul 05 17:01:09 2017 +0200
@@ -82,6 +82,7 @@
     TrustAnchor trustAnchor;
     private Comparator<X509Certificate> comparator;
     private boolean searchAllCertStores = true;
+    private boolean onlyEECert = false;
 
     /**
      * Initialize the builder with the input parameters.
@@ -89,7 +90,8 @@
      * @param params the parameter set used to build a certification path
      */
     ForwardBuilder(PKIXBuilderParameters buildParams,
-        X500Principal targetSubjectDN, boolean searchAllCertStores)
+        X500Principal targetSubjectDN, boolean searchAllCertStores,
+        boolean onlyEECert)
     {
         super(buildParams, targetSubjectDN);
 
@@ -108,6 +110,7 @@
         }
         comparator = new PKIXCertComparator(trustedSubjectDNs);
         this.searchAllCertStores = searchAllCertStores;
+        this.onlyEECert = onlyEECert;
     }
 
     /**
@@ -875,8 +878,8 @@
             /* Check revocation if it is enabled */
             if (buildParams.isRevocationEnabled()) {
                 try {
-                    CrlRevocationChecker crlChecker =
-                        new CrlRevocationChecker(anchor, buildParams);
+                    CrlRevocationChecker crlChecker = new CrlRevocationChecker
+                        (anchor, buildParams, null, onlyEECert);
                     crlChecker.check(cert, anchor.getCAPublicKey(), true);
                 } catch (CertPathValidatorException cpve) {
                     if (debug != null) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,329 @@
+/*
+ * 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.provider.certpath;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.net.HttpURLConnection;
+import java.security.cert.CertificateException;
+import java.security.cert.CertPathValidatorException;
+import java.security.cert.CRLReason;
+import java.security.cert.Extension;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static sun.security.provider.certpath.OCSPResponse.*;
+import sun.security.util.Debug;
+import sun.security.x509.AccessDescription;
+import sun.security.x509.AuthorityInfoAccessExtension;
+import sun.security.x509.GeneralName;
+import sun.security.x509.GeneralNameInterface;
+import sun.security.x509.URIName;
+import sun.security.x509.X509CertImpl;
+
+/**
+ * This is a class that checks the revocation status of a certificate(s) using
+ * OCSP. It is not a PKIXCertPathChecker and therefore can be used outside of
+ * the CertPathValidator framework. It is useful when you want to
+ * just check the revocation status of a certificate, and you don't want to
+ * incur the overhead of validating all of the certificates in the
+ * associated certificate chain.
+ *
+ * @author Sean Mullan
+ */
+public final class OCSP {
+
+    private static final Debug debug = Debug.getInstance("certpath");
+
+    private OCSP() {}
+
+    /**
+     * Obtains the revocation status of a certificate using OCSP using the most
+     * common defaults. The OCSP responder URI is retrieved from the
+     * certificate's AIA extension. The OCSP responder certificate is assumed
+     * to be the issuer's certificate (or issued by the issuer CA).
+     *
+     * @param cert the certificate to be checked
+     * @param issuerCert the issuer certificate
+     * @return the RevocationStatus
+     * @throws IOException if there is an exception connecting to or
+     *    communicating with the OCSP responder
+     * @throws CertPathValidatorException if an exception occurs while
+     *    encoding the OCSP Request or validating the OCSP Response
+     */
+    public static RevocationStatus check(X509Certificate cert,
+        X509Certificate issuerCert)
+        throws IOException, CertPathValidatorException {
+        CertId certId = null;
+        URI responderURI = null;
+        try {
+            X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+            responderURI = getResponderURI(certImpl);
+            if (responderURI == null) {
+                throw new CertPathValidatorException
+                    ("No OCSP Responder URI in certificate");
+            }
+            certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ce);
+        } catch (IOException ioe) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ioe);
+        }
+        OCSPResponse ocspResponse = check(Collections.singletonList(certId),
+            responderURI, issuerCert, null);
+        return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+    }
+
+    /**
+     * Obtains the revocation status of a certificate using OCSP.
+     *
+     * @param cert the certificate to be checked
+     * @param issuerCert the issuer certificate
+     * @param responderURI the URI of the OCSP responder
+     * @param responderCert the OCSP responder's certificate
+     * @param date the time the validity of the OCSP responder's certificate
+     *    should be checked against. If null, the current time is used.
+     * @return the RevocationStatus
+     * @throws IOException if there is an exception connecting to or
+     *    communicating with the OCSP responder
+     * @throws CertPathValidatorException if an exception occurs while
+     *    encoding the OCSP Request or validating the OCSP Response
+     */
+    public static RevocationStatus check(X509Certificate cert,
+        X509Certificate issuerCert, URI responderURI, X509Certificate
+        responderCert, Date date)
+        throws IOException, CertPathValidatorException {
+        CertId certId = null;
+        try {
+            X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+            certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ce);
+        } catch (IOException ioe) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ioe);
+        }
+        OCSPResponse ocspResponse = check(Collections.singletonList(certId),
+            responderURI, responderCert, date);
+        return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+    }
+
+    /**
+     * Checks the revocation status of a list of certificates using OCSP.
+     *
+     * @param certs the CertIds to be checked
+     * @param responderURI the URI of the OCSP responder
+     * @param responderCert the OCSP responder's certificate
+     * @param date the time the validity of the OCSP responder's certificate
+     *    should be checked against. If null, the current time is used.
+     * @return the OCSPResponse
+     * @throws IOException if there is an exception connecting to or
+     *    communicating with the OCSP responder
+     * @throws CertPathValidatorException if an exception occurs while
+     *    encoding the OCSP Request or validating the OCSP Response
+     */
+    static OCSPResponse check(List<CertId> certIds, URI responderURI,
+        X509Certificate responderCert, Date date)
+        throws IOException, CertPathValidatorException {
+
+        byte[] bytes = null;
+        try {
+            OCSPRequest request = new OCSPRequest(certIds);
+            bytes = request.encodeBytes();
+        } catch (IOException ioe) {
+            throw new CertPathValidatorException
+                ("Exception while encoding OCSPRequest", ioe);
+        }
+
+        InputStream in = null;
+        OutputStream out = null;
+        byte[] response = null;
+        try {
+            URL url = responderURI.toURL();
+            if (debug != null) {
+                debug.println("connecting to OCSP service at: " + url);
+            }
+            HttpURLConnection con = (HttpURLConnection)url.openConnection();
+            con.setDoOutput(true);
+            con.setDoInput(true);
+            con.setRequestMethod("POST");
+            con.setRequestProperty
+                ("Content-type", "application/ocsp-request");
+            con.setRequestProperty
+                ("Content-length", String.valueOf(bytes.length));
+            out = con.getOutputStream();
+            out.write(bytes);
+            out.flush();
+            // Check the response
+            if (debug != null &&
+                con.getResponseCode() != HttpURLConnection.HTTP_OK) {
+                debug.println("Received HTTP error: " + con.getResponseCode()
+                    + " - " + con.getResponseMessage());
+            }
+            in = con.getInputStream();
+            int contentLength = con.getContentLength();
+            if (contentLength == -1) {
+                contentLength = Integer.MAX_VALUE;
+            }
+            response = new byte[contentLength > 2048 ? 2048 : contentLength];
+            int total = 0;
+            while (total < contentLength) {
+                int count = in.read(response, total, response.length - total);
+                if (count < 0)
+                    break;
+
+                total += count;
+                if (total >= response.length && total < contentLength) {
+                    response = Arrays.copyOf(response, total * 2);
+                }
+            }
+            response = Arrays.copyOf(response, total);
+        } finally {
+            if (in != null) {
+                try {
+                    in.close();
+                } catch (IOException ioe) {
+                    throw ioe;
+                }
+            }
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException ioe) {
+                    throw ioe;
+                }
+            }
+        }
+
+        OCSPResponse ocspResponse = null;
+        try {
+            ocspResponse = new OCSPResponse(response, date, responderCert);
+        } catch (IOException ioe) {
+            // response decoding exception
+            throw new CertPathValidatorException(ioe);
+        }
+        if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) {
+            throw new CertPathValidatorException
+                ("OCSP response error: " + ocspResponse.getResponseStatus());
+        }
+
+        // Check that the response includes a response for all of the
+        // certs that were supplied in the request
+        for (CertId certId : certIds) {
+            SingleResponse sr = ocspResponse.getSingleResponse(certId);
+            if (sr == null) {
+                if (debug != null) {
+                    debug.println("No response found for CertId: " + certId);
+                }
+                throw new CertPathValidatorException(
+                    "OCSP response does not include a response for a " +
+                    "certificate supplied in the OCSP request");
+            }
+            if (debug != null) {
+                debug.println("Status of certificate (with serial number " +
+                    certId.getSerialNumber() + ") is: " + sr.getCertStatus());
+            }
+        }
+        return ocspResponse;
+    }
+
+    /**
+     * Returns the URI of the OCSP Responder as specified in the
+     * certificate's Authority Information Access extension, or null if
+     * not specified.
+     *
+     * @param cert the certificate
+     * @return the URI of the OCSP Responder, or null if not specified
+     */
+    public static URI getResponderURI(X509Certificate cert) {
+        try {
+            return getResponderURI(X509CertImpl.toImpl(cert));
+        } catch (CertificateException ce) {
+            // treat this case as if the cert had no extension
+            return null;
+        }
+    }
+
+    static URI getResponderURI(X509CertImpl certImpl) {
+
+        // Examine the certificate's AuthorityInfoAccess extension
+        AuthorityInfoAccessExtension aia =
+            certImpl.getAuthorityInfoAccessExtension();
+        if (aia == null) {
+            return null;
+        }
+
+        List<AccessDescription> descriptions = aia.getAccessDescriptions();
+        for (AccessDescription description : descriptions) {
+            if (description.getAccessMethod().equals(
+                AccessDescription.Ad_OCSP_Id)) {
+
+                GeneralName generalName = description.getAccessLocation();
+                if (generalName.getType() == GeneralNameInterface.NAME_URI) {
+                    URIName uri = (URIName) generalName.getName();
+                    return uri.getURI();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * The Revocation Status of a certificate.
+     */
+    public static interface RevocationStatus {
+        public enum CertStatus { GOOD, REVOKED, UNKNOWN };
+
+        /**
+         * Returns the revocation status.
+         */
+        CertStatus getCertStatus();
+        /**
+         * Returns the time when the certificate was revoked, or null
+         * if it has not been revoked.
+         */
+        Date getRevocationTime();
+        /**
+         * Returns the reason the certificate was revoked, or null if it
+         * has not been revoked.
+         */
+        CRLReason getRevocationReason();
+
+        /**
+         * Returns a Map of additional extensions.
+         */
+        Map<String, Extension> getSingleExtensions();
+    }
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,19 +25,20 @@
 
 package sun.security.provider.certpath;
 
-import java.io.*;
+import java.io.IOException;
 import java.math.BigInteger;
 import java.util.*;
 import java.security.AccessController;
-import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.security.Security;
 import java.security.cert.*;
 import java.security.cert.CertPathValidatorException.BasicReason;
-import java.net.*;
+import java.net.URI;
+import java.net.URISyntaxException;
 import javax.security.auth.x500.X500Principal;
 
-import sun.security.util.*;
+import static sun.security.provider.certpath.OCSP.*;
+import sun.security.util.Debug;
 import sun.security.x509.*;
 
 /**
@@ -50,27 +51,18 @@
  */
 class OCSPChecker extends PKIXCertPathChecker {
 
-    public static final String OCSP_ENABLE_PROP = "ocsp.enable";
-    public static final String OCSP_URL_PROP = "ocsp.responderURL";
-    public static final String OCSP_CERT_SUBJECT_PROP =
+    static final String OCSP_ENABLE_PROP = "ocsp.enable";
+    static final String OCSP_URL_PROP = "ocsp.responderURL";
+    static final String OCSP_CERT_SUBJECT_PROP =
         "ocsp.responderCertSubjectName";
-    public static final String OCSP_CERT_ISSUER_PROP =
-        "ocsp.responderCertIssuerName";
-    public static final String OCSP_CERT_NUMBER_PROP =
+    static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName";
+    static final String OCSP_CERT_NUMBER_PROP =
         "ocsp.responderCertSerialNumber";
 
     private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
     private static final Debug DEBUG = Debug.getInstance("certpath");
     private static final boolean dump = false;
 
-    // Supported extensions
-    private static final int OCSP_NONCE_DATA[] =
-        { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2 };
-    private static final ObjectIdentifier OCSP_NONCE_OID;
-    static {
-        OCSP_NONCE_OID = ObjectIdentifier.newInternal(OCSP_NONCE_DATA);
-    }
-
     private int remainingCerts;
 
     private X509Certificate[] certs;
@@ -79,19 +71,26 @@
 
     private PKIXParameters pkixParams;
 
+    private boolean onlyEECert = false;
+
     /**
      * Default Constructor
      *
      * @param certPath the X509 certification path
      * @param pkixParams the input PKIX parameter set
-     * @exception CertPathValidatorException Exception thrown if cert path
-     * does not validate.
+     * @throws CertPathValidatorException if OCSPChecker can not be created
      */
     OCSPChecker(CertPath certPath, PKIXParameters pkixParams)
         throws CertPathValidatorException {
+        this(certPath, pkixParams, false);
+    }
+
+    OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert)
+        throws CertPathValidatorException {
 
         this.cp = certPath;
         this.pkixParams = pkixParams;
+        this.onlyEECert = onlyEECert;
         List<? extends Certificate> tmp = cp.getCertificates();
         certs = tmp.toArray(new X509Certificate[tmp.size()]);
         init(false);
@@ -101,6 +100,7 @@
      * Initializes the internal state of the checker from parameters
      * specified in the constructor
      */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
         if (!forward) {
             remainingCerts = certs.length + 1;
@@ -110,11 +110,11 @@
         }
     }
 
-    public boolean isForwardCheckingSupported() {
+    @Override public boolean isForwardCheckingSupported() {
         return false;
     }
 
-    public Set<String> getSupportedExtensions() {
+    @Override public Set<String> getSupportedExtensions() {
         return Collections.<String>emptySet();
     }
 
@@ -127,300 +127,233 @@
      * @exception CertPathValidatorException Exception is thrown if the
      *            certificate has been revoked.
      */
+    @Override
     public void check(Certificate cert, Collection<String> unresolvedCritExts)
         throws CertPathValidatorException {
 
-        InputStream in = null;
-        OutputStream out = null;
-
         // Decrement the certificate counter
         remainingCerts--;
 
+        X509CertImpl currCertImpl = null;
         try {
-            X509Certificate responderCert = null;
-            boolean seekResponderCert = false;
-            X500Principal responderSubjectName = null;
-            X500Principal responderIssuerName = null;
-            BigInteger responderSerialNumber = null;
+            currCertImpl = X509CertImpl.toImpl((X509Certificate)cert);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        if (onlyEECert && currCertImpl.getBasicConstraints() != -1) {
+            if (DEBUG != null) {
+                DEBUG.println("Skipping revocation check, not end entity cert");
+            }
+            return;
+        }
 
-            boolean seekIssuerCert = true;
-            X509CertImpl issuerCertImpl = null;
-            X509CertImpl currCertImpl =
-                X509CertImpl.toImpl((X509Certificate)cert);
+        /*
+         * OCSP security property values, in the following order:
+         *   1. ocsp.responderURL
+         *   2. ocsp.responderCertSubjectName
+         *   3. ocsp.responderCertIssuerName
+         *   4. ocsp.responderCertSerialNumber
+         */
+        // should cache these properties to avoid calling every time?
+        String[] properties = getOCSPProperties();
+
+        // Check whether OCSP is feasible before seeking cert information
+        URI uri = getOCSPServerURI(currCertImpl, properties[0]);
 
-            /*
-             * OCSP security property values, in the following order:
-             *   1. ocsp.responderURL
-             *   2. ocsp.responderCertSubjectName
-             *   3. ocsp.responderCertIssuerName
-             *   4. ocsp.responderCertSerialNumber
-             */
-            String[] properties = getOCSPProperties();
+        // When responder's subject name is set then the issuer/serial
+        // properties are ignored
+        X500Principal responderSubjectName = null;
+        X500Principal responderIssuerName = null;
+        BigInteger responderSerialNumber = null;
+        if (properties[1] != null) {
+            responderSubjectName = new X500Principal(properties[1]);
+        } else if (properties[2] != null && properties[3] != null) {
+            responderIssuerName = new X500Principal(properties[2]);
+            // remove colon or space separators
+            String value = stripOutSeparators(properties[3]);
+            responderSerialNumber = new BigInteger(value, 16);
+        } else if (properties[2] != null || properties[3] != null) {
+            throw new CertPathValidatorException(
+                "Must specify both ocsp.responderCertIssuerName and " +
+                "ocsp.responderCertSerialNumber properties");
+        }
 
-            // Check whether OCSP is feasible before seeking cert information
-            URL url = getOCSPServerURL(currCertImpl, properties);
+        // If the OCSP responder cert properties are set then the
+        // identified cert must be located in the trust anchors or
+        // in the cert stores.
+        boolean seekResponderCert = false;
+        if (responderSubjectName != null || responderIssuerName != null) {
+            seekResponderCert = true;
+        }
 
-            // When responder's subject name is set then the issuer/serial
-            // properties are ignored
-            if (properties[1] != null) {
-                responderSubjectName = new X500Principal(properties[1]);
+        // Set the issuer certificate to the next cert in the chain
+        // (unless we're processing the final cert).
+        X509Certificate issuerCert = null;
+        boolean seekIssuerCert = true;
+        X509Certificate responderCert = null;
+        if (remainingCerts < certs.length) {
+            issuerCert = certs[remainingCerts];
+            seekIssuerCert = false; // done
 
-            } else if (properties[2] != null && properties[3] != null) {
-                responderIssuerName = new X500Principal(properties[2]);
-                // remove colon or space separators
-                String value = stripOutSeparators(properties[3]);
-                responderSerialNumber = new BigInteger(value, 16);
+            // By default, the OCSP responder's cert is the same as the
+            // issuer of the cert being validated.
+            if (!seekResponderCert) {
+                responderCert = issuerCert;
+                if (DEBUG != null) {
+                    DEBUG.println("Responder's certificate is the same " +
+                        "as the issuer of the certificate being validated");
+                }
+            }
+        }
 
-            } else if (properties[2] != null || properties[3] != null) {
-                throw new CertPathValidatorException(
-                    "Must specify both ocsp.responderCertIssuerName and " +
-                    "ocsp.responderCertSerialNumber properties");
+        // Check anchor certs for:
+        //    - the issuer cert (of the cert being validated)
+        //    - the OCSP responder's cert
+        if (seekIssuerCert || seekResponderCert) {
+
+            if (DEBUG != null && seekResponderCert) {
+                DEBUG.println("Searching trust anchors for responder's " +
+                    "certificate");
             }
 
-            // If the OCSP responder cert properties are set then the
-            // identified cert must be located in the trust anchors or
-            // in the cert stores.
-            if (responderSubjectName != null || responderIssuerName != null) {
-                seekResponderCert = true;
+            // Extract the anchor certs
+            Iterator<TrustAnchor> anchors
+                = pkixParams.getTrustAnchors().iterator();
+            if (!anchors.hasNext()) {
+                throw new CertPathValidatorException(
+                    "Must specify at least one trust anchor");
             }
 
-            // Set the issuer certificate to the next cert in the chain
-            // (unless we're processing the final cert).
-            if (remainingCerts < certs.length) {
-                issuerCertImpl = X509CertImpl.toImpl(certs[remainingCerts]);
-                seekIssuerCert = false; // done
+            X500Principal certIssuerName =
+                currCertImpl.getIssuerX500Principal();
+            while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) {
+
+                TrustAnchor anchor = anchors.next();
+                X509Certificate anchorCert = anchor.getTrustedCert();
+                X500Principal anchorSubjectName =
+                    anchorCert.getSubjectX500Principal();
+
+                if (dump) {
+                    System.out.println("Issuer DN is " + certIssuerName);
+                    System.out.println("Subject DN is " + anchorSubjectName);
+                }
+
+                // Check if anchor cert is the issuer cert
+                if (seekIssuerCert &&
+                    certIssuerName.equals(anchorSubjectName)) {
+
+                    issuerCert = anchorCert;
+                    seekIssuerCert = false; // done
 
-                // By default, the OCSP responder's cert is the same as the
-                // issuer of the cert being validated.
-                if (! seekResponderCert) {
-                    responderCert = certs[remainingCerts];
-                    if (DEBUG != null) {
-                        DEBUG.println("Responder's certificate is the same " +
-                            "as the issuer of the certificate being validated");
+                    // By default, the OCSP responder's cert is the same as
+                    // the issuer of the cert being validated.
+                    if (!seekResponderCert && responderCert == null) {
+                        responderCert = anchorCert;
+                        if (DEBUG != null) {
+                            DEBUG.println("Responder's certificate is the" +
+                                " same as the issuer of the certificate " +
+                                "being validated");
+                        }
+                    }
+                }
+
+                // Check if anchor cert is the responder cert
+                if (seekResponderCert) {
+                    // Satisfy the responder subject name property only, or
+                    // satisfy the responder issuer name and serial number
+                    // properties only
+                    if ((responderSubjectName != null &&
+                         responderSubjectName.equals(anchorSubjectName)) ||
+                        (responderIssuerName != null &&
+                         responderSerialNumber != null &&
+                         responderIssuerName.equals(
+                         anchorCert.getIssuerX500Principal()) &&
+                         responderSerialNumber.equals(
+                         anchorCert.getSerialNumber()))) {
+
+                        responderCert = anchorCert;
+                        seekResponderCert = false; // done
                     }
                 }
             }
+            if (issuerCert == null) {
+                throw new CertPathValidatorException(
+                    "No trusted certificate for " + currCertImpl.getIssuerDN());
+            }
 
-            // Check anchor certs for:
-            //    - the issuer cert (of the cert being validated)
-            //    - the OCSP responder's cert
-            if (seekIssuerCert || seekResponderCert) {
-
-                if (DEBUG != null && seekResponderCert) {
-                    DEBUG.println("Searching trust anchors for responder's " +
+            // Check cert stores if responder cert has not yet been found
+            if (seekResponderCert) {
+                if (DEBUG != null) {
+                    DEBUG.println("Searching cert stores for responder's " +
                         "certificate");
                 }
-
-                // Extract the anchor certs
-                Iterator anchors = pkixParams.getTrustAnchors().iterator();
-                if (! anchors.hasNext()) {
-                    throw new CertPathValidatorException(
-                        "Must specify at least one trust anchor");
+                X509CertSelector filter = null;
+                if (responderSubjectName != null) {
+                    filter = new X509CertSelector();
+                    filter.setSubject(responderSubjectName);
+                } else if (responderIssuerName != null &&
+                    responderSerialNumber != null) {
+                    filter = new X509CertSelector();
+                    filter.setIssuer(responderIssuerName);
+                    filter.setSerialNumber(responderSerialNumber);
                 }
-
-                X500Principal certIssuerName =
-                    currCertImpl.getIssuerX500Principal();
-                while (anchors.hasNext() &&
-                        (seekIssuerCert || seekResponderCert)) {
-
-                    TrustAnchor anchor = (TrustAnchor)anchors.next();
-                    X509Certificate anchorCert = anchor.getTrustedCert();
-                    X500Principal anchorSubjectName =
-                        anchorCert.getSubjectX500Principal();
-
-                    if (dump) {
-                        System.out.println("Issuer DN is " + certIssuerName);
-                        System.out.println("Subject DN is " +
-                            anchorSubjectName);
-                    }
-
-                    // Check if anchor cert is the issuer cert
-                    if (seekIssuerCert &&
-                        certIssuerName.equals(anchorSubjectName)) {
-
-                        issuerCertImpl = X509CertImpl.toImpl(anchorCert);
-                        seekIssuerCert = false; // done
-
-                        // By default, the OCSP responder's cert is the same as
-                        // the issuer of the cert being validated.
-                        if (! seekResponderCert && responderCert == null) {
-                            responderCert = anchorCert;
+                if (filter != null) {
+                    List<CertStore> certStores = pkixParams.getCertStores();
+                    for (CertStore certStore : certStores) {
+                        Iterator i = null;
+                        try {
+                            i = certStore.getCertificates(filter).iterator();
+                        } catch (CertStoreException cse) {
+                            // ignore and try next certStore
                             if (DEBUG != null) {
-                                DEBUG.println("Responder's certificate is the" +
-                                    " same as the issuer of the certificate " +
-                                    "being validated");
+                                DEBUG.println("CertStore exception:" + cse);
                             }
+                            continue;
                         }
-                    }
-
-                    // Check if anchor cert is the responder cert
-                    if (seekResponderCert) {
-                        // Satisfy the responder subject name property only, or
-                        // satisfy the responder issuer name and serial number
-                        // properties only
-                        if ((responderSubjectName != null &&
-                             responderSubjectName.equals(anchorSubjectName)) ||
-                            (responderIssuerName != null &&
-                             responderSerialNumber != null &&
-                             responderIssuerName.equals(
-                                anchorCert.getIssuerX500Principal()) &&
-                             responderSerialNumber.equals(
-                                anchorCert.getSerialNumber()))) {
-
-                            responderCert = anchorCert;
+                        if (i.hasNext()) {
+                            responderCert = (X509Certificate) i.next();
                             seekResponderCert = false; // done
-                        }
-                    }
-                }
-                if (issuerCertImpl == null) {
-                    throw new CertPathValidatorException(
-                        "No trusted certificate for " +
-                        currCertImpl.getIssuerDN());
-                }
-
-                // Check cert stores if responder cert has not yet been found
-                if (seekResponderCert) {
-                    if (DEBUG != null) {
-                        DEBUG.println("Searching cert stores for responder's " +
-                            "certificate");
-                    }
-                    X509CertSelector filter = null;
-                    if (responderSubjectName != null) {
-                        filter = new X509CertSelector();
-                        filter.setSubject(responderSubjectName.getName());
-                    } else if (responderIssuerName != null &&
-                        responderSerialNumber != null) {
-                        filter = new X509CertSelector();
-                        filter.setIssuer(responderIssuerName.getName());
-                        filter.setSerialNumber(responderSerialNumber);
-                    }
-                    if (filter != null) {
-                        List<CertStore> certStores = pkixParams.getCertStores();
-                        for (CertStore certStore : certStores) {
-                            Iterator i =
-                                certStore.getCertificates(filter).iterator();
-                            if (i.hasNext()) {
-                                responderCert = (X509Certificate) i.next();
-                                seekResponderCert = false; // done
-                                break;
-                            }
+                            break;
                         }
                     }
                 }
             }
-
-            // Could not find the certificate identified in the OCSP properties
-            if (seekResponderCert) {
-                throw new CertPathValidatorException(
-                    "Cannot find the responder's certificate " +
-                    "(set using the OCSP security properties).");
-            }
-
-            // Construct an OCSP Request
-            OCSPRequest ocspRequest =
-                new OCSPRequest(currCertImpl, issuerCertImpl);
-
-            // Use the URL to the OCSP service that was created earlier
-            HttpURLConnection con = (HttpURLConnection)url.openConnection();
-            if (DEBUG != null) {
-                DEBUG.println("connecting to OCSP service at: " + url);
-            }
-
-            // Indicate that both input and output will be performed,
-            // that the method is POST, and that the content length is
-            // the length of the byte array
+        }
 
-            con.setDoOutput(true);
-            con.setDoInput(true);
-            con.setRequestMethod("POST");
-            con.setRequestProperty("Content-type", "application/ocsp-request");
-            byte[] bytes = ocspRequest.encodeBytes();
-            CertId certId = ocspRequest.getCertId();
-
-            con.setRequestProperty("Content-length",
-                String.valueOf(bytes.length));
-            out = con.getOutputStream();
-            out.write(bytes);
-            out.flush();
-
-            // Check the response
-            if (DEBUG != null &&
-                con.getResponseCode() != HttpURLConnection.HTTP_OK) {
-                DEBUG.println("Received HTTP error: " + con.getResponseCode() +
-                    " - " + con.getResponseMessage());
-            }
-            in = con.getInputStream();
-
-            byte[] response = null;
-            int total = 0;
-            int contentLength = con.getContentLength();
-            if (contentLength != -1) {
-                response = new byte[contentLength];
-            } else {
-                response = new byte[2048];
-                contentLength = Integer.MAX_VALUE;
-            }
+        // Could not find the certificate identified in the OCSP properties
+        if (seekResponderCert) {
+            throw new CertPathValidatorException(
+                "Cannot find the responder's certificate " +
+                "(set using the OCSP security properties).");
+        }
 
-            while (total < contentLength) {
-                int count = in.read(response, total, response.length - total);
-                if (count < 0)
-                    break;
-
-                total += count;
-                if (total >= response.length && total < contentLength) {
-                    response = Arrays.copyOf(response, total * 2);
-                }
-            }
-            response = Arrays.copyOf(response, total);
-
-            OCSPResponse ocspResponse = new OCSPResponse(response, pkixParams,
-                responderCert);
-            // Check that response applies to the cert that was supplied
-            if (! certId.equals(ocspResponse.getCertId())) {
-                throw new CertPathValidatorException(
-                    "Certificate in the OCSP response does not match the " +
-                    "certificate supplied in the OCSP request.");
-            }
-            SerialNumber serialNumber = currCertImpl.getSerialNumberObject();
-            int certOCSPStatus = ocspResponse.getCertStatus(serialNumber);
-
-            if (DEBUG != null) {
-                DEBUG.println("Status of certificate (with serial number " +
-                    serialNumber.getNumber() + ") is: " +
-                    OCSPResponse.certStatusToText(certOCSPStatus));
-            }
+        CertId certId = null;
+        OCSPResponse response = null;
+        try {
+            certId = new CertId
+                (issuerCert, currCertImpl.getSerialNumberObject());
+            response = OCSP.check(Collections.singletonList(certId), uri,
+                responderCert, pkixParams.getDate());
+        } catch (IOException ioe) {
+            // should allow this to pass if network failures are acceptable
+            throw new CertPathValidatorException
+                ("Unable to send OCSP request", ioe);
+        }
 
-            if (certOCSPStatus == OCSPResponse.CERT_STATUS_REVOKED) {
-                Throwable t = new CertificateRevokedException(
-                        ocspResponse.getRevocationTime(),
-                        ocspResponse.getRevocationReason(),
-                        responderCert.getSubjectX500Principal(),
-                        ocspResponse.getSingleExtensions());
-                throw new CertPathValidatorException(t.getMessage(), t,
-                        null, -1, BasicReason.REVOKED);
-
-            } else if (certOCSPStatus == OCSPResponse.CERT_STATUS_UNKNOWN) {
-                throw new CertPathValidatorException(
-                    "Certificate's revocation status is unknown", null, cp,
-                    remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
-            }
-        } catch (Exception e) {
-            throw new CertPathValidatorException(e);
-        } finally {
-            if (in != null) {
-                try {
-                    in.close();
-                } catch (IOException ioe) {
-                    throw new CertPathValidatorException(ioe);
-                }
-            }
-            if (out != null) {
-                try {
-                    out.close();
-                } catch (IOException ioe) {
-                    throw new CertPathValidatorException(ioe);
-                }
-            }
+        RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
+        RevocationStatus.CertStatus certStatus = rs.getCertStatus();
+        if (certStatus == RevocationStatus.CertStatus.REVOKED) {
+            Throwable t = new CertificateRevokedException(
+                rs.getRevocationTime(), rs.getRevocationReason(),
+                responderCert.getSubjectX500Principal(),
+                rs.getSingleExtensions());
+            throw new CertPathValidatorException(t.getMessage(), t,
+                null, -1, BasicReason.REVOKED);
+        } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
+            throw new CertPathValidatorException(
+                "Certificate's revocation status is unknown", null, cp,
+                remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
         }
     }
 
@@ -431,20 +364,18 @@
      *   3. ocsp.responderCertIssuerName
      *   4. ocsp.responderCertSerialNumber
      */
-    private static URL getOCSPServerURL(X509CertImpl currCertImpl,
-        String[] properties)
-        throws CertificateParsingException, CertPathValidatorException {
+    private static URI getOCSPServerURI(X509CertImpl currCertImpl,
+        String responderURL) throws CertPathValidatorException {
 
-        if (properties[0] != null) {
-           try {
-                return new URL(properties[0]);
-           } catch (java.net.MalformedURLException e) {
+        if (responderURL != null) {
+            try {
+                return new URI(responderURL);
+            } catch (URISyntaxException e) {
                 throw new CertPathValidatorException(e);
-           }
+            }
         }
 
         // Examine the certificate's AuthorityInfoAccess extension
-
         AuthorityInfoAccessExtension aia =
             currCertImpl.getAuthorityInfoAccessExtension();
         if (aia == null) {
@@ -459,13 +390,8 @@
 
                 GeneralName generalName = description.getAccessLocation();
                 if (generalName.getType() == GeneralNameInterface.NAME_URI) {
-                    try {
-                        URIName uri = (URIName) generalName.getName();
-                        return (new URL(uri.getName()));
-
-                    } catch (java.net.MalformedURLException e) {
-                        throw new CertPathValidatorException(e);
-                    }
+                    URIName uri = (URIName) generalName.getName();
+                    return uri.getURI();
                 }
             }
         }
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright 2003-2004 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 2003-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
@@ -26,9 +26,9 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
-import java.security.cert.CertPathValidatorException;
+import java.util.Collections;
+import java.util.List;
 import sun.misc.HexDumpEncoder;
-import sun.security.x509.*;
 import sun.security.util.*;
 
 /**
@@ -77,47 +77,33 @@
     private static final Debug debug = Debug.getInstance("certpath");
     private static final boolean dump = false;
 
-    // Serial number of the certificates to be checked for revocation
-    private SerialNumber serialNumber;
-
-    // Issuer's certificate (for computing certId hash values)
-    private X509CertImpl issuerCert;
-
-    // CertId of the certificate to be checked
-    private CertId certId = null;
+    // List of request CertIds
+    private final List<CertId> certIds;
 
     /*
      * Constructs an OCSPRequest. This constructor is used
      * to construct an unsigned OCSP Request for a single user cert.
      */
-    // used by OCSPChecker
-    OCSPRequest(X509CertImpl userCert, X509CertImpl issuerCert)
-        throws CertPathValidatorException {
-
-        if (issuerCert == null) {
-            throw new CertPathValidatorException("Null IssuerCertificate");
-        }
-        this.issuerCert = issuerCert;
-        serialNumber = userCert.getSerialNumberObject();
+    OCSPRequest(CertId certId) {
+        this.certIds = Collections.singletonList(certId);
     }
 
-    // used by OCSPChecker
+    OCSPRequest(List<CertId> certIds) {
+        this.certIds = certIds;
+    }
+
     byte[] encodeBytes() throws IOException {
 
         // encode tbsRequest
         DerOutputStream tmp = new DerOutputStream();
-        DerOutputStream derSingleReqList  = new DerOutputStream();
-        SingleRequest singleRequest = null;
-
-        try {
-            singleRequest = new SingleRequest(issuerCert, serialNumber);
-        } catch (Exception e) {
-            throw new IOException("Error encoding OCSP request");
+        DerOutputStream requestsOut = new DerOutputStream();
+        for (CertId certId : certIds) {
+            DerOutputStream certIdOut = new DerOutputStream();
+            certId.encode(certIdOut);
+            requestsOut.write(DerValue.tag_Sequence, certIdOut);
         }
 
-        certId = singleRequest.getCertId();
-        singleRequest.encode(derSingleReqList);
-        tmp.write(DerValue.tag_Sequence, derSingleReqList);
+        tmp.write(DerValue.tag_Sequence, requestsOut);
         // No extensions supported
         DerOutputStream tbsRequest = new DerOutputStream();
         tbsRequest.write(DerValue.tag_Sequence, tmp);
@@ -130,35 +116,14 @@
 
         if (dump) {
             HexDumpEncoder hexEnc = new HexDumpEncoder();
-            System.out.println ("OCSPRequest bytes are... ");
+            System.out.println("OCSPRequest bytes are... ");
             System.out.println(hexEnc.encode(bytes));
         }
 
-        return(bytes);
-    }
-
-    // used by OCSPChecker
-    CertId getCertId() {
-        return certId;
+        return bytes;
     }
 
-    private static class SingleRequest {
-        private CertId certId;
-
-        // No extensions are set
-
-        private SingleRequest(X509CertImpl cert, SerialNumber serialNo) throws Exception {
-            certId = new CertId(cert, serialNo);
-        }
-
-        private void encode(DerOutputStream out) throws IOException {
-            DerOutputStream tmp = new DerOutputStream();
-            certId.encode(tmp);
-            out.write(DerValue.tag_Sequence, tmp);
-        }
-
-        private CertId getCertId() {
-            return certId;
-        }
+    List<CertId> getCertIds() {
+        return certIds;
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed Jul 05 17:01:09 2017 +0200
@@ -28,17 +28,16 @@
 import java.io.*;
 import java.math.BigInteger;
 import java.security.*;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateParsingException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.CRLReason;
 import java.security.cert.X509Certificate;
-import java.security.cert.PKIXParameters;
-import javax.security.auth.x500.X500Principal;
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.Iterator;
 import sun.misc.HexDumpEncoder;
 import sun.security.x509.*;
 import sun.security.util.*;
@@ -113,32 +112,29 @@
  * @author      Ram Marti
  */
 
-class OCSPResponse {
+public final class OCSPResponse {
 
-    // Certificate status CHOICE
-    public static final int CERT_STATUS_GOOD = 0;
-    public static final int CERT_STATUS_REVOKED = 1;
-    public static final int CERT_STATUS_UNKNOWN = 2;
+    public enum ResponseStatus {
+        SUCCESSFUL,            // Response has valid confirmations
+        MALFORMED_REQUEST,     // Illegal confirmation request
+        INTERNAL_ERROR,        // Internal error in issuer
+        TRY_LATER,             // Try again later
+        UNUSED,                // is not used
+        SIG_REQUIRED,          // Must sign the request
+        UNAUTHORIZED           // Request unauthorized
+    };
+    private static ResponseStatus[] rsvalues = ResponseStatus.values();
 
     private static final Debug DEBUG = Debug.getInstance("certpath");
     private static final boolean dump = false;
-    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID;
-    private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID;
-    static {
-        ObjectIdentifier tmp1 = null;
-        ObjectIdentifier tmp2 = null;
-        try {
-            tmp1 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.1");
-            tmp2 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.2");
-        } catch (Exception e) {
-            // should not happen; log and exit
-        }
-        OCSP_BASIC_RESPONSE_OID = tmp1;
-        OCSP_NONCE_EXTENSION_OID = tmp2;
-    }
+    private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
+        ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
+    private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
+        ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
 
-    // OCSP response status code
-    private static final int OCSP_RESPONSE_OK = 0;
+    private static final int CERT_STATUS_GOOD = 0;
+    private static final int CERT_STATUS_REVOKED = 1;
+    private static final int CERT_STATUS_UNKNOWN = 2;
 
     // ResponderID CHOICE tags
     private static final int NAME_TAG = 1;
@@ -147,7 +143,8 @@
     // Object identifier for the OCSPSigning key purpose
     private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
 
-    private SingleResponse singleResponse;
+    private final ResponseStatus responseStatus;
+    private final Map<CertId, SingleResponse> singleResponseMap;
 
     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
     // validity of OCSP responses
@@ -159,301 +156,300 @@
     /*
      * Create an OCSP response from its ASN.1 DER encoding.
      */
-    // used by OCSPChecker
-    OCSPResponse(byte[] bytes, PKIXParameters params,
+    OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
         X509Certificate responderCert)
         throws IOException, CertPathValidatorException {
 
-        try {
-            int responseStatus;
-            ObjectIdentifier  responseType;
-            int version;
-            CertificateIssuerName responderName = null;
-            Date producedAtDate;
-            AlgorithmId sigAlgId;
-            byte[] ocspNonce;
+        // OCSPResponse
+        if (dump) {
+            HexDumpEncoder hexEnc = new HexDumpEncoder();
+            System.out.println("OCSPResponse bytes are...");
+            System.out.println(hexEnc.encode(bytes));
+        }
+        DerValue der = new DerValue(bytes);
+        if (der.tag != DerValue.tag_Sequence) {
+            throw new IOException("Bad encoding in OCSP response: " +
+                "expected ASN.1 SEQUENCE tag.");
+        }
+        DerInputStream derIn = der.getData();
 
-            // OCSPResponse
-            if (dump) {
-                HexDumpEncoder hexEnc = new HexDumpEncoder();
-                System.out.println("OCSPResponse bytes are...");
-                System.out.println(hexEnc.encode(bytes));
-            }
-            DerValue der = new DerValue(bytes);
-            if (der.tag != DerValue.tag_Sequence) {
-                throw new IOException("Bad encoding in OCSP response: " +
-                    "expected ASN.1 SEQUENCE tag.");
-            }
-            DerInputStream derIn = der.getData();
-
-            // responseStatus
-            responseStatus = derIn.getEnumerated();
-            if (DEBUG != null) {
-                DEBUG.println("OCSP response: " +
-                    responseToText(responseStatus));
-            }
-            if (responseStatus != OCSP_RESPONSE_OK) {
-                throw new CertPathValidatorException(
-                    "OCSP Response Failure: " +
-                        responseToText(responseStatus));
-            }
+        // responseStatus
+        int status = derIn.getEnumerated();
+        if (status >= 0 && status < rsvalues.length) {
+            responseStatus = rsvalues[status];
+        } else {
+            // unspecified responseStatus
+            throw new IOException("Unknown OCSPResponse status: " + status);
+        }
+        if (DEBUG != null) {
+            DEBUG.println("OCSP response status: " + responseStatus);
+        }
+        if (responseStatus != ResponseStatus.SUCCESSFUL) {
+            // no need to continue, responseBytes are not set.
+            singleResponseMap = Collections.emptyMap();
+            return;
+        }
 
-            // responseBytes
-            der = derIn.getDerValue();
-            if (! der.isContextSpecific((byte)0)) {
-                throw new IOException("Bad encoding in responseBytes element " +
-                    "of OCSP response: expected ASN.1 context specific tag 0.");
-            };
-            DerValue tmp = der.data.getDerValue();
-            if (tmp.tag != DerValue.tag_Sequence) {
-                throw new IOException("Bad encoding in responseBytes element " +
-                    "of OCSP response: expected ASN.1 SEQUENCE tag.");
-            }
+        // responseBytes
+        der = derIn.getDerValue();
+        if (!der.isContextSpecific((byte)0)) {
+            throw new IOException("Bad encoding in responseBytes element " +
+                "of OCSP response: expected ASN.1 context specific tag 0.");
+        }
+        DerValue tmp = der.data.getDerValue();
+        if (tmp.tag != DerValue.tag_Sequence) {
+            throw new IOException("Bad encoding in responseBytes element " +
+                "of OCSP response: expected ASN.1 SEQUENCE tag.");
+        }
 
-            // responseType
-            derIn = tmp.data;
-            responseType = derIn.getOID();
-            if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
-                if (DEBUG != null) {
-                    DEBUG.println("OCSP response type: basic");
-                }
-            } else {
-                if (DEBUG != null) {
-                    DEBUG.println("OCSP response type: " + responseType);
-                }
-                throw new IOException("Unsupported OCSP response type: " +
-                    responseType);
+        // responseType
+        derIn = tmp.data;
+        ObjectIdentifier responseType = derIn.getOID();
+        if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) {
+            if (DEBUG != null) {
+                DEBUG.println("OCSP response type: basic");
+            }
+        } else {
+            if (DEBUG != null) {
+                DEBUG.println("OCSP response type: " + responseType);
             }
+            throw new IOException("Unsupported OCSP response type: " +
+                responseType);
+        }
 
-            // BasicOCSPResponse
-            DerInputStream basicOCSPResponse =
-                new DerInputStream(derIn.getOctetString());
+        // BasicOCSPResponse
+        DerInputStream basicOCSPResponse =
+            new DerInputStream(derIn.getOctetString());
 
-            DerValue[]  seqTmp = basicOCSPResponse.getSequence(2);
-            DerValue responseData = seqTmp[0];
+        DerValue[] seqTmp = basicOCSPResponse.getSequence(2);
+        if (seqTmp.length < 3) {
+            throw new IOException("Unexpected BasicOCSPResponse value");
+        }
 
-            // Need the DER encoded ResponseData to verify the signature later
-            byte[] responseDataDer = seqTmp[0].toByteArray();
+        DerValue responseData = seqTmp[0];
+
+        // Need the DER encoded ResponseData to verify the signature later
+        byte[] responseDataDer = seqTmp[0].toByteArray();
 
-            // tbsResponseData
-            if (responseData.tag != DerValue.tag_Sequence) {
-                throw new IOException("Bad encoding in tbsResponseData " +
-                    " element of OCSP response: expected ASN.1 SEQUENCE tag.");
-            }
-            DerInputStream seqDerIn = responseData.data;
-            DerValue seq = seqDerIn.getDerValue();
+        // tbsResponseData
+        if (responseData.tag != DerValue.tag_Sequence) {
+            throw new IOException("Bad encoding in tbsResponseData " +
+                "element of OCSP response: expected ASN.1 SEQUENCE tag.");
+        }
+        DerInputStream seqDerIn = responseData.data;
+        DerValue seq = seqDerIn.getDerValue();
 
-            // version
-            if (seq.isContextSpecific((byte)0)) {
-                // seq[0] is version
-                if (seq.isConstructed() && seq.isContextSpecific()) {
-                    //System.out.println ("version is available");
-                    seq = seq.data.getDerValue();
-                    version = seq.getInteger();
-                    if (seq.data.available() != 0) {
-                        throw new IOException("Bad encoding in version " +
-                            " element of OCSP response: bad format");
-                    }
-                    seq = seqDerIn.getDerValue();
-                }
-            }
-
-            // responderID
-            short tag = (byte)(seq.tag & 0x1f);
-            if (tag == NAME_TAG) {
-                responderName = new CertificateIssuerName(seq.getData());
-                if (DEBUG != null) {
-                    DEBUG.println("OCSP Responder name: " + responderName);
+        // version
+        if (seq.isContextSpecific((byte)0)) {
+            // seq[0] is version
+            if (seq.isConstructed() && seq.isContextSpecific()) {
+                //System.out.println ("version is available");
+                seq = seq.data.getDerValue();
+                int version = seq.getInteger();
+                if (seq.data.available() != 0) {
+                    throw new IOException("Bad encoding in version " +
+                        " element of OCSP response: bad format");
                 }
-            } else if (tag == KEY_TAG) {
-                // Ignore, for now
-            } else {
-                throw new IOException("Bad encoding in responderID element " +
-                    "of OCSP response: expected ASN.1 context specific tag 0 " +
-                    "or 1");
+                seq = seqDerIn.getDerValue();
             }
+        }
 
-            // producedAt
-            seq = seqDerIn.getDerValue();
-            producedAtDate = seq.getGeneralizedTime();
+        // responderID
+        short tag = (byte)(seq.tag & 0x1f);
+        if (tag == NAME_TAG) {
+            if (DEBUG != null) {
+                X500Name responderName = new X500Name(seq.getData());
+                DEBUG.println("OCSP Responder name: " + responderName);
+            }
+        } else if (tag == KEY_TAG) {
+            // Ignore, for now
+        } else {
+            throw new IOException("Bad encoding in responderID element of " +
+                "OCSP response: expected ASN.1 context specific tag 0 or 1");
+        }
 
-            // responses
-            DerValue[] singleResponseDer = seqDerIn.getSequence(1);
-            // Examine only the first response
-            singleResponse = new SingleResponse(singleResponseDer[0]);
+        // producedAt
+        seq = seqDerIn.getDerValue();
+        if (DEBUG != null) {
+            Date producedAtDate = seq.getGeneralizedTime();
+            DEBUG.println("OCSP response produced at: " + producedAtDate);
+        }
 
-            // responseExtensions
-            if (seqDerIn.available() > 0) {
-                seq = seqDerIn.getDerValue();
-                if (seq.isContextSpecific((byte)1)) {
-                    DerValue[]  responseExtDer = seq.data.getSequence(3);
-                    Extension[] responseExtension =
-                        new Extension[responseExtDer.length];
-                    for (int i = 0; i < responseExtDer.length; i++) {
-                        responseExtension[i] = new Extension(responseExtDer[i]);
-                        if (DEBUG != null) {
-                            DEBUG.println("OCSP extension: " +
-                                responseExtension[i]);
-                        }
-                        if ((responseExtension[i].getExtensionId()).equals(
-                            OCSP_NONCE_EXTENSION_OID)) {
-                            ocspNonce =
-                                responseExtension[i].getExtensionValue();
+        // responses
+        DerValue[] singleResponseDer = seqDerIn.getSequence(1);
+        singleResponseMap
+            = new HashMap<CertId, SingleResponse>(singleResponseDer.length);
+        if (DEBUG != null) {
+            DEBUG.println("OCSP number of SingleResponses: "
+                + singleResponseDer.length);
+        }
+        for (int i = 0; i < singleResponseDer.length; i++) {
+            SingleResponse singleResponse
+                = new SingleResponse(singleResponseDer[i]);
+            singleResponseMap.put(singleResponse.getCertId(), singleResponse);
+        }
 
-                        } else if (responseExtension[i].isCritical())  {
-                            throw new IOException(
-                                "Unsupported OCSP critical extension: " +
-                                responseExtension[i].getExtensionId());
-                        }
+        // responseExtensions
+        if (seqDerIn.available() > 0) {
+            seq = seqDerIn.getDerValue();
+            if (seq.isContextSpecific((byte)1)) {
+                DerValue[] responseExtDer = seq.data.getSequence(3);
+                for (int i = 0; i < responseExtDer.length; i++) {
+                    Extension responseExtension
+                        = new Extension(responseExtDer[i]);
+                    if (DEBUG != null) {
+                        DEBUG.println("OCSP extension: " + responseExtension);
+                    }
+                    if (responseExtension.getExtensionId().equals(
+                        OCSP_NONCE_EXTENSION_OID)) {
+                        /*
+                        ocspNonce =
+                            responseExtension[i].getExtensionValue();
+                         */
+                    } else if (responseExtension.isCritical())  {
+                        throw new IOException(
+                            "Unsupported OCSP critical extension: " +
+                            responseExtension.getExtensionId());
                     }
                 }
             }
-
-            // signatureAlgorithmId
-            sigAlgId = AlgorithmId.parse(seqTmp[1]);
+        }
 
-            // signature
-            byte[] signature = seqTmp[2].getBitString();
-            X509CertImpl[] x509Certs = null;
+        // signatureAlgorithmId
+        AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
+
+        // signature
+        byte[] signature = seqTmp[2].getBitString();
+        X509CertImpl[] x509Certs = null;
 
-            // if seq[3] is available , then it is a sequence of certificates
-            if (seqTmp.length > 3) {
-                // certs are available
-                DerValue seqCert = seqTmp[3];
-                if (! seqCert.isContextSpecific((byte)0)) {
-                    throw new IOException("Bad encoding in certs element " +
-                    "of OCSP response: expected ASN.1 context specific tag 0.");
-                }
-                DerValue[] certs = (seqCert.getData()).getSequence(3);
-                x509Certs = new X509CertImpl[certs.length];
+        // if seq[3] is available , then it is a sequence of certificates
+        if (seqTmp.length > 3) {
+            // certs are available
+            DerValue seqCert = seqTmp[3];
+            if (!seqCert.isContextSpecific((byte)0)) {
+                throw new IOException("Bad encoding in certs element of " +
+                    "OCSP response: expected ASN.1 context specific tag 0.");
+            }
+            DerValue[] certs = seqCert.getData().getSequence(3);
+            x509Certs = new X509CertImpl[certs.length];
+            try {
                 for (int i = 0; i < certs.length; i++) {
                     x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
                 }
+            } catch (CertificateException ce) {
+                throw new IOException("Bad encoding in X509 Certificate", ce);
             }
+        }
 
-            // Check whether the cert returned by the responder is trusted
-            if (x509Certs != null && x509Certs[0] != null) {
-                X509CertImpl cert = x509Certs[0];
+        // Check whether the cert returned by the responder is trusted
+        if (x509Certs != null && x509Certs[0] != null) {
+            X509CertImpl cert = x509Certs[0];
 
-                // First check if the cert matches the responder cert which
-                // was set locally.
-                if (cert.equals(responderCert)) {
-                    // cert is trusted, now verify the signed response
+            // First check if the cert matches the responder cert which
+            // was set locally.
+            if (cert.equals(responderCert)) {
+                // cert is trusted, now verify the signed response
 
-                // Next check if the cert was issued by the responder cert
-                // which was set locally.
-                } else if (cert.getIssuerX500Principal().equals(
-                    responderCert.getSubjectX500Principal())) {
+            // Next check if the cert was issued by the responder cert
+            // which was set locally.
+            } else if (cert.getIssuerX500Principal().equals(
+                responderCert.getSubjectX500Principal())) {
 
-                    // Check for the OCSPSigning key purpose
+                // Check for the OCSPSigning key purpose
+                try {
                     List<String> keyPurposes = cert.getExtendedKeyUsage();
                     if (keyPurposes == null ||
                         !keyPurposes.contains(KP_OCSP_SIGNING_OID)) {
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate is not " +
-                                "valid for signing OCSP responses.");
-                        }
                         throw new CertPathValidatorException(
                             "Responder's certificate not valid for signing " +
                             "OCSP responses");
                     }
-
-                    // check the validity
-                    try {
-                        Date dateCheckedAgainst = params.getDate();
-                        if (dateCheckedAgainst == null) {
-                            cert.checkValidity();
-                        } else {
-                            cert.checkValidity(dateCheckedAgainst);
-                        }
-                    } catch (GeneralSecurityException e) {
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate is not " +
-                                "within the validity period.");
-                        }
-                        throw new CertPathValidatorException(
-                            "Responder's certificate not within the " +
-                            "validity period");
-                    }
+                } catch (CertificateParsingException cpe) {
+                    // assume cert is not valid for signing
+                    throw new CertPathValidatorException(
+                        "Responder's certificate not valid for signing " +
+                        "OCSP responses", cpe);
+                }
 
-                    // check for revocation
-                    //
-                    // A CA may specify that an OCSP client can trust a
-                    // responder for the lifetime of the responder's
-                    // certificate. The CA does so by including the
-                    // extension id-pkix-ocsp-nocheck.
-                    //
-                    Extension noCheck =
-                            cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
-                    if (noCheck != null) {
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate includes " +
-                                "the extension id-pkix-ocsp-nocheck.");
-                        }
+                // check the validity
+                try {
+                    if (dateCheckedAgainst == null) {
+                        cert.checkValidity();
                     } else {
-                        // we should do the revocating checking of the
-                        // authorized responder in a future update.
+                        cert.checkValidity(dateCheckedAgainst);
                     }
+                } catch (GeneralSecurityException e) {
+                    throw new CertPathValidatorException(
+                        "Responder's certificate not within the " +
+                        "validity period", e);
+                }
 
-                    // verify the signature
-                    try {
-                        cert.verify(responderCert.getPublicKey());
-                        responderCert = cert;
-                        // cert is trusted, now verify the signed response
-
-                    } catch (GeneralSecurityException e) {
-                        responderCert = null;
+                // check for revocation
+                //
+                // A CA may specify that an OCSP client can trust a
+                // responder for the lifetime of the responder's
+                // certificate. The CA does so by including the
+                // extension id-pkix-ocsp-nocheck.
+                //
+                Extension noCheck =
+                    cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
+                if (noCheck != null) {
+                    if (DEBUG != null) {
+                        DEBUG.println("Responder's certificate includes " +
+                            "the extension id-pkix-ocsp-nocheck.");
                     }
                 } else {
-                    if (DEBUG != null) {
-                        DEBUG.println("Responder's certificate is not " +
-                            "authorized to sign OCSP responses.");
-                    }
-                    throw new CertPathValidatorException(
-                        "Responder's certificate not authorized to sign " +
-                        "OCSP responses");
+                    // we should do the revocation checking of the
+                    // authorized responder in a future update.
                 }
-            }
 
-            // Confirm that the signed response was generated using the public
-            // key from the trusted responder cert
-            if (responderCert != null) {
+                // verify the signature
+                try {
+                    cert.verify(responderCert.getPublicKey());
+                    responderCert = cert;
+                    // cert is trusted, now verify the signed response
 
-                if (! verifyResponse(responseDataDer, responderCert,
-                    sigAlgId, signature, params)) {
-                    if (DEBUG != null) {
-                        DEBUG.println("Error verifying OCSP Responder's " +
-                            "signature");
-                    }
-                    throw new CertPathValidatorException(
-                        "Error verifying OCSP Responder's signature");
+                } catch (GeneralSecurityException e) {
+                    responderCert = null;
                 }
             } else {
-                // Need responder's cert in order to verify the signature
-                if (DEBUG != null) {
-                    DEBUG.println("Unable to verify OCSP Responder's " +
-                        "signature");
-                }
+                throw new CertPathValidatorException(
+                    "Responder's certificate is not authorized to sign " +
+                    "OCSP responses");
+            }
+        }
+
+        // Confirm that the signed response was generated using the public
+        // key from the trusted responder cert
+        if (responderCert != null) {
+            if (!verifyResponse(responseDataDer, responderCert,
+                sigAlgId, signature)) {
                 throw new CertPathValidatorException(
-                    "Unable to verify OCSP Responder's signature");
+                    "Error verifying OCSP Responder's signature");
             }
-        } catch (CertPathValidatorException cpve) {
-            throw cpve;
-        } catch (Exception e) {
-            throw new CertPathValidatorException(e);
+        } else {
+            // Need responder's cert in order to verify the signature
+            throw new CertPathValidatorException(
+                "Unable to verify OCSP Responder's signature");
         }
     }
 
+    /**
+     * Returns the OCSP ResponseStatus.
+     */
+    ResponseStatus getResponseStatus() {
+        return responseStatus;
+    }
+
     /*
      * Verify the signature of the OCSP response.
      * The responder's cert is implicitly trusted.
      */
     private boolean verifyResponse(byte[] responseData, X509Certificate cert,
-        AlgorithmId sigAlgId, byte[] signBytes, PKIXParameters params)
-        throws SignatureException {
+        AlgorithmId sigAlgId, byte[] signBytes)
+        throws CertPathValidatorException {
 
         try {
-
             Signature respSignature = Signature.getInstance(sigAlgId.getName());
             respSignature.initVerify(cert);
             respSignature.update(responseData);
@@ -472,92 +468,33 @@
                 return false;
             }
         } catch (InvalidKeyException ike) {
-            throw new SignatureException(ike);
-
+            throw new CertPathValidatorException(ike);
         } catch (NoSuchAlgorithmException nsae) {
-            throw new SignatureException(nsae);
+            throw new CertPathValidatorException(nsae);
+        } catch (SignatureException se) {
+            throw new CertPathValidatorException(se);
         }
     }
 
-    /*
-     * Return the revocation status code for a given certificate.
-     */
-    // used by OCSPChecker
-    int getCertStatus(SerialNumber sn) {
-        // ignore serial number for now; if we support multiple
-        // requests/responses then it will be used
-        return singleResponse.getStatus();
-    }
-
-    // used by OCSPChecker
-    CertId getCertId() {
-        return singleResponse.getCertId();
-    }
-
-    Date getRevocationTime() {
-        return singleResponse.getRevocationTime();
-    }
-
-    CRLReason getRevocationReason() {
-        return singleResponse.getRevocationReason();
-    }
-
-    Map<String, java.security.cert.Extension> getSingleExtensions() {
-        return singleResponse.getSingleExtensions();
-    }
-
-    /*
-     * Map an OCSP response status code to a string.
+    /**
+     * Returns the SingleResponse of the specified CertId, or null if
+     * there is no response for that CertId.
      */
-    static private String responseToText(int status) {
-        switch (status)  {
-        case 0:
-            return "Successful";
-        case 1:
-            return "Malformed request";
-        case 2:
-            return "Internal error";
-        case 3:
-            return "Try again later";
-        case 4:
-            return "Unused status code";
-        case 5:
-            return "Request must be signed";
-        case 6:
-            return "Request is unauthorized";
-        default:
-            return ("Unknown status code: " + status);
-        }
-    }
-
-    /*
-     * Map a certificate's revocation status code to a string.
-     */
-    // used by OCSPChecker
-    static String certStatusToText(int certStatus) {
-        switch (certStatus)  {
-        case 0:
-            return "Good";
-        case 1:
-            return "Revoked";
-        case 2:
-            return "Unknown";
-        default:
-            return ("Unknown certificate status code: " + certStatus);
-        }
+    SingleResponse getSingleResponse(CertId certId) {
+        return singleResponseMap.get(certId);
     }
 
     /*
      * A class representing a single OCSP response.
      */
-    private class SingleResponse {
-        private CertId certId;
-        private int certStatus;
-        private Date thisUpdate;
-        private Date nextUpdate;
-        private Date revocationTime;
-        private CRLReason revocationReason = CRLReason.UNSPECIFIED;
-        private HashMap<String, java.security.cert.Extension> singleExtensions;
+    final static class SingleResponse implements OCSP.RevocationStatus {
+        private final CertId certId;
+        private final CertStatus certStatus;
+        private final Date thisUpdate;
+        private final Date nextUpdate;
+        private final Date revocationTime;
+        private final CRLReason revocationReason;
+        private final Map<String, java.security.cert.Extension> singleExtensions;
 
         private SingleResponse(DerValue der) throws IOException {
             if (der.tag != DerValue.tag_Sequence) {
@@ -568,35 +505,48 @@
             certId = new CertId(tmp.getDerValue().data);
             DerValue derVal = tmp.getDerValue();
             short tag = (byte)(derVal.tag & 0x1f);
-            if (tag ==  CERT_STATUS_GOOD) {
-                certStatus = CERT_STATUS_GOOD;
-            } else if (tag == CERT_STATUS_REVOKED) {
-                certStatus = CERT_STATUS_REVOKED;
+            if (tag ==  CERT_STATUS_REVOKED) {
+                certStatus = CertStatus.REVOKED;
                 revocationTime = derVal.data.getGeneralizedTime();
                 if (derVal.data.available() != 0) {
-                    int reason = derVal.getEnumerated();
-                    // if reason out-of-range just leave as UNSPECIFIED
-                    if (reason >= 0 && reason < values.length) {
-                        revocationReason = values[reason];
+                    DerValue dv = derVal.data.getDerValue();
+                    tag = (byte)(dv.tag & 0x1f);
+                    if (tag == 0) {
+                        int reason = dv.data.getEnumerated();
+                        // if reason out-of-range just leave as UNSPECIFIED
+                        if (reason >= 0 && reason < values.length) {
+                            revocationReason = values[reason];
+                        } else {
+                            revocationReason = CRLReason.UNSPECIFIED;
+                        }
+                    } else {
+                        revocationReason = CRLReason.UNSPECIFIED;
                     }
+                } else {
+                    revocationReason = CRLReason.UNSPECIFIED;
                 }
                 // RevokedInfo
                 if (DEBUG != null) {
                     DEBUG.println("Revocation time: " + revocationTime);
                     DEBUG.println("Revocation reason: " + revocationReason);
                 }
-
-            } else if (tag == CERT_STATUS_UNKNOWN) {
-                certStatus = CERT_STATUS_UNKNOWN;
-
             } else {
-                throw new IOException("Invalid certificate status");
+                revocationTime = null;
+                revocationReason = CRLReason.UNSPECIFIED;
+                if (tag == CERT_STATUS_GOOD) {
+                    certStatus = CertStatus.GOOD;
+                } else if (tag == CERT_STATUS_UNKNOWN) {
+                    certStatus = CertStatus.UNKNOWN;
+                } else {
+                    throw new IOException("Invalid certificate status");
+                }
             }
 
             thisUpdate = tmp.getGeneralizedTime();
 
             if (tmp.available() == 0)  {
                 // we are done
+                nextUpdate = null;
             } else {
                 derVal = tmp.getDerValue();
                 tag = (byte)(derVal.tag & 0x1f);
@@ -610,6 +560,8 @@
                         derVal = tmp.getDerValue();
                         tag = (byte)(derVal.tag & 0x1f);
                     }
+                } else {
+                    nextUpdate = null;
                 }
             }
             // singleExtensions
@@ -627,7 +579,11 @@
                             DEBUG.println("OCSP single extension: " + ext);
                         }
                     }
+                } else {
+                    singleExtensions = Collections.emptyMap();
                 }
+            } else {
+                singleExtensions = Collections.emptyMap();
             }
 
             long now = System.currentTimeMillis();
@@ -657,7 +613,7 @@
         /*
          * Return the certificate's revocation status code
          */
-        private int getStatus() {
+        @Override public CertStatus getCertStatus() {
             return certStatus;
         }
 
@@ -665,28 +621,28 @@
             return certId;
         }
 
-        private Date getRevocationTime() {
-            return revocationTime;
+        @Override public Date getRevocationTime() {
+            return (Date) revocationTime.clone();
         }
 
-        private CRLReason getRevocationReason() {
+        @Override public CRLReason getRevocationReason() {
             return revocationReason;
         }
 
-        private Map<String, java.security.cert.Extension> getSingleExtensions() {
-            return singleExtensions;
+        @Override
+        public Map<String, java.security.cert.Extension> getSingleExtensions() {
+            return Collections.unmodifiableMap(singleExtensions);
         }
 
         /**
          * Construct a string representation of a single OCSP response.
          */
-        public String toString() {
+        @Override public String toString() {
             StringBuilder sb = new StringBuilder();
             sb.append("SingleResponse:  \n");
             sb.append(certId);
-            sb.append("\nCertStatus: "+ certStatusToText(getCertStatus(null)) +
-                "\n");
-            if (certStatus == CERT_STATUS_REVOKED) {
+            sb.append("\nCertStatus: "+ certStatus + "\n");
+            if (certStatus == CertStatus.REVOKED) {
                 sb.append("revocationTime is " + revocationTime + "\n");
                 sb.append("revocationReason is " + revocationReason + "\n");
             }
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Wed Jul 05 17:01:09 2017 +0200
@@ -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
@@ -28,8 +28,6 @@
 import java.io.IOException;
 import java.security.AccessController;
 import java.security.InvalidAlgorithmParameterException;
-import java.security.PrivilegedAction;
-import java.security.Security;
 import java.security.cert.CertPath;
 import java.security.cert.CertPathParameters;
 import java.security.cert.CertPathValidatorException;
@@ -49,6 +47,7 @@
 import java.util.Date;
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
+import sun.security.action.GetBooleanSecurityPropertyAction;
 import sun.security.util.Debug;
 
 /**
@@ -67,7 +66,8 @@
     private List<PKIXCertPathChecker> userCheckers;
     private String sigProvider;
     private BasicChecker basicChecker;
-    private String ocspProperty;
+    private boolean ocspEnabled = false;
+    private boolean onlyEECert = false;
 
     /**
      * Default constructor.
@@ -253,13 +253,12 @@
 
         if (pkixParam.isRevocationEnabled()) {
             // Examine OCSP security property
-            ocspProperty = AccessController.doPrivileged(
-                new PrivilegedAction<String>() {
-                    public String run() {
-                        return
-                            Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP);
-                    }
-                });
+            ocspEnabled = AccessController.doPrivileged(
+                new GetBooleanSecurityPropertyAction
+                    (OCSPChecker.OCSP_ENABLE_PROP));
+            onlyEECert = AccessController.doPrivileged(
+                new GetBooleanSecurityPropertyAction
+                    ("com.sun.security.onlyCheckRevocationOfEECert"));
         }
     }
 
@@ -301,15 +300,15 @@
         if (pkixParam.isRevocationEnabled()) {
 
             // Use OCSP if it has been enabled
-            if ("true".equalsIgnoreCase(ocspProperty)) {
+            if (ocspEnabled) {
                 OCSPChecker ocspChecker =
-                    new OCSPChecker(cpOriginal, pkixParam);
+                    new OCSPChecker(cpOriginal, pkixParam, onlyEECert);
                 certPathCheckers.add(ocspChecker);
             }
 
             // Always use CRLs
-            CrlRevocationChecker revocationChecker =
-                new CrlRevocationChecker(anchor, pkixParam, certList);
+            CrlRevocationChecker revocationChecker = new
+                CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert);
             certPathCheckers.add(revocationChecker);
         }
 
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Wed Jul 05 17:01:09 2017 +0200
@@ -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
@@ -26,6 +26,7 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
+import java.security.AccessController;
 import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
 import java.security.Principal;
@@ -44,6 +45,7 @@
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.action.GetBooleanSecurityPropertyAction;
 import sun.security.x509.X500Name;
 import sun.security.x509.PKIXExtensions;
 import sun.security.util.Debug;
@@ -85,6 +87,7 @@
     private PublicKey finalPublicKey;
     private X509CertSelector targetSel;
     private List<CertStore> orderedCertStores;
+    private boolean onlyEECert = false;
 
     /**
      * Create an instance of <code>SunCertPathBuilder</code>.
@@ -97,6 +100,9 @@
         } catch (CertificateException e) {
             throw new CertPathBuilderException(e);
         }
+        onlyEECert = AccessController.doPrivileged(
+            new GetBooleanSecurityPropertyAction
+                ("com.sun.security.onlyCheckRevocationOfEECert"));
     }
 
     /**
@@ -256,7 +262,6 @@
 
     /*
      * Private build reverse method.
-     *
      */
     private void buildReverse(List<List<Vertex>> adjacencyList,
         LinkedList<X509Certificate> certPathList) throws Exception
@@ -296,7 +301,7 @@
             currentState.updateState(anchor);
             // init the crl checker
             currentState.crlChecker =
-                new CrlRevocationChecker(null, buildParams);
+                new CrlRevocationChecker(null, buildParams, null, onlyEECert);
             try {
                 depthFirstSearchReverse(null, currentState,
                 new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
@@ -341,10 +346,12 @@
         adjacencyList.add(new LinkedList<Vertex>());
 
         // init the crl checker
-        currentState.crlChecker = new CrlRevocationChecker(null, buildParams);
+        currentState.crlChecker
+            = new CrlRevocationChecker(null, buildParams, null, onlyEECert);
 
         depthFirstSearchForward(targetSubjectDN, currentState,
-          new ForwardBuilder(buildParams, targetSubjectDN, searchAllCertStores),
+          new ForwardBuilder
+              (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
           adjacencyList, certPathList);
     }
 
@@ -486,8 +493,8 @@
                     userCheckers.add(mustCheck, basicChecker);
                     mustCheck++;
                     if (buildParams.isRevocationEnabled()) {
-                        userCheckers.add(mustCheck,
-                            new CrlRevocationChecker(anchor, buildParams));
+                        userCheckers.add(mustCheck, new CrlRevocationChecker
+                            (anchor, buildParams, null, onlyEECert));
                         mustCheck++;
                     }
                 }
--- a/jdk/src/share/classes/sun/security/x509/AccessDescription.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/security/x509/AccessDescription.java	Wed Jul 05 17:01:09 2017 +0200
@@ -113,7 +113,7 @@
         } else {
             method = accessMethod.toString();
         }
-        return ("accessMethod: " + method +
+        return ("\n   accessMethod: " + method +
                 "\n   accessLocation: " + accessLocation.toString() + "\n");
     }
 }
--- a/jdk/src/share/classes/sun/util/LocaleServiceProviderPool.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/classes/sun/util/LocaleServiceProviderPool.java	Wed Jul 05 17:01:09 2017 +0200
@@ -39,8 +39,8 @@
 import java.util.ServiceConfigurationError;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
 import java.util.spi.LocaleServiceProvider;
+import sun.util.logging.PlatformLogger;
 import sun.util.resources.LocaleData;
 import sun.util.resources.OpenListResourceBundle;
 
@@ -122,10 +122,15 @@
                 }
             });
         }  catch (PrivilegedActionException e) {
-            Logger.getLogger("sun.util.LocaleServiceProviderPool").config(e.toString());
+            config(e.toString());
         }
     }
 
+    private static void config(String message) {
+        PlatformLogger logger = PlatformLogger.getLogger("sun.util.LocaleServiceProviderPool");
+        logger.config(message);
+    }
+
     /**
      * Lazy loaded set of available locales.
      * Loading all locales is a very long operation.
@@ -337,7 +342,7 @@
                     if (providersObj != null) {
                         return providersObj;
                     } else if (isObjectProvider) {
-                        Logger.getLogger("sun.util.LocaleServiceProviderPool").config(
+                        config(
                             "A locale sensitive service provider returned null for a localized objects,  which should not happen.  provider: " + lsp + " locale: " + requested);
                     }
                 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/util/logging/PlatformLogger.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,635 @@
+/*
+ * 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.util.logging;
+
+import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.MessageFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import sun.misc.JavaLangAccess;
+import sun.misc.SharedSecrets;
+
+/**
+ * Platform logger provides an API for the JRE components to log
+ * messages.  This enables the runtime components to eliminate the
+ * static dependency of the logging facility and also defers the
+ * java.util.logging initialization until it is enabled.
+ * In addition, the PlatformLogger API can be used if the logging
+ * module does not exist.
+ *
+ * If the logging facility is not enabled, the platform loggers
+ * will output log messages per the default logging configuration
+ * (see below). In this implementation, it does not log the
+ * the stack frame information issuing the log message.
+ *
+ * When the logging facility is enabled (at startup or runtime),
+ * the java.util.logging.Logger will be created for each platform
+ * logger and all log messages will be forwarded to the Logger
+ * to handle.
+ *
+ * Logging facility is "enabled" when one of the following
+ * conditions is met:
+ * 1) a system property "java.util.logging.config.class" or
+ *    "java.util.logging.config.file" is set
+ * 2) java.util.logging.LogManager or java.util.logging.Logger
+ *    is referenced that will trigger the logging initialization.
+ *
+ * Default logging configuration:
+ *   global logging level = INFO
+ *   handlers = java.util.logging.ConsoleHandler
+ *   java.util.logging.ConsoleHandler.level = INFO
+ *   java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
+ *
+ * Limitation:
+ * <JAVA_HOME>/lib/logging.properties is the system-wide logging
+ * configuration defined in the specification and read in the
+ * default case to configure any java.util.logging.Logger instances.
+ * Platform loggers will not detect if <JAVA_HOME>/lib/logging.properties
+ * is modified. In other words, unless the java.util.logging API
+ * is used at runtime or the logging system properties is set,
+ * the platform loggers will use the default setting described above.
+ * The platform loggers are designed for JDK developers use and
+ * this limitation can be workaround with setting
+ * -Djava.util.logging.config.file system property.
+ *
+ * @since 1.7
+ */
+public class PlatformLogger {
+    // Same values as java.util.logging.Level for easy mapping
+    public static final int OFF     = Integer.MAX_VALUE;
+    public static final int SEVERE  = 1000;
+    public static final int WARNING = 900;
+    public static final int INFO    = 800;
+    public static final int CONFIG  = 700;
+    public static final int FINE    = 500;
+    public static final int FINER   = 400;
+    public static final int FINEST  = 300;
+    public static final int ALL     = Integer.MIN_VALUE;
+
+    private static final int defaultLevel = INFO;
+    private static boolean loggingEnabled;
+    static {
+        loggingEnabled = AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>() {
+                public Boolean run() {
+                    String cname = System.getProperty("java.util.logging.config.class");
+                    String fname = System.getProperty("java.util.logging.config.file");
+                    return (cname != null || fname != null);
+                }
+            });
+    }
+
+    // Table of known loggers.  Maps names to PlatformLoggers.
+    private static Map<String,WeakReference<PlatformLogger>> loggers =
+        new HashMap<String,WeakReference<PlatformLogger>>();
+
+    /**
+     * Returns a PlatformLogger of a given name.
+     */
+    public static synchronized PlatformLogger getLogger(String name) {
+        PlatformLogger log = null;
+        WeakReference<PlatformLogger> ref = loggers.get(name);
+        if (ref != null) {
+            log = ref.get();
+        }
+        if (log == null) {
+            log = new PlatformLogger(name);
+            loggers.put(name, new WeakReference<PlatformLogger>(log));
+        }
+        return log;
+    }
+
+    /**
+     * Initialize java.util.logging.Logger objects for all platform loggers.
+     * This method is called from LogManager.readPrimordialConfiguration().
+     */
+    public static synchronized void redirectPlatformLoggers() {
+        if (loggingEnabled || !JavaLogger.supported) return;
+
+        loggingEnabled = true;
+        for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
+            WeakReference<PlatformLogger> ref = entry.getValue();
+            PlatformLogger plog = ref.get();
+            if (plog != null) {
+                plog.newJavaLogger();
+            }
+        }
+    }
+
+    /**
+     * Creates a new JavaLogger that the platform logger uses
+     */
+    private void newJavaLogger() {
+        logger = new JavaLogger(logger.name, logger.effectiveLevel);
+    }
+
+    // logger may be replaced with a JavaLogger object
+    // when the logging facility is enabled
+    private volatile LoggerProxy logger;
+
+    private PlatformLogger(String name) {
+        if (loggingEnabled) {
+            this.logger = new JavaLogger(name);
+        } else {
+            this.logger = new LoggerProxy(name);
+        }
+    }
+
+    /**
+     * A convenience method to test if the logger is turned off.
+     * (i.e. its level is OFF).
+     */
+    public boolean isEnabled() {
+        return logger.isEnabled();
+    }
+
+    /**
+     * Gets the name for this platform logger.
+     */
+    public String getName() {
+        return logger.name;
+    }
+
+    /**
+     * Returns true if a message of the given level would actually
+     * be logged by this logger.
+     */
+    public boolean isLoggable(int level) {
+        return logger.isLoggable(level);
+    }
+
+    /**
+     * Gets the current log level.  Returns 0 if the current effective level
+     * is not set (equivalent to Logger.getLevel() returns null).
+     */
+    public int getLevel() {
+        return logger.getLevel();
+    }
+
+    /**
+     * Sets the log level.
+     */
+    public void setLevel(int newLevel) {
+        logger.setLevel(newLevel);
+    }
+
+    /**
+     * Logs a SEVERE message.
+     */
+    public void severe(String msg) {
+        logger.doLog(SEVERE, msg);
+    }
+
+    public void severe(String msg, Throwable t) {
+        logger.doLog(SEVERE, msg, t);
+    }
+
+    public void severe(String msg, Object... params) {
+        logger.doLog(SEVERE, msg, params);
+    }
+
+    /**
+     * Logs a WARNING message.
+     */
+    public void warning(String msg) {
+        logger.doLog(WARNING, msg);
+    }
+
+    public void warning(String msg, Throwable t) {
+        logger.doLog(WARNING, msg, t);
+    }
+
+    public void warning(String msg, Object... params) {
+        logger.doLog(WARNING, msg, params);
+    }
+
+    /**
+     * Logs an INFO message.
+     */
+    public void info(String msg) {
+        logger.doLog(INFO, msg);
+    }
+
+    public void info(String msg, Throwable t) {
+        logger.doLog(INFO, msg, t);
+    }
+
+    public void info(String msg, Object... params) {
+        logger.doLog(INFO, msg, params);
+    }
+
+    /**
+     * Logs a CONFIG message.
+     */
+    public void config(String msg) {
+        logger.doLog(CONFIG, msg);
+    }
+
+    public void config(String msg, Throwable t) {
+        logger.doLog(CONFIG, msg, t);
+    }
+
+    public void config(String msg, Object... params) {
+        logger.doLog(CONFIG, msg, params);
+    }
+
+    /**
+     * Logs a FINE message.
+     */
+    public void fine(String msg) {
+        logger.doLog(FINE, msg);
+    }
+
+    public void fine(String msg, Throwable t) {
+        logger.doLog(FINE, msg, t);
+    }
+
+    public void fine(String msg, Object... params) {
+        logger.doLog(FINE, msg, params);
+    }
+
+    /**
+     * Logs a FINER message.
+     */
+    public void finer(String msg) {
+        logger.doLog(FINER, msg);
+    }
+
+    public void finer(String msg, Throwable t) {
+        logger.doLog(FINER, msg, t);
+    }
+
+    public void finer(String msg, Object... params) {
+        logger.doLog(FINER, msg, params);
+    }
+
+    /**
+     * Logs a FINEST message.
+     */
+    public void finest(String msg) {
+        logger.doLog(FINEST, msg);
+    }
+
+    public void finest(String msg, Throwable t) {
+        logger.doLog(FINEST, msg, t);
+    }
+
+    public void finest(String msg, Object... params) {
+        logger.doLog(FINEST, msg, params);
+    }
+
+    /**
+     * Default platform logging support - output messages to
+     * System.err - equivalent to ConsoleHandler with SimpleFormatter.
+     */
+    static class LoggerProxy {
+        private static final PrintStream defaultStream = System.err;
+        private static final String lineSeparator = AccessController.doPrivileged(
+            new PrivilegedAction<String>() {
+                public String run() {
+                    return System.getProperty("line.separator");
+                }
+            });
+
+        final String name;
+        volatile int levelValue;
+        volatile int effectiveLevel = 0; // current effective level value
+
+        LoggerProxy(String name) {
+            this(name, defaultLevel);
+        }
+
+        LoggerProxy(String name, int level) {
+            this.name = name;
+            this.levelValue = level == 0 ? defaultLevel : level;
+        }
+
+        boolean isEnabled() {
+            return levelValue != OFF;
+        }
+
+        int getLevel() {
+            return effectiveLevel;
+        }
+
+        void setLevel(int newLevel) {
+            levelValue = newLevel;
+            effectiveLevel = newLevel;
+        }
+
+        void doLog(int level, String msg) {
+            if (level < levelValue || levelValue == OFF) {
+                return;
+            }
+            defaultStream.println(format(level, msg, null));
+        }
+
+        void doLog(int level, String msg, Throwable thrown) {
+            if (level < levelValue || levelValue == OFF) {
+                return;
+            }
+            defaultStream.println(format(level, msg, thrown));
+        }
+
+        void doLog(int level, String msg, Object... params) {
+            if (level < levelValue || levelValue == OFF) {
+                return;
+            }
+            String newMsg = formatMessage(msg, params);
+            defaultStream.println(format(level, newMsg, null));
+        }
+
+        public boolean isLoggable(int level) {
+            if (level < levelValue || levelValue == OFF) {
+                return false;
+            }
+            return true;
+        }
+
+        private static final String format = "{0,date} {0,time}";
+
+        private Object args[] = new Object[1];
+        private MessageFormat formatter;
+        private Date dat;
+
+        // Copied from java.util.logging.Formatter.formatMessage
+        private String formatMessage(String format, Object... parameters) {
+            // Do the formatting.
+            try {
+                if (parameters == null || parameters.length == 0) {
+                    // No parameters.  Just return format string.
+                    return format;
+                }
+                // Is it a java.text style format?
+                // Ideally we could match with
+                // Pattern.compile("\\{\\d").matcher(format).find())
+                // However the cost is 14% higher, so we cheaply check for
+                // 1 of the first 4 parameters
+                if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
+                            format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
+                    return java.text.MessageFormat.format(format, parameters);
+                }
+                return format;
+            } catch (Exception ex) {
+                // Formatting failed: use format string.
+                return format;
+            }
+        }
+
+        private synchronized String format(int level, String msg, Throwable thrown) {
+            StringBuffer sb = new StringBuffer();
+            // Minimize memory allocations here.
+            if (dat == null) {
+                dat = new Date();
+                formatter = new MessageFormat(format);
+            }
+            dat.setTime(System.currentTimeMillis());
+            args[0] = dat;
+            StringBuffer text = new StringBuffer();
+            formatter.format(args, text, null);
+            sb.append(text);
+            sb.append(" ");
+            sb.append(getCallerInfo());
+            sb.append(lineSeparator);
+            sb.append(PlatformLogger.getLevelName(level));
+            sb.append(": ");
+            sb.append(msg);
+            if (thrown != null) {
+                try {
+                    StringWriter sw = new StringWriter();
+                    PrintWriter pw = new PrintWriter(sw);
+                    thrown.printStackTrace(pw);
+                    pw.close();
+                    sb.append(sw.toString());
+                } catch (Exception ex) {
+                    throw new AssertionError(ex);
+                }
+            }
+
+            return sb.toString();
+        }
+
+        // Returns the caller's class and method's name; best effort
+        // if cannot infer, return the logger's name.
+        private String getCallerInfo() {
+            String sourceClassName = null;
+            String sourceMethodName = null;
+
+            JavaLangAccess access = SharedSecrets.getJavaLangAccess();
+            Throwable throwable = new Throwable();
+            int depth = access.getStackTraceDepth(throwable);
+
+            String logClassName = "sun.util.logging.PlatformLogger";
+            boolean lookingForLogger = true;
+            for (int ix = 0; ix < depth; ix++) {
+                // Calling getStackTraceElement directly prevents the VM
+                // from paying the cost of building the entire stack frame.
+                StackTraceElement frame =
+                    access.getStackTraceElement(throwable, ix);
+                String cname = frame.getClassName();
+                if (lookingForLogger) {
+                    // Skip all frames until we have found the first logger frame.
+                    if (cname.equals(logClassName)) {
+                        lookingForLogger = false;
+                    }
+                } else {
+                    if (!cname.equals(logClassName)) {
+                        // We've found the relevant frame.
+                        sourceClassName = cname;
+                        sourceMethodName = frame.getMethodName();
+                        break;
+                    }
+                }
+            }
+
+            if (sourceClassName != null) {
+                return sourceClassName + " " + sourceMethodName;
+            } else {
+                return name;
+            }
+        }
+    }
+
+    /**
+     * JavaLogger forwards all the calls to its corresponding
+     * java.util.logging.Logger object.
+     */
+    static class JavaLogger extends LoggerProxy {
+        private static final boolean supported;
+        private static final Class<?> loggerClass;
+        private static final Class<?> levelClass;
+        private static final Method getLoggerMethod;
+        private static final Method setLevelMethod;
+        private static final Method getLevelMethod;
+        private static final Method isLoggableMethod;
+        private static final Method logMethod;
+        private static final Method logThrowMethod;
+        private static final Method logParamsMethod;
+        private static final Map<Integer, Object> levelObjects =
+            new HashMap<Integer, Object>();
+
+        static {
+            loggerClass = getClass("java.util.logging.Logger");
+            levelClass = getClass("java.util.logging.Level");
+            getLoggerMethod = getMethod(loggerClass, "getLogger", String.class);
+            setLevelMethod = getMethod(loggerClass, "setLevel", levelClass);
+            getLevelMethod = getMethod(loggerClass, "getLevel");
+            isLoggableMethod = getMethod(loggerClass, "isLoggable", levelClass);
+            logMethod = getMethod(loggerClass, "log", levelClass, String.class);
+            logThrowMethod = getMethod(loggerClass, "log", levelClass, String.class, Throwable.class);
+            logParamsMethod = getMethod(loggerClass, "log", levelClass, String.class, Object[].class);
+            supported = (loggerClass != null && levelClass != null && getLoggerMethod != null &&
+                         getLevelMethod != null && setLevelMethod != null &&
+                         logMethod != null && logThrowMethod != null && logParamsMethod != null);
+            if (supported) {
+                // initialize the map to Level objects
+                getLevelObjects();
+            }
+        }
+
+        private static Class<?> getClass(String name) {
+            try {
+                return Class.forName(name, true, null);
+            } catch (ClassNotFoundException e) {
+                return null;
+            }
+        }
+
+        private static Method getMethod(Class<?> cls, String name, Class<?>... parameterTypes) {
+            if (cls == null) return null;
+
+            try {
+                return cls.getMethod(name, parameterTypes);
+            } catch (NoSuchMethodException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        private static Object invoke(Method m, Object obj, Object... params) {
+            try {
+                return m.invoke(obj, params);
+            } catch (IllegalAccessException e) {
+                throw new AssertionError(e);
+            } catch (InvocationTargetException e) {
+                throw new AssertionError(e);
+            }
+        }
+
+        private static void getLevelObjects() {
+            // get all java.util.logging.Level objects
+            Method parseLevelMethod = getMethod(levelClass, "parse", String.class);
+            int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL};
+            for (int l : levelArray) {
+                Object o = invoke(parseLevelMethod, null, getLevelName(l));
+                levelObjects.put(l, o);
+            }
+        }
+
+        private final Object javaLogger;
+        JavaLogger(String name) {
+            this(name, 0);
+        }
+
+        JavaLogger(String name, int level) {
+            super(name, level);
+            this.javaLogger = invoke(getLoggerMethod, null, name);
+            if (level != 0) {
+                // level has been updated and so set the Logger's level
+                invoke(setLevelMethod, javaLogger, levelObjects.get(level));
+            }
+        }
+
+       /**
+        * Let Logger.log() do the filtering since if the level of a
+        * platform logger is altered directly from
+        * java.util.logging.Logger.setLevel(), the levelValue will
+        * not be updated.
+        */
+        void doLog(int level, String msg) {
+            invoke(logMethod, javaLogger, levelObjects.get(level), msg);
+        }
+
+        void doLog(int level, String msg, Throwable t) {
+            invoke(logThrowMethod, javaLogger, levelObjects.get(level), msg, t);
+        }
+
+        void doLog(int level, String msg, Object... params) {
+            invoke(logParamsMethod, javaLogger, levelObjects.get(level), msg, params);
+        }
+
+        boolean isEnabled() {
+            Object level = invoke(getLevelMethod, javaLogger);
+            return level == null || level.equals(levelObjects.get(OFF)) == false;
+        }
+
+        int getLevel() {
+            Object level = invoke(getLevelMethod, javaLogger);
+            if (level != null) {
+                for (Map.Entry<Integer, Object> l : levelObjects.entrySet()) {
+                    if (level == l.getValue()) {
+                        return l.getKey();
+                    }
+                }
+            }
+            return 0;
+        }
+
+        void setLevel(int newLevel) {
+            levelValue = newLevel;
+            invoke(setLevelMethod, javaLogger, levelObjects.get(newLevel));
+        }
+
+        public boolean isLoggable(int level) {
+            return (Boolean) invoke(isLoggableMethod, javaLogger, levelObjects.get(level));
+        }
+    }
+
+
+    private static String getLevelName(int level) {
+        switch (level) {
+            case OFF     : return "OFF";
+            case SEVERE  : return "SEVERE";
+            case WARNING : return "WARNING";
+            case INFO    : return "INFO";
+            case CONFIG  : return "CONFIG";
+            case FINE    : return "FINE";
+            case FINER   : return "FINER";
+            case FINEST  : return "FINEST";
+            case ALL     : return "ALL";
+            default      : return "UNKNOWN";
+        }
+    }
+
+}
--- a/jdk/src/share/demo/jvmti/waiters/Agent.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/demo/jvmti/waiters/Agent.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -72,36 +72,30 @@
 {
     jvmtiError err;
     Monitor   *m;
-
-    /* We use tags to track these, the tag is the Monitor pointer */
-    err = jvmti->RawMonitorEnter(lock); {
-        check_jvmti_error(jvmti, err, "raw monitor enter");
+    jlong      tag;
 
-        /* The raw monitor enter/exit protects us from creating two
-         *   instances for the same object.
-         */
-        jlong tag;
-
-        m   = NULL;
-        tag = (jlong)0;
-        err = jvmti->GetTag(object, &tag);
-        check_jvmti_error(jvmti, err, "get tag");
+    m   = NULL;
+    tag = (jlong)0;
+    err = jvmti->GetTag(object, &tag);
+    check_jvmti_error(jvmti, err, "get tag");
+    /*LINTED*/
+    m = (Monitor *)(void *)(ptrdiff_t)tag;
+    if ( m == NULL ) {
+        m = new Monitor(jvmti, env, object);
+        /* Save monitor on list */
+        if (monitor_count == monitor_list_size) {
+            monitor_list_size += monitor_list_grow_size;
+            monitor_list = (Monitor**)realloc((void*)monitor_list,
+                (monitor_list_size)*(int)sizeof(Monitor*));
+        }
+        monitor_list[monitor_count] = m;
+        m->set_slot(monitor_count);
+        monitor_count++;
         /*LINTED*/
-        m = (Monitor *)(void *)(ptrdiff_t)tag;
-        if ( m == NULL ) {
-            m = new Monitor(jvmti, env, object);
-            /*LINTED*/
-            tag = (jlong)(ptrdiff_t)(void *)m;
-            err = jvmti->SetTag(object, tag);
-            check_jvmti_error(jvmti, err, "set tag");
-            /* Save monitor on list */
-            monitor_list = (Monitor**)realloc((void*)monitor_list,
-                                (monitor_count+1)*(int)sizeof(Monitor*));
-            monitor_list[monitor_count++] = m;
-        }
-    } err = jvmti->RawMonitorExit(lock);
-    check_jvmti_error(jvmti, err, "raw monitor exit");
-
+        tag = (jlong)(ptrdiff_t)(void *)m;
+        err = jvmti->SetTag(object, tag);
+        check_jvmti_error(jvmti, err, "set tag");
+    }
     return m;
 }
 
@@ -112,12 +106,11 @@
 
     stdout_message("Agent created..\n");
     stdout_message("VMInit...\n");
-    /* Create a Monitor lock to use */
-    err = jvmti->CreateRawMonitor("waiters Agent lock", &lock);
-    check_jvmti_error(jvmti, err, "create raw monitor");
     /* Start monitor list */
     monitor_count = 0;
-    monitor_list  = (Monitor**)malloc((int)sizeof(Monitor*));
+    monitor_list_size = initial_monitor_list_size;
+    monitor_list = (Monitor**)
+        malloc(monitor_list_size*(int)sizeof(Monitor*));
 }
 
 Agent::~Agent()
@@ -134,9 +127,6 @@
         delete monitor_list[i];
     }
     free(monitor_list);
-    /* Destroy the Monitor lock to use */
-    err = jvmti->DestroyRawMonitor(lock);
-    check_jvmti_error(jvmti, err, "destroy raw monitor");
     /* Print death message */
     stdout_message("VMDeath...\n");
 }
@@ -215,8 +205,16 @@
     /* We just cast the tag to a C++ pointer and delete it.
      *   we know it can only be a Monitor *.
      */
-    Monitor *m;
+    Monitor   *m;
     /*LINTED*/
     m = (Monitor *)(ptrdiff_t)tag;
+    if (monitor_count > 1) {
+        /* Move the last element to this Monitor's slot */
+        int slot = m->get_slot();
+        Monitor *last = monitor_list[monitor_count-1];
+        monitor_list[slot] = last;
+        last->set_slot(slot);
+    }
+    monitor_count--;
     delete m;
 }
--- a/jdk/src/share/demo/jvmti/waiters/Agent.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/demo/jvmti/waiters/Agent.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -34,8 +34,12 @@
 class Agent {
 
   private:
-    jrawMonitorID lock;
+    enum {
+      initial_monitor_list_size = 64,
+      monitor_list_grow_size = 16
+    };
     Monitor     **monitor_list;
+    unsigned      monitor_list_size;
     unsigned      monitor_count;
     Thread *get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
     Monitor *get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
--- a/jdk/src/share/demo/jvmti/waiters/Monitor.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/demo/jvmti/waiters/Monitor.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -73,6 +73,16 @@
         name, contends, waits, timeouts);
 }
 
+int Monitor::get_slot()
+{
+    return slot;
+}
+
+void Monitor::set_slot(int aslot)
+{
+    slot = aslot;
+}
+
 void Monitor::contended()
 {
     contends++;
--- a/jdk/src/share/demo/jvmti/waiters/Monitor.hpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/demo/jvmti/waiters/Monitor.hpp	Wed Jul 05 17:01:09 2017 +0200
@@ -35,6 +35,7 @@
 
   private:
     char     name[64];
+    int      slot;
     unsigned contends;
     unsigned waits;
     unsigned timeouts;
@@ -42,6 +43,8 @@
   public:
     Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
     ~Monitor();
+    int get_slot();
+    void set_slot(int i);
     void contended();
     void waited();
     void timeout();
--- a/jdk/src/share/javavm/export/jvm.h	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/javavm/export/jvm.h	Wed Jul 05 17:01:09 2017 +0200
@@ -375,6 +375,12 @@
 JVM_ResolveClass(JNIEnv *env, jclass cls);
 
 /*
+ * Find a class from a boot class loader. Returns NULL if class not found.
+ */
+JNIEXPORT jclass JNICALL
+JVM_FindClassFromBootLoader(JNIEnv *env, const char *name);
+
+/*
  * Find a class from a given class loader. Throw ClassNotFoundException
  * or NoClassDefFoundError depending on the value of the last
  * argument.
--- a/jdk/src/share/lib/net.properties	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/lib/net.properties	Wed Jul 05 17:01:09 2017 +0200
@@ -32,7 +32,7 @@
 #
 # http.proxyHost=
 # http.proxyPort=80
-# http.nonProxyHosts=localhost|127.0.0.1
+http.nonProxyHosts=localhost|127.*|[::1]
 #
 # HTTPS Proxy Settings. proxyHost is the name of the proxy server
 # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
@@ -49,7 +49,7 @@
 #
 # ftp.proxyHost=
 # ftp.proxyPort=80
-# ftp.nonProxyHosts=localhost|127.0.0.1
+ftp.nonProxyHosts=localhost|127.*|[::1]
 #
 # Gopher Proxy settings. proxyHost is the name of the proxy server
 # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default
--- a/jdk/src/share/native/java/lang/ClassLoader.c	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/native/java/lang/ClassLoader.c	Wed Jul 05 17:01:09 2017 +0200
@@ -237,6 +237,9 @@
     JVM_ResolveClass(env, cls);
 }
 
+/*
+ * Returns NULL if class not found.
+ */
 JNIEXPORT jclass JNICALL
 Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader,
                                               jstring classname)
@@ -246,7 +249,6 @@
     char buf[128];
 
     if (classname == NULL) {
-        JNU_ThrowClassNotFoundException(env, 0);
         return 0;
     }
 
@@ -258,11 +260,10 @@
     VerifyFixClassname(clname);
 
     if (!VerifyClassname(clname, JNI_TRUE)) {  /* expects slashed name */
-        JNU_ThrowClassNotFoundException(env, clname);
         goto done;
     }
 
-    cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE);
+    cls = JVM_FindClassFromBootLoader(env, clname);
 
  done:
     if (clname != buf) {
--- a/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp	Wed Jul 05 17:01:09 2017 +0200
@@ -24,7 +24,7 @@
  */
 
 #include <jni.h>
-#include "ecc_impl.h"
+#include "impl/ecc_impl.h"
 
 #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
 #define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
--- a/jdk/src/share/native/sun/security/ec/ec.c	Mon Sep 28 19:38:55 2009 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1099 +0,0 @@
-/* *********************************************************************
- *
- * 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) {
-        randomlen = 2 * len;
-    }
-    /* 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/impl/ec.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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) {
+        randomlen = 2 * len;
+    }
+    /* 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/impl/ec.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec2.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec2_163.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec2_193.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec2_233.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec2_aff.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec2_mont.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ec_naf.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecc_impl.h	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,275 @@
+/* *********************************************************************
+ *
+ * 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.
+*/
+#define RNG_GenerateGlobalRandomBytes(p,l) SECFailure
+#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);
+/* This function has been modified to accept an array of random bytes */
+extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
+    const unsigned char* random, int randomlen, int);
+/* This function has been modified to accept an array of random bytes */
+extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *,
+    const unsigned char* random, int randomlen, int);
+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/impl/ecdecode.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl-curve.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl-exp.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl-priv.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl_curve.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl_gf.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecl_mult.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_192.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_224.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_256.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_384.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_521.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_aff.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_jac.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_jm.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/ecp_mont.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/logtab.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mp_gf2m-priv.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mp_gf2m.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mp_gf2m.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mpi-config.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mpi-priv.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mpi.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mpi.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mplogic.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mplogic.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mpmontg.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/mpprime.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/oid.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/secitem.c	Wed Jul 05 17:01:09 2017 +0200
@@ -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/impl/secoidt.h	Wed Jul 05 17:01:09 2017 +0200
@@ -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/bin/java_md.c	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/solaris/bin/java_md.c	Wed Jul 05 17:01:09 2017 +0200
@@ -1324,12 +1324,12 @@
 {
    if (findBootClass == NULL) {
        findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT,
-          "JVM_FindClassFromClassLoader");
+          "JVM_FindClassFromBootLoader");
        if (findBootClass == NULL) {
            JLI_ReportErrorMessage(DLL_ERROR4,
-               "JVM_FindClassFromClassLoader");
+               "JVM_FindClassFromBootLoader");
            return NULL;
        }
    }
-   return findBootClass(env, classname, JNI_FALSE, (jobject)NULL, JNI_FALSE);
+   return findBootClass(env, classname);
 }
--- a/jdk/src/solaris/classes/sun/net/www/protocol/http/NTLMAuthentication.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/solaris/classes/sun/net/www/protocol/http/NTLMAuthentication.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,18 +25,23 @@
 
 package sun.net.www.protocol.http;
 
-import java.util.Arrays;
-import java.util.StringTokenizer;
-import java.util.Random;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.PasswordAuthentication;
+import java.net.UnknownHostException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import javax.crypto.Cipher;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.DESKeySpec;
 
 import sun.net.www.HeaderParser;
 
-import java.io.*;
-import javax.crypto.*;
-import javax.crypto.spec.*;
-import java.security.*;
-import java.net.*;
-
 /**
  * NTLMAuthentication:
  *
@@ -66,8 +71,6 @@
 class NTLMAuthentication extends AuthenticationInfo {
     private static final long serialVersionUID = -2403849171106437142L;
 
-    static char NTLM_AUTH = 'N';
-
     private byte[] type1;
     private byte[] type3;
 
@@ -142,7 +145,10 @@
      * from a system property: "http.auth.ntlm.domain".
      */
     public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH, url, "");
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+                AuthScheme.NTLM,
+                url,
+                "");
         init (pw);
     }
 
@@ -166,7 +172,11 @@
     */
     public NTLMAuthentication(boolean isProxy, String host, int port,
                                 PasswordAuthentication pw) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH,host, port, "");
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+                AuthScheme.NTLM,
+                host,
+                port,
+                "");
         init (pw);
     }
 
--- a/jdk/src/windows/bin/java_md.c	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/windows/bin/java_md.c	Wed Jul 05 17:01:09 2017 +0200
@@ -1093,12 +1093,6 @@
  */
 static FindClassFromBootLoader_t *findBootClass = NULL;
 
-#ifdef _M_AMD64
-#define JVM_BCLOADER "JVM_FindClassFromClassLoader"
-#else
-#define JVM_BCLOADER "_JVM_FindClassFromClassLoader@20"
-#endif /* _M_AMD64 */
-
 jclass FindBootStrapClass(JNIEnv *env, const char *classname)
 {
    HMODULE hJvm;
@@ -1108,13 +1102,13 @@
        if (hJvm == NULL) return NULL;
        /* need to use the demangled entry point */
        findBootClass = (FindClassFromBootLoader_t *)GetProcAddress(hJvm,
-            JVM_BCLOADER);
+            "JVM_FindClassFromBootLoader");
        if (findBootClass == NULL) {
-          JLI_ReportErrorMessage(DLL_ERROR4, JVM_BCLOADER);
+          JLI_ReportErrorMessage(DLL_ERROR4, "JVM_FindClassFromBootLoader");
           return NULL;
        }
    }
-   return findBootClass(env, classname, JNI_FALSE, (jobject)NULL, JNI_FALSE);
+   return findBootClass(env, classname);
 }
 
 void
--- a/jdk/src/windows/classes/java/util/prefs/WindowsPreferences.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/windows/classes/java/util/prefs/WindowsPreferences.java	Wed Jul 05 17:01:09 2017 +0200
@@ -29,7 +29,7 @@
 import java.util.TreeMap;
 import java.util.StringTokenizer;
 import java.io.ByteArrayOutputStream;
-import java.util.logging.Logger;
+import sun.util.logging.PlatformLogger;
 
 /**
  * Windows registry based implementation of  <tt>Preferences</tt>.
@@ -48,7 +48,7 @@
     /**
      * Logger for error messages
      */
-    private static Logger logger;
+    private static PlatformLogger logger;
 
     /**
      * Windows registry path to <tt>Preferences</tt>'s root nodes.
@@ -1102,9 +1102,9 @@
         // assert false;
     }
 
-    private static synchronized Logger logger() {
+    private static synchronized PlatformLogger logger() {
         if (logger == null) {
-            logger = Logger.getLogger("java.util.prefs");
+            logger = PlatformLogger.getLogger("java.util.prefs");
         }
         return logger;
     }
--- a/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java	Wed Jul 05 17:01:09 2017 +0200
@@ -67,6 +67,9 @@
         if (d3dAvailable) {
             // we don't use pixel formats for the d3d pipeline
             pfDisabled = true;
+            sun.misc.PerfCounter.getD3DAvailable().set(1);
+        } else {
+            sun.misc.PerfCounter.getD3DAvailable().set(0);
         }
     }
 
--- a/jdk/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,18 +25,13 @@
 
 package sun.net.www.protocol.http;
 
-import java.util.Arrays;
-import java.util.StringTokenizer;
-import java.util.Random;
-
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.PasswordAuthentication;
+import java.net.UnknownHostException;
+import java.net.URL;
 import sun.net.www.HeaderParser;
 
-import java.io.*;
-import javax.crypto.*;
-import javax.crypto.spec.*;
-import java.security.*;
-import java.net.*;
-
 /**
  * NTLMAuthentication:
  *
@@ -47,7 +42,6 @@
 
     private static final long serialVersionUID = 100L;
 
-    static final char NTLM_AUTH = 'N';
     private String hostname;
     private static String defaultDomain; /* Domain to use if not specified by user */
 
@@ -88,7 +82,10 @@
      * from a system property: "http.auth.ntlm.domain".
      */
     public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH, url, "");
+        super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
+              AuthScheme.NTLM,
+              url,
+              "");
         init (pw);
     }
 
@@ -119,7 +116,11 @@
     */
     public NTLMAuthentication(boolean isProxy, String host, int port,
                                 PasswordAuthentication pw) {
-        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH,host, port, "");
+        super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
+              AuthScheme.NTLM,
+              host,
+              port,
+              "");
         init (pw);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/sun/jdi/BreakpointWithFullGC.sh	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,128 @@
+#!/bin/sh
+
+#
+# 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 6862295
+#  @summary Verify breakpoints still work after a full GC.
+#  @author dcubed (based on the test program posted to the following
+#  Eclipse thread https://bugs.eclipse.org/bugs/show_bug.cgi?id=279137)
+#
+#  @run shell BreakpointWithFullGC.sh
+
+compileOptions=-g
+# Hijacking the mode parameter to make sure we use a small amount
+# of memory and can see what GC is doing.
+mode="-Xmx32m -verbose:gc"
+# Force use of a GC framework collector to see the original failure.
+#mode="$mode -XX:+UseSerialGC"
+
+# Uncomment this to see the JDI trace
+#jdbOptions=-dbgtrace
+
+createJavaFile()
+{
+    cat <<EOF > $1.java.1
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class $1 {
+    public static List<Object> objList = new ArrayList<Object>();
+
+    private static void init(int numObjs) {
+        for (int i = 0; i < numObjs; i++) {
+            objList.add(new Object());
+        }
+    }
+
+    public static void main(String[] args) {
+        for (int i = 0; i < 10; i++) {
+            System.out.println("top of loop");     // @1 breakpoint
+            init(1000000);
+            objList.clear();
+            System.out.println("bottom of loop");  // @1 breakpoint
+        }
+        System.out.println("end of test");         // @1 breakpoint
+    }
+}
+
+EOF
+}
+
+# This is called to feed cmds to jdb.
+dojdbCmds()
+{
+    setBkpts @1
+
+    # get to the first loop breakpoint
+    runToBkpt
+    # 19 "cont" commands gets us through all the loop breakpoints.
+    # Use for-loop instead of while-loop to avoid creating processes
+    # for '[' and 'expr'.
+    for ii in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do
+        contToBkpt
+    done
+    # get to the last breakpoint
+    contToBkpt
+}
+
+
+mysetup()
+{
+    if [ -z "$TESTSRC" ] ; then
+        TESTSRC=.
+    fi
+
+    for ii in . $TESTSRC $TESTSRC/.. ; do
+        if [ -r "$ii/ShellScaffold.sh" ] ; then
+            . $ii/ShellScaffold.sh
+            break
+        fi
+    done
+}
+
+# You could replace this next line with the contents
+# of ShellScaffold.sh and this script will run just the same.
+mysetup
+
+runit
+
+# make sure we hit the first breakpoint at least once
+jdbFailIfNotPresent 'System\..*top of loop'
+
+# make sure we hit the second breakpoint at least once
+jdbFailIfNotPresent 'System\..*bottom of loop'
+
+# make sure we hit the last breakpoint
+jdbFailIfNotPresent 'System\..*end of test'
+
+# make sure we had at least one full GC
+debuggeeFailIfNotPresent 'Full GC'
+
+# check for error message due to thread ID change
+debuggeeFailIfPresent \
+    'Exception in thread "event-handler" java.lang.NullPointerException'
+
+pass
--- a/jdk/test/java/lang/ProcessBuilder/Basic.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/Basic.java	Wed Jul 05 17:01:09 2017 +0200
@@ -25,7 +25,7 @@
  * @test
  * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
  *      5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
- *      6464154 6523983 6206031 4960438 6631352 6631966
+ *      6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
  * @summary Basic tests for Process and Environment Variable code
  * @run main/othervm Basic
  * @author Martin Buchholz
@@ -302,6 +302,14 @@
                 printUTF8(val == null ? "null" : val);
             } else if (action.equals("System.getenv()")) {
                 printUTF8(getenvAsString(System.getenv()));
+            } else if (action.equals("ArrayOOME")) {
+                Object dummy;
+                switch(new Random().nextInt(3)) {
+                case 0: dummy = new Integer[Integer.MAX_VALUE]; break;
+                case 1: dummy = new double[Integer.MAX_VALUE];  break;
+                case 2: dummy = new byte[Integer.MAX_VALUE][];  break;
+                default: throw new InternalError();
+                }
             } else if (action.equals("pwd")) {
                 printUTF8(new File(System.getProperty("user.dir"))
                           .getCanonicalPath());
@@ -1473,6 +1481,22 @@
         } catch (Throwable t) { unexpected(t); }
 
         //----------------------------------------------------------------
+        // OOME in child allocating maximally sized array
+        // Test for hotspot/jvmti bug 6850957
+        //----------------------------------------------------------------
+        try {
+            List<String> list = new ArrayList<String>(javaChildArgs);
+            list.add(1, String.format("-XX:OnOutOfMemoryError=%s -version",
+                                      javaExe));
+            list.add("ArrayOOME");
+            ProcessResults r = run(new ProcessBuilder(list));
+            check(r.out().contains("java.lang.OutOfMemoryError:"));
+            check(r.out().contains(javaExe));
+            check(r.err().contains(System.getProperty("java.version")));
+            equal(r.exitValue(), 1);
+        } catch (Throwable t) { unexpected(t); }
+
+        //----------------------------------------------------------------
         // Windows has tricky semi-case-insensitive semantics
         //----------------------------------------------------------------
         if (Windows.is())
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/ProxySelector/B6737819.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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 6737819
+ * @summary sun.misc.net.DefaultProxySelector doesn't use proxy setting to localhost
+ */
+
+import java.net.ProxySelector;
+import java.net.Proxy;
+import java.net.URI;
+
+public class B6737819 {
+    private static String[] uris = {
+        "http://localhost/index.html",
+        "http://127.0.0.1/index.html",
+        "http://127.2/index.html",
+        "http://[::1]/index.html"
+    };
+    public static void main(String[] args) throws Exception {
+        System.setProperty("http.proxyHost", "myproxy");
+        System.setProperty("http.proxyPort", "8080");
+        ProxySelector sel = ProxySelector.getDefault();
+        java.util.List<Proxy> l;
+        // Default value for http.nonProxyHots should exclude all this uris
+        // from going through the HTTP proxy
+        for (String s : uris) {
+            l = sel.select(new URI(s));
+            if (l.size() == 1 && l.get(0).type() != Proxy.Type.DIRECT) {
+                throw new RuntimeException("ProxySelector returned the wrong proxy for " + s);
+            }
+        }
+        // Let's override the default nonProxyHosts and make sure we now get a
+        // HTTP proxy
+        System.setProperty("http.nonProxyHosts", "");
+        for (String s : uris) {
+            l = sel.select(new URI(s));
+            if (l.size() == 1 && l.get(0).type() != Proxy.Type.HTTP) {
+                throw new RuntimeException("ProxySelector returned the wrong proxy for " + s);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/WalkWithSecurity.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,132 @@
+/*
+ * 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 6876541
+ * @summary Test Files.walkFileTree in the presence of a security manager
+ * @build WalkWithSecurity
+ * @run main/othervm WalkWithSecurity grantAll.policy pass
+ * @run main/othervm WalkWithSecurity denyAll.policy fail
+ * @run main/othervm WalkWithSecurity grantTopOnly.policy top_only
+ */
+
+import java.nio.file.*;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.io.IOException;
+
+public class WalkWithSecurity {
+
+    public static void main(String[] args) throws IOException {
+        String policyFile = args[0];
+        ExpectedResult expectedResult = ExpectedResult.valueOf(args[1].toUpperCase());
+
+        String here = System.getProperty("user.dir");
+        String testSrc = System.getProperty("test.src");
+        if (testSrc == null)
+            throw new RuntimeException("This test must be run by jtreg");
+        Path dir = Paths.get(testSrc);
+
+        // Sanity check the environment
+        if (Paths.get(here).isSameFile(dir))
+            throw new RuntimeException("Working directory cannot be " + dir);
+        DirectoryStream<Path> stream = dir.newDirectoryStream();
+        try {
+            if (!stream.iterator().hasNext())
+                throw new RuntimeException(testSrc + " is empty");
+        } finally {
+            stream.close();
+        }
+
+        // Install security manager with the given policy file
+        System.setProperty("java.security.policy",
+            dir.resolve(policyFile).toString());
+        System.setSecurityManager(new SecurityManager());
+
+        // Walk the source tree
+        CountingVisitor visitor = new CountingVisitor();
+        SecurityException exception = null;
+        try {
+            Files.walkFileTree(dir, visitor);
+        } catch (SecurityException se) {
+            exception = se;
+        }
+
+        // Check result
+        switch (expectedResult) {
+            case PASS:
+                if (exception != null) {
+                    exception.printStackTrace();
+                    throw new RuntimeException("SecurityException not expected");
+                }
+                if (visitor.count() == 0)
+                    throw new RuntimeException("No files visited");
+                break;
+            case FAIL:
+                if (exception == null)
+                    throw new RuntimeException("SecurityException expected");
+                if (visitor.count() > 0)
+                    throw new RuntimeException("Files were visited");
+                break;
+            case TOP_ONLY:
+                if (exception != null) {
+                    exception.printStackTrace();
+                    throw new RuntimeException("SecurityException not expected");
+                }
+                if (visitor.count() == 0)
+                    throw new RuntimeException("Starting file not visited");
+                if (visitor.count() > 1)
+                    throw new RuntimeException("More than starting file visited");
+                break;
+            default:
+                throw new RuntimeException("Should not get here");
+        }
+    }
+
+    static enum ExpectedResult {
+        PASS,
+        FAIL,
+        TOP_ONLY;
+    }
+
+    static class CountingVisitor extends SimpleFileVisitor<Path> {
+        private int count;
+
+        int count() {
+            return count;
+        }
+
+        @Override
+        public FileVisitResult preVisitDirectory(Path dir) {
+            System.out.println(dir);
+            count++;
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
+            System.out.println(file);
+            count++;
+            return FileVisitResult.CONTINUE;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/denyAll.policy	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,3 @@
+// policy file that does not grant any permissions
+grant {
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/grantAll.policy	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,5 @@
+// policy file that grants read access to source directory and all descendants
+grant {
+    permission java.io.FilePermission "${test.src}", "read";
+    permission java.io.FilePermission "${test.src}${file.separator}-", "read";
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/nio/file/Files/grantTopOnly.policy	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,4 @@
+// policy file that grants read access to source directory
+grant {
+    permission java.io.FilePermission "${test.src}", "read";
+};
--- a/jdk/test/sun/security/ec/TestEC.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/test/sun/security/ec/TestEC.java	Wed Jul 05 17:01:09 2017 +0200
@@ -27,6 +27,8 @@
  * @summary  Provide out-of-the-box support for ECC algorithms
  * @library ../pkcs11
  * @library ../pkcs11/ec
+ * @library ../pkcs11/sslecc
+ * @compile -XDignore.symbol.file TestEC.java
  * @run main TestEC
  */
 
@@ -35,12 +37,15 @@
 /*
  * Leverage the collection of EC tests used by PKCS11
  *
- * NOTE: the following files were copied here from the PKCS11 EC Test area
+ * NOTE: the following 6 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/certs/sunlabscerts.pem
  *           ../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12
  *           ../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12
+ *           ../pkcs11/sslecc/keystore
+ *           ../pkcs11/sslecc/truststore
  */
 
 public class TestEC {
@@ -49,18 +54,23 @@
         Provider p = new sun.security.ec.SunEC();
         System.out.println("Running tests with " + p.getName() +
             " provider...\n");
+        long start = System.currentTimeMillis();
 
-        long start = System.currentTimeMillis();
+        /*
+         * The entry point used for each test is its instance method
+         * called main (not its static method called main).
+         */
         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();
+        new ReadCertificates().main(p);
+        new ClientJSSEServerJSSE().main(p);
 
+        long stop = System.currentTimeMillis();
         System.out.println("\nCompleted tests with " + p.getName() +
-            " provider (" + (stop - start) + " ms).");
+            " provider (" + ((stop - start) / 1000.0) + " seconds).");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ec/certs/sunlabscerts.pem	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,1317 @@
+-----BEGIN CERTIFICATE-----
+MIIDyDCCAzGgAwIBAgIJAJh6e4zfP9lXMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAk
+BgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMR8wHQYDVQQLDBZU
+ZXN0IFNlcnZlciAoUlNBIDEwMjQpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFs
+c3R1ZmYuY29tMB4XDTA1MTIwNjIxMjk1OFoXDTEwMDExNDIxMjk1OFowgZ8xCzAJ
+BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEm
+MCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHzAdBgNVBAsM
+FlRlc3QgU2VydmVyIChSU0EgMTAyNCkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50
+YWxzdHVmZi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJrKL3D9xOca
+b5C5m1yeIFXvwufm5m06RnQdLWaj5Epg9+6tM3uZNn9B0r4k7MKYPbzBqyQO9ZSm
+sulV9U3nWLhjChOrrNCIxzAUIR1//11QVKfjv3k8Ts7N5g5kIIiG8GUXh1WCNYhN
+SvPo0BpNJ3FFwMMCZu0VpAP0j9krqWjfAgMBAAGjggEIMIIBBDAdBgNVHQ4EFgQU
+FrXN7dxlrB1ccI0ZOi+NzYpz6UIwgdQGA1UdIwSBzDCByYAUFrXN7dxlrB1ccI0Z
+Oi+NzYpz6UKhgaWkgaIwgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQG
+A1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBM
+YWJvcmF0b3JpZXMxHzAdBgNVBAsMFlRlc3QgU2VydmVyIChSU0EgMTAyNCkxIjAg
+BgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5jb22CCQCYenuM3z/ZVzAMBgNV
+HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAAEQHmeWmoe+s784Qi1oK04eNeI3
+m3Iw06IWjdKH5xatQqj9VjvngLWnmY26PYlF6PK3cAktuempXVA2rZ3Dv5pkgAdQ
+f3LXGHBKfAEsSjSSpxIsQA6Q+Yk7zqht5hSPOtUXHcWUx9EMvh7HnjmEEdR80fw/
+txvN4xm8V+flmK/T
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICxjCCAi8CCQCg3U8Mc7XCZzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwNTlaFw0xMDAxMTQyMTMwNTlaMIGuMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0
+IFNlcnZlciAocnNhMTAyNHNlcnZlci1yc2ExMDI0Y2EpMSIwIAYDVQQDDBlkZXYu
+ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQCZCOorl//TxbVdj8X+fb9xhMlApe9sAU/jlHRtrv+7FflqCLMmhcR8s90LTCjq
+gcX0mGm7fIusBff4/hjaKlmrto0YLNg8c8Zvev5CD+0HQHtbGUfx3TGOHv7gvG31
+nt88ZOzyIlPe2khcDTmb613zxFZhgJBs3bCsQz0TK3bR/wIDAQABMA0GCSqGSIb3
+DQEBBQUAA4GBABHP8xO3ouLm6SgZefjJnmbURTpjosE7oR15T1Fpf6o0WARaTeYO
+07H/GdDFUgV3RTA/zNMimfq6XqJB5r5WBziVkLLuixzS7nNaAci6o5b2UaU7shUc
+z3k0O4Dclybb4J1dYeAIwXUGqLAzI1NCgjRoGirFWT+O+02tT1KCiSl3
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDRzCCAi8CCQCg3U8Mc7XCaDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMxMDBaFw0xMDAxMTQyMTMxMDBaMIGuMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0
+IFNlcnZlciAocnNhMTAyNHNlcnZlci1yc2EyMDQ4Y2EpMSIwIAYDVQQDDBlkZXYu
+ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQC5EyeXl7YTi5NPgJiIZHNSrG9qlAVoM5BYKqAVtFwHCbLYB7ZWyN2BuEfUSf8p
+KSKkq28DkNTqnyz6Rg57kHzO3+kca0+iHlqFpbcP6uuN4ubOGZCuEDT0Ti7VXRtc
+a8hGNrOEzZKA6DCl9csfrN0jHB5VBfJ4qTJCEi8fXNQbzwIDAQABMA0GCSqGSIb3
+DQEBBQUAA4IBAQC05575dPOqJ6Qk2rs7wHu4tGE15OR2jnXSZXXDObRUHetykmfQ
+YbUq9/z9f3k4R53GAisgDwbVUb3EUsXofy7eMTUD89A7MiZ99SvebPilDQE3djqM
+D0uA9a96LG6fAarc1MdpbMPcFiFFiwwlqJVtx4TNlektFbFQRzrrbMSF/ISLzdWK
+fR3XD5qpwiCQbSug9Zm7cornUk8cK/Fs571wErOrdPo47aw1C8NjspLhux/JtHM9
+hNuAqona/4lX5lMVNpnSkWaT+B281+ysm1uEK8lvsDSUuLy+fZvokCrhQPFLoI+h
+l5HGNqXdyIu1POCl6yqd6+BKNnfA5Qy+Bp87
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICbDCCAioCCQCg3U8Mc7XCYTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA0OVoXDTEwMDExNDIxMzA0OVowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2ExMDI0c2VydmVyLXNlY3AxNjByMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyvWS
+/5LJKlEJNR+jEWB1VMQVC09227El9V80yZ8WYqL0RdvWvDHN/vN1HKlFni/X5pwK
+Def0vpXEDueeUgs9nQd+WDI/HOHTZ6BwUu2x2JParIBm9+dylWiBqhV+9LI/TyIr
+4KMKjcnTMlCKZvzrIplIvcf+Gu/OFG46q3PUIFcCAwEAATAJBgcqhkjOPQQBAzEA
+MC4CFQCslg/BEN7fygz0CIIWO+1n/yenNwIVAMivW2BhQhk1TEPw5Zs3QgXEw187
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIChDCCAioCCQCg3U8Mc7XCYjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA1MVoXDTEwMDExNDIxMzA1MVowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2ExMDI0c2VydmVyLXNlY3AyNTZyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5v3h
+NBYB07K2o8TMStAW5j5qDfy1XciU6Hx32qeoPwBdsvalmiAP+Scawfi7xPWGCMTK
+zBiRSRHVgFU+tsvpFhJ+7mnl0k7zQMdmuzJCH/IV8889TAobQbGsvSdMa5ry+FRo
+u+2QoEAaOQik4RFZcZmw+46wbMbeNhesirEkG20CAwEAATAJBgcqhkjOPQQBA0kA
+MEYCIQCMTGl7AImRhjsdQuEUaODQKFWGcZSFT0ZVe+ikWQCdcQIhANOPoSjaBDHa
+kJVhR6MrTMHvnfAGL+EZpAqHGPMM12JD
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICpDCCAioCCQCg3U8Mc7XCYzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA1MloXDTEwMDExNDIxMzA1MlowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2ExMDI0c2VydmVyLXNlY3AzODRyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsTW
+yLsCTz6nEeBEHW1JvMFPFnFqvXWWJJsEHbJtPDU0FF3xurgfNX4T7BsPW5LNIneh
+MJbKqSCRgw0q97zgVLhB1WBE6y5jkfYCTDA5QAuNOlqgTGrBg0WIANgsXjHFZ5kQ
+46i98IzFOFHZFOdtj+i0T3GviZWKGCbjKShyWnMCAwEAATAJBgcqhkjOPQQBA2kA
+MGYCMQD4L6X8M2oCiwQE0/HqNNI4zCt6gp2o8Uk2HWa5If59QhwlfjXQSdbvVGfW
+T2XpnUACMQDJ6Ir8G4H9Mu9ktf64MhnYg6A22hV4nWZ5bpM3AiD+10q+30r+TWV4
+89YQz707Eok=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICyDCCAioCCQCg3U8Mc7XCZDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA1NFoXDTEwMDExNDIxMzA1NFowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2ExMDI0c2VydmVyLXNlY3A1MjFyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1Nmx
+2TOGk8FQXJIzDM2+x4jVWocD2lRShsFQaMhltST4PWm+TbXBPSxpvS9oFW7eZE3J
+50OqxMiZkmH8un44Iet7E6fi0iRhw0bl4uqG2JHtyMzSYR6niSy0yqgHVJVwM24Q
+Z/39X17PD0NwCEiPBGFx9Xa5E2JP9KcnCbrj49sCAwEAATAJBgcqhkjOPQQBA4GM
+ADCBiAJCAZ4Apzk6L7BLjKoln+NEl5a/I1TmNIPVR0HtcLwbdZQ/y9b0+vhENkkS
+XIGTc/2Jx+OV/tc4JyNW7PNM/YPl5FDUAkIByKevbRtsBD0HuCVK6WOf+6uz+QFs
+fgxz0XoMyWMuoUIM2ytx+Eq9UY13QgqCQ5FxYWJ6RtDiNhEovr5GMjqjG0Q=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICbDCCAioCCQCg3U8Mc7XCZTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA1NVoXDTEwMDExNDIxMzA1NVowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2ExMDI0c2VydmVyLXNlY3QxNjNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy4Vh
+Ju/NaZEhiu6wsh4fsKGvwdHwRKvmJwMk8wEk3/Vz92/9kPR5B/Co3XVGBmW4UJwD
+0BcdPcMyr1TDHYOL7kS65MJGq0eFcBblA5hr2G3unZwgVwpS9GzMA7n8s3BtDGYN
+UpUyt5u5C6mTqQoK39xVWWbke5tM90T3jr6MiN0CAwEAATAJBgcqhkjOPQQBAzEA
+MC4CFQOcO1rEZFieKqpNL8E8T1wwchv2FQIVAQ4DEcV2AkLqSXxgt+h03NyWPeEN
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICcjCCAioCCQCg3U8Mc7XCZjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA1N1oXDTEwMDExNDIxMzA1N1owgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2ExMDI0c2VydmVyLXNlY3QxOTNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAws4d
+5PHRj1UOeuc60MnkGhmwJ/RD7Vmaq8NUJwliTHnAscTlZuv5Irv9cYHhAka2p8WJ
+mo8xZxlUQMIUxIx/9ocZEYAKrv/vjWo05iaDQowJOUHM77usJnTZbDrVfeuOBqFo
+6G2scl6RBGdCUOGUBVdRT6sEWQnYm/wIcTxj9OcCAwEAATAJBgcqhkjOPQQBAzcA
+MDQCGHDRiFsRMDB+Y4+Mnjs4jWHHKyjqoOYFlwIYemZsC0uC1/oI/ZFUuERW7TEe
+BPpqMQgX
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICyzCCAjQCCQClVpDHKllBjTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcGA1UECwwgVGVzdCBT
+ZXJ2ZXIgKHJzYTEwMjRzZXJ2ZXItc2VsZikxIjAgBgNVBAMMGWRldi5leHBlcmlt
+ZW50YWxzdHVmZi5jb20wHhcNMDUxMjA2MjEzMTAxWhcNMTAwMTE0MjEzMTAxWjCB
+qTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBW
+aWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcG
+A1UECwwgVGVzdCBTZXJ2ZXIgKHJzYTEwMjRzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
+MIGJAoGBALx55L25d1DjV6X6z/rqebCJvhD0IfWqUU6ekiADnDgmOhFT8gutI4Xh
+2AlBhIyticLU5IMP/MYud0OPnavaH3dcNRsfkJkfmZRULqIDjWnVmtmBhV8th9TM
+KaH7V1TOqxqMfGuzFq9uwL8p5i2f8fLQjZ9sNNj7qeuW5XI05cv1AgMBAAEwDQYJ
+KoZIhvcNAQEFBQADgYEAG3UcMUmwpTKUwNA6P0i0073ptjmzhRIeDdpf1d69X99Y
+Wrnf2H6xA2boa8gBkVFjCaLBakIq6px5IuGFZNB2+0yJqd8QE22DKk1Ikr5hBsEC
+owhd0feRaNjO0u/kPFZU1XAVFyz2AGKdLUOw4OEV8tuSOXAmWoMZHwfoocy1JnQ=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIEzTCCA7WgAwIBAgIJAMkNhmYP6nKsMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAk
+BgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMR8wHQYDVQQLDBZU
+ZXN0IFNlcnZlciAoUlNBIDIwNDgpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFs
+c3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAwOVoXDTEwMDExNDIxMzAwOVowgZ8xCzAJ
+BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEm
+MCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHzAdBgNVBAsM
+FlRlc3QgU2VydmVyIChSU0EgMjA0OCkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50
+YWxzdHVmZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO/6vZ
+zPZAmeKP/fMAwKTRzCmy30TnoEZJybsk8QDlL9xaYIcEiIhf6eOV0/IYPcSwPakv
+Ha5lT9aCTEEdcxACqAQlm2LOFZ79pUc0bGEmeFpHDZoO2w7+/RCYbGLkdWKTfj1D
+kKG9PoWX5MelBZqkQuvE3+6eAr70IlQRA8uMA+Aq+Hl7KZys+eTX3eVWcNYZu94U
+Z9wOKsRnRT4Yzf1G8aPJq4gIwxW4nBVAHqUc2N8bUzsHVqbTpcytU3KYT1YlcLGG
+Ir1LulgjWws3Lncx1rZQuAIT5cyjCmW8wZ/O+GewzmbgV95lFsf8HCd0ZD4j65sS
+/l0xB4zHnSBAegntAgMBAAGjggEIMIIBBDAdBgNVHQ4EFgQUS1aD1pb8BOGcjSyh
+9IhovqLk1TcwgdQGA1UdIwSBzDCByYAUS1aD1pb8BOGcjSyh9IhovqLk1TehgaWk
+gaIwgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRh
+aW4gVmlldzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMx
+HzAdBgNVBAsMFlRlc3QgU2VydmVyIChSU0EgMjA0OCkxIjAgBgNVBAMMGWRldi5l
+eHBlcmltZW50YWxzdHVmZi5jb22CCQDJDYZmD+pyrDAMBgNVHRMEBTADAQH/MA0G
+CSqGSIb3DQEBBQUAA4IBAQBDl6f5HVzv0r0/DNAMy6vaKHrKXCJYVXLh7AZWLShP
+3BfvekDRncLFjldTEqE1vqD4wndxpHVVwyZWWBWHVcw76AAtYnZp36ex5ZP56pHw
+Mg308O+tYLgjdm5cDEzGzqNgavUIi/T/lMnWJrls1Zr/qnf7hzbvIAlMGJ4jcZGF
+U1Z8T4mpFyroafXSbHEE/awX9DbyZL0ryXXtlTggxgLfzPqmSx4ZXurqv4LFdjlu
+pZ/+/b6qU3JAlDMDMReb+iDBIllNGVZj88QTp3cC2CtwnYBYvLLWFtWoQpN2Ppz4
+X5xcdh4VuTICpk5kQSbzrij3GXZl0fDVuX4Z+5J1xodl
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDSjCCArMCCQCg3U8Mc7XCbzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMyMjlaFw0xMDAxMTQyMTMyMjlaMIGuMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0
+IFNlcnZlciAocnNhMjA0OHNlcnZlci1yc2ExMDI0Y2EpMSIwIAYDVQQDDBlkZXYu
+ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA7I6hIU6+t1DQABGWtaqyhUjieQTzoaN3dZzmzTcUXY62F+IedLuVrxcQ
+3YJU8+jcM6rl+/eIa90rNcKpxjrdzx676CqFCHO3/aHF1iCMmQF368ezfs2lDPTF
+mobrn6KMNe71SM8bQ8MHFmRxY1wWk7GKIuz8OQnJOHD1nXQisjv1GBZ7HssaEPGd
+m8c1rKCvzqrC4Nj/U+cKV0VeWtJod5inIx5RT/5FYW4QdBwuhovoKumPxpImYz6Y
+SuFAce2hTMjxmvFXD0V1+VfWsYUe0/TilRgOv5l9iWo4haGBftYFWW8w0iqOB4+q
+cPqcKozI7Tjs9r3Rby0zTdjB6vZi9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAAUd
+cnt8YHDUvIroDiLQQsH+p2mDD+ra10K3C9H0Lsvt6cb3/2jn6PupFVJzwkEEankS
+Lo/pOe+bO5uSA4C2FQAymrYZX5Hh1guK/Has+Sf0K+HKPx28QPGg1EoS2KAbUf1t
+RBX2jtq8Suz3iS9u77PbpB7aMNAEBihr2jAyfSka
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDyzCCArMCCQCg3U8Mc7XCcDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMyMzVaFw0xMDAxMTQyMTMyMzVaMIGuMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0
+IFNlcnZlciAocnNhMjA0OHNlcnZlci1yc2EyMDQ4Y2EpMSIwIAYDVQQDDBlkZXYu
+ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxHxrsAwLznaK+dmgQxUzmWTsNLhuKk+yBkpJZQDQDjkdxVrime1DxPAZ
+MDi4OL+9YCIDS3ZWG0uLH49Atq08/2TB+aYDm0YBjrq3BRphTBrNNpntezSgP/nz
+R2hOBvBgSvFqorTLzRF9THq18CrSJJB/OPFzvl6mYK8dtS4CnOfdUs0Pv8SwdxhJ
+X6qsO0NJclrfBYBodGW1PiY62NPX0h2mLcg4OmD3gThfjUvXnsdjLJYV6hZFT+YC
+vPJNTxTGebfnJr4sRGdqRUyBrjiqZtXwGpIBCSg/YpnUOfDSxJNA2Wd/WFJJv8Fq
+kBh2oDRqlFNC/Z+HjGqKj0gFowTq3QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBp
+iFO+5KbnHfRBStgxZdTBrr+HEezeFlxeE04bM7kSWII2SiQbAWSG5Rkb518m5x65
+q23KqUK+YJiy7k0zoKInvG/qLf1D5osFlwaAll7AKBadn/R8x822xSJCydHgD64V
+b3u89zBY5Jtl+EzTA+n+UWRsurlLL1K9ockWZrDiZn6gGO5/ucR8OkZ192sxqKRr
+iQbN12LWSmUCYPwba8nvDdm1ymAbnFOg1oQJ9HvxmFI3GaGjdmNo9rlaoNS/xQ35
+iTtJyi1MK2d+O2JPD5cS5otGfFnQiTWIngBiuEoOwzw7x8eWsOQaBPVnNSlMdU+z
+Zrc6M1OSOUh2+DqvAoBp
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC8DCCAq4CCQCg3U8Mc7XCaTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzExM1oXDTEwMDExNDIxMzExM1owgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2EyMDQ4c2VydmVyLXNlY3AxNjByMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AMPD0turqL6uNjGfquQy3MTv90+RvDCvCQXGnxdJa6QcOOHnv/4ua9g/TOO2cVuc
+UuF3EnMSDg+HIo8qJhdKcOa4nnp1IxAnPsQs1K9vq8eqtuSuFMZUoUKy969ThPqd
+UTYyZpOn87XMftm76nz92q2gDPLj7ZxD1QOv0MpMHjXJMSRHWEhsoCpYBdFT5Nl5
+28bK0AWTv4nw2RmQryn+UMblAqnJBNiIWzVHBUa1UNMBt2lnO12w6EpSGmkx9+Op
+rv8kcfJgXnUkH/l7krHUADplp4yxO1hIzdH5Xsd+Hxrnl85vGjNJyuNOlFJ1Eh0x
+AJTT6m1ypPKAs+zF1nWJaJECAwEAATAJBgcqhkjOPQQBAzEAMC4CFQCsQDzAbX4C
+uri94k3X0mUTxCrweAIVAON/UYsS+fYp74XS5ucP8I31tl8n
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDCDCCAq4CCQCg3U8Mc7XCajAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzEyOFoXDTEwMDExNDIxMzEyOFowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2EyMDQ4c2VydmVyLXNlY3AyNTZyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALYeH/U234MovGN9iM3mr3kah93WJY64Dg8kGHg4zaUeKSmZVBgj/IlaCbfsRzXp
+0xtsBCXAHGlZosiIInQzfxVNS/XIUOI3B5h+n3wMl61BsC2R/pmHyEg8eFp6Jiwv
+1HMW9xKYF4qGgH396HczXPxOov3iJvtHHLElzYXDwCqy+x4D1PzXQLEkaGQzXsY4
+xhqskq1qg4pacNvow1eJair9zk5ebrV9t39icdTMkrtwgNBYAM/RU5DBxjdHDb/p
+Ef26uOmpEfgopcRpoZlDY7mpBozK49Ocsx+PCAx74A1kj8M2i7s+edlLMxIl66Co
++ELzqZW7YjwtyrOakPNb1m0CAwEAATAJBgcqhkjOPQQBA0kAMEYCIQCwL9kS1Dza
+3G7UiC3Hxo2f/kfp9621l8dLV5Uh+yhxagIhAIj28sZe3blr+MkrJHZjkYsAMY1e
+JijPcsnXEr0uGamb
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDJzCCAq4CCQCg3U8Mc7XCazAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzE0NloXDTEwMDExNDIxMzE0NlowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2EyMDQ4c2VydmVyLXNlY3AzODRyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AK0JI2U8gdr/OdkEIeWTRnwnmfXJYyIvTQjsMIK/v2o9jpCh5rRiEJfF/JuypP5O
+yHg6F1Qs6P/XafvxC/jsEe6VLbkwvT8THCKKMEvy6WyJuq58U5N5Zy2VEdMi+Q8C
+XI4QrL6igOEW2W4wgYHgh6qxUee0kUeqY7DJJwvgTVTTHVTWpub/yrY+5LOAiQis
+6eHxgp7xfUKKt64nk7pPdEdXeJ80PuCbau27/lQMhT8mBdE9YPkzX8dpS6ivYWFk
+6VCv/qTz0qxQZF9BHHLJeStRgcGIQOV3Udm/EsjRfcTipDwVdxhHxJxpAOQ/xO+m
+kJRKFitovc90AV9K2TtlG5UCAwEAATAJBgcqhkjOPQQBA2gAMGUCMHzhiyCuCuN6
+UxwoWA0q0nytE4H9t/2PnFGtAgmrzhnb4aWHw4xs5EJbTjGbqfVgBQIxAOIU5d2o
+nnpT/vmlvyijgAHFXAE8qHsKi2XTI7bPy9PDrv2FCS7lLAw8+mNF2mJCug==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDSzCCAq4CCQCg3U8Mc7XCbDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzE1MloXDTEwMDExNDIxMzE1MlowgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2EyMDQ4c2VydmVyLXNlY3A1MjFyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKB2axKYh2X1jRjtLpQIqhjLeIv55HiqlhF2dElrdTQP/qGN9TAYG9m0hAEzLKE/
+djgYMrsp0M9QfSxlNcLYjOtmYVLz57v1BQnDZI7/DS4jWOKfcnlvJSPbwE7LBoLQ
+KKfmXmDWvMwmTBtIEs4nxPph2UuROc5exd1samwS6doAcUm09wqP60aM3lK+9ml3
+/Ukd0coK9824cWa5m4OUcqPtbS8u3LcYJqFb7q7N8q0yYBwuU4kUVpGRlKz5baEv
+43qr5l+Fyib/pNEEAO1YhEW+7WjmvOAW4F/GSTI7SHce3Q4+3EoMoORM9nF9t482
+ojDsCe8emGFsGq0eS6MwYY0CAwEAATAJBgcqhkjOPQQBA4GLADCBhwJBdd9GUYv4
+BCF0NKQ583v33GreTlqD2Z0iXnni5du9A+8qJgG1wZlAGAosqXpZCi7i+3q2DVxI
+hCU67LcsUi59GJMCQgDTLuJI2gkKvqNufZXIR5vR7/RUd4EddkLw2whv4NMfwLJM
+532DeZIH+BtbyfjWYFujjoR/rhhcvtU0+lXsRT4xPQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC7zCCAq4CCQCg3U8Mc7XCbTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzE1N1oXDTEwMDExNDIxMzE1N1owgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2EyMDQ4c2VydmVyLXNlY3QxNjNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AJ/8bNSkM/3fhVhEiFtu2r1fam1CVdbHE1tW1MjF2HOHBt2kz2LwLrJZq8ae9NkF
+82qSw7TB7b5EWWa+o7y6we8So8VenTXnk1oxRRh1tJi2AMFgqpx+LVh4EVqnhfAp
+r7UrtrnM+eAxOyGUVaTMgJKIkhDcfdIS3zHEL1i4tlbmLYRhWUE+wyogZ56FyWhR
+mIpfWv9yV8pMaF1VDEBEN/Yl/6w5f8DG4bQnvkOhL51GVb9GdUBKXI/0bybKTgr3
+Ku/T4q1ppHJSSFohM4Riju4EAgrJ2f3p0ebhX0dtTV7SuCH6vgTpOmSqTIGQ5cHh
+sGFV4/9Aoky/grDx9hp9D4sCAwEAATAJBgcqhkjOPQQBAzAAMC0CFA1Rg/uMcGW2
+lXuIUjKOiWxBhox7AhUDz3eNq7ir06Ukk5DxFpjGWA4kx2s=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC9zCCAq4CCQCg3U8Mc7XCbjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzIxM1oXDTEwMDExNDIxMzIxM1owgbAxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy
+IChyc2EyMDQ4c2VydmVyLXNlY3QxOTNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy
+aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALY3OYbAL3fEdoDHiak/3aj7141wmsobDVXPbNR1QFoHDrUqpgdQR3zHGY+BPjDD
+qvo0xzzIUE40Hg49R3ya6WyECH8ozl9WJ+JS+lH63RYlHDWOJfzjylF6ihiqixj7
+Twjk1j9ZBPjjiGUA/6RlikxsRhoQTDU/pDD6bSn+yosimpePbOao1BDPfntYFejw
+JWPlgC307o++ZKLcGjZH/9IfaKvgiBgl48rVDlQjFNLRkehufk1lviz5CdGph4uF
+D8qoO83mIH/wGJ9kWVjv0nvcEOGeGfaM1mDBwsuzVPXqtvUQHOnCfc18B8y8Fw8g
+bdoNde6lzDo6IMttKQEa+LMCAwEAATAJBgcqhkjOPQQBAzgAMDUCGQCV2p48seE6
+bqHpTgNOe3WdVuZe9dQYJgECGFG66yqtsjvMSg7snsWmMU/S2a8jvMywLg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIID0DCCArgCCQDHAy9pv/zMBzANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcGA1UECwwgVGVzdCBT
+ZXJ2ZXIgKHJzYTIwNDhzZXJ2ZXItc2VsZikxIjAgBgNVBAMMGWRldi5leHBlcmlt
+ZW50YWxzdHVmZi5jb20wHhcNMDUxMjA2MjEzMjM5WhcNMTAwMTE0MjEzMjM5WjCB
+qTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBW
+aWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcG
+A1UECwwgVGVzdCBTZXJ2ZXIgKHJzYTIwNDhzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDt8MTCSkfQyPw/EjB/lzT1yHMDVuniAFLkxe8GzJYOUEbZQTRt
+3gIZ56kX65DDW4R7VCcrFtDbF+PBVwwuBR3YT5adV0mbI0k2jBkteBe2N7CrQMAn
+3m5Mmb3pcxLZOHSSH2HJXJzDGY7YCY4UfdUjNCFro56NeSKylTF1TdVpPkDPzbEm
+BliscaJZ56WB9AKujbVx2apEaNcpaEXnJ5XbEmtccC463TPXX6Su8haccdXrfDFV
+mLe+kwe1w8B/nQbVGWw/v9lysIdx6i1FmWtsU8lJp+kwzg47RiCeb68cumJxvJHp
+/WoZGHFE15CYEp4N7lbF/UuiyWsn1VqHfkqnAgMBAAEwDQYJKoZIhvcNAQEFBQAD
+ggEBAF0+NeYI0T+ZiDhR4B9kOMZfeQGYov+m2d/Y3Ly3rV35NJ6PbuGpb/VbYSxP
+m0l6PhLB/c0V0pyg7MwgwtumhAxlnR5te0wNyYXzuO2oVBoO/8JmsQT8jnCFoANG
+9KNrI+A6ed0V7V1u4Uz3YFbD33FWIDWIR+nfDe07FNl7th/8jzpZAhqudtj372jy
+Andyzedx/kI4yePpjkHf8F0/MocI691C3rPW8uhSYloPfmaTftYoGl7+E1Xc85bW
+JMvnUqwPptOzIVrd2Ei4/4jQDxmI05gDKxZ8aMZddJFkLPKMIFAMwEzo75fCJCBr
+7Qo20ez/vMV+XAWGbHr1qLYhHzU=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDAzCCAsKgAwIBAgIJAIsK5NQHdHWbMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE
+CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg
+Q0EgKHNlY3AxNjByMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j
+b20wHhcNMDUxMjA2MjEyOTUzWhcNMTAwMTE0MjEyOTUzWjCBnDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD
+QSAoc2VjcDE2MHIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv
+bTA+MBAGByqGSM49AgEGBSuBBAAIAyoABEomOz9/rS0q4OSF2hP23h8Cobi6nftl
+PlvgqVcjp+vnica6wXZ8TYOjggEFMIIBATAdBgNVHQ4EFgQUfdItvmVsDmZPpKZD
+nEvW2UkF1GEwgdEGA1UdIwSByTCBxoAUfdItvmVsDmZPpKZDnEvW2UkF1GGhgaKk
+gZ8wgZwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRh
+aW4gVmlldzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMx
+HDAaBgNVBAsME1Rlc3QgQ0EgKHNlY3AxNjByMSkxIjAgBgNVBAMMGWRldi5leHBl
+cmltZW50YWxzdHVmZi5jb22CCQCLCuTUB3R1mzAMBgNVHRMEBTADAQH/MAkGByqG
+SM49BAEDMAAwLQIUGxw8NFGW58flX5kQ+9sTr62kN/UCFQClrPQNlpt7uW9Q5qMB
+WRpd1SDyIQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICZjCCAc8CCQCg3U8Mc7XCNzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMTNaFw0xMDAxMTQyMTMwMTNaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDE2MHIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wPjAQBgcqhkjOPQIBBgUrgQQACAMqAAT9
+re7ILR102TfjTOu5h9XN7kIs42BEGeVyFHGqc9El4PEOy8Q4h5waMA0GCSqGSIb3
+DQEBBQUAA4GBAG0/n0eT7HK/1cgn4Qa6czMBpms0ca22r/V11Aj+h2mAqJNuz4aU
+7q1r+W94hblFrzAlGSZqRIHykFL/yr6/xzStCB3gd9OslvXIjgrGatzuhAttuO8A
+mA6VmPYG2aT5Ih9Bdg/HKuWdkSIeZTDJKMZli/CNWdtl/YcjsmyJDPUX
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAc8CCQCg3U8Mc7XCODANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMTRaFw0xMDAxMTQyMTMwMTRaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDE2MHIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wPjAQBgcqhkjOPQIBBgUrgQQACAMqAAT+
+gt3/qI+svlfcqv3G+ldM/9cBveia+Z4S+UUurYsZR3joZVEUSm2JMA0GCSqGSIb3
+DQEBBQUAA4IBAQAGZFmNoRJUjpqoVkZWOP7ZDgjAgQqKFYI3Mm0QGNPvIEq1VCcj
+LQnx9PY2B1oMKZJQQ/1KsNqnEMm8jlFXq+O25/QuD1/jv37ME2sn8rZe6vsdKLr6
+4SB/GU4mHID4eNDttT4WepT8OfRBO2EY8MWv+97tkUIr9saxjVMYrp4nK0vJ2Yql
+LY0Jw3PgZ11y+WDKwkTWQkOx0SaZhKGRKZelbZZ2xcrV5XUtOFj2Ze27RMARRmmG
+SEnSPUg95eaKjpFbjMiPvTACcYJfnpRKN+ev/dQ0lJa1mZEnsXkaNqzb3q7F91Fm
+/NQ0Qi0OLeNZWeUUo1q3xhA3L2YvRyvz3425
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICDDCCAcoCCQCg3U8Mc7XCMTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxMFoXDTEwMDExNDIxMzAxMFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEeIPEikmn
+11U+4+r1Q1MikFns3u/81SlifvD9FK7i2eHXsm4pJbz66DAJBgcqhkjOPQQBAzEA
+MC4CFQD+m6pQXn1FPgD5NS62SFJwZxTe+QIVAOGRJ9XxBZ8CfPMEDDmNkzEyw5I+
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICIzCCAcoCCQCg3U8Mc7XCMjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxMFoXDTEwMDExNDIxMzAxMFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEsNpgI810
+hR1H/L88VDCIsDJbvQVU/WBqSi+dTVX0E1lITw4S8oJwSDAJBgcqhkjOPQQBA0gA
+MEUCIQDTPITeYMLlsJT8jh2CyDHjEskSGLb62OaM4a0iq7wiPwIgbM9hJwczrPcw
+3uCNgCT990nAdET61HPVfWOBwDJi7tU=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICQjCCAcoCCQCg3U8Mc7XCMzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxMVoXDTEwMDExNDIxMzAxMVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAE/E51tE6b
+bbeYQtaomWTWdwqTlW/8UbNDlC/LDHFXhYhNNJJzGdHoLzAJBgcqhkjOPQQBA2cA
+MGQCMHjfuIklGYjJgYQYBBDNraRptWiaPe7dsI58LZdeJIwJcQcesTpPjjLDszS9
+jfTUNgIwZiD6FVi1yVTckFvPIGqNwzz46KrpKEO1JWR05DkawDnYoUzOoZjEtDhI
+fktezP7a
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICZzCCAcoCCQCg3U8Mc7XCNDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxMVoXDTEwMDExNDIxMzAxMVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAExrjEN9Rb
+kS59txyKYNnlunaAY8PGDBeWy/t5JItcB8BdYNNaQ6Td1jAJBgcqhkjOPQQBA4GL
+ADCBhwJBDPCBtcw+W8IBo9x6F9ajBOlstHeR9lV6dE3sLyJhpV9sn697LHA6fQ6u
+s4x0aT8OJLod+62DFwDX40ATPoT3RoACQgHscuDNMVpOCx8mdka2mvD442Tcb76w
+Qc5DQSd+d0Rw0c9zAvPwObwSttNaaNmuT4v3DturgBVQGdb02bmQIuDNrA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICDDCCAcoCCQCg3U8Mc7XCNTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxMloXDTEwMDExNDIxMzAxMlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMTYwcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEuQ9FFr/a
+O6E1WAQ0LtG1wH8nczXWLqJc7f+sgDgzrub2NjvOvfcQ5DAJBgcqhkjOPQQBAzEA
+MC4CFQGBzvmRQ4HhuGwqOnKztHmUS9viEwIVAKZCrx0tZO03y9nSpGBRXeTB+bb2
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICEzCCAcoCCQCg3U8Mc7XCNjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxM1oXDTEwMDExNDIxMzAxM1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMTYwcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEp8qqFVSZ
+48NmZKnPWpaJXybje/F2E0wDq8rNOX+LC73zfK3ZC7xDvDAJBgcqhkjOPQQBAzgA
+MDUCGQCQP6SvfPS/AVHix6tG38uduEl53DG97JACGBWSckcbWsXYXDhKo3LrNy0h
+9uBgV9Gs5Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICEzCCAdICCQDt+YU/aZ6s4TAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl
+ciAoc2VjcDE2MHIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu
+dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAxNFoXDTEwMDExNDIxMzAxNFowgasx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
+dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV
+BAsMIlRlc3QgU2VydmVyIChzZWNwMTYwcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wPjAQBgcqhkjOPQIBBgUrgQQACAMq
+AATr4Hx367/3ldBBiTV/6WfVuaRjVYUrFtcXLqsF04z3yL3dw4TcwSnQMAkGByqG
+SM49BAEDMAAwLQIVAICB0ciEiBjudkS5M+TgDRowS9wqAhQxdt3pJoNMch0sBGvy
+ZvpPEqW4lA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDNTCCAt2gAwIBAgIJAMWAX1EW46gEMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE
+CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg
+Q0EgKHNlY3AyNTZyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j
+b20wHhcNMDUxMjA2MjEyOTUzWhcNMTAwMTE0MjEyOTUzWjCBnDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD
+QSAoc2VjcDI1NnIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv
+bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNzAD4317T6bb1oio1J2awuyb2wS
+F7okuHwbFhfTuXgvLsQcAWh34Md5SJ711rN7an+sEr0RVyE6h6zgQkD8DUyjggEF
+MIIBATAdBgNVHQ4EFgQUSPfZCnqQodFg6YlBySBCsrjQ7hYwgdEGA1UdIwSByTCB
+xoAUSPfZCnqQodFg6YlBySBCsrjQ7hahgaKkgZ8wgZwxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3QgQ0EgKHNl
+Y3AyNTZyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5jb22CCQDF
+gF9RFuOoBDAMBgNVHRMEBTADAQH/MAkGByqGSM49BAEDRwAwRAIgeXLod9K7A3VG
+Rw/3wMXrnxNUA+K4yzfAf1OlCy8923kCIGqu3+9B5lZgHWvHiWBkjpkBqegBp5t1
+7YyV4K1ALxcH
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICgTCCAeoCCQCg3U8Mc7XCPzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMThaFw0xMDAxMTQyMTMwMThaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDI1NnIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
+AARnBDetfBY6JJYtJ6BTttMX/edfb+Lc/DCwTneZzjE5lUaM+LzNwNt02H/+XD27
+hhTDJWXP5r26qZzuBkwpi2UJMA0GCSqGSIb3DQEBBQUAA4GBAF1uQyY7WpxJkkht
+Ru87ib8WISy/liosB1ijy2bcPHjcpKRSW+LH2+A2+mQYiasfOkLck+9pS7efhFtT
+b1A/3BkI9tMGhvMgop8860Khkl6pRETNu/nlVIQ2xzdRdpvJCmFPa67YK25/cn0O
+XN6PHMPJF1JVyJhppvjmV/u6TS2N
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAeoCCQCg3U8Mc7XCQDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMTlaFw0xMDAxMTQyMTMwMTlaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDI1NnIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC
+AAQmlPt4PtwUBkFqDl1dc+5XqpiPYJ8t0oVklz86WljYLHXNWl20Wd+t+/4akyc+
+3L9Wr2OzkZyXWv4nA4UteyFiMA0GCSqGSIb3DQEBBQUAA4IBAQBWbbxxLkiwz7eo
+uN7Jfa+I9xMNFwPhCc7api63Z6Q6P1tcdTxtl6xQefdiFc550H+tOWb+sn3EmBFo
+r8XIPAb73dG+41Vp2bSajkY9povAT/UHFYt9rwr9bQfWtJktd939A/hQix4YImzV
+7cw8b+SAoEWuWifScDKDlFQvs4zxUAOxFeXbOrb3X1oGDjE93TEx7+x9DBNMDSu3
+hN11j9cyMotJCWB5OFYzCf3ibwwo0usiz768Wu1C3RvauET+xbcE3NkxM6rsQxI1
+lNXM1NNbm7/nOm+zK2lTH7g4Qui8owSgwR0uwEHhmrAHIug0uHC7GbrIn4yibkrq
+xkZaaUr3
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICJTCCAeUCCQCg3U8Mc7XCOTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxNVoXDTEwMDExNDIxMzAxNVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErJOw
+EmmdQcay7oSZTNySdc2m4/iwftH3KfY3wDA5qVusJ85AJUYPbwEvqloKpOTdCZI7
+P4za7x7COTuZAzVFVzAJBgcqhkjOPQQBAy8AMCwCFG5V4voKrcE0UlK1osPuHXZD
+N2f5AhQR9TzLTT7D1Ee270xtQ+Bwcq9mBA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICPjCCAeUCCQCg3U8Mc7XCOjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxNVoXDTEwMDExNDIxMzAxNVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERwmM
+YUHXpp9LfbDmk33yWOjAf9flz43IHqFq2xa6bczvcht7ZDka7UmSOVQ8A8d2FdjG
+BlqAnEKvCHlxqw41SjAJBgcqhkjOPQQBA0gAMEUCIH++MmRaY7IhySci6HGfsACD
+otlDDt6kvpJOCTXQS0G8AiEAwNA+4/wVeEvtjendgLX7icNK33L53fK9CqiZovfi
+w7o=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICXjCCAeUCCQCg3U8Mc7XCOzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxNloXDTEwMDExNDIxMzAxNlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXjcN
+bCMqCgsKw4WhdPm6ankP3pHHg/bKWiJXJ6BI4QQYGsNBXPb8YvwP6Q1tFPSyjSJo
+VRUVmWGn9X7FzQAGQzAJBgcqhkjOPQQBA2gAMGUCMG4SIhLBYKht8fGzVRte/4lJ
+Aj+hMTbCuNa36BMOoez16SskyhCtar46QkFIGnmoQgIxAKIxzKgH4dBAdRGu7fsU
+OawK3AvNYm9Xb8bn7js+KjB4pJdYBZw4Q3kHB2cBgX+hvg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICgjCCAeUCCQCg3U8Mc7XCPDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxNloXDTEwMDExNDIxMzAxNlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH/cQ
+KncxMblNmy+gpvCcfxdnC96RTzVT5ZdbeTBlmsRLXxWlrORx4+URCmHGpFdFzpmb
+Hfc8rPAIQNGiQucuQDAJBgcqhkjOPQQBA4GLADCBhwJCANGrCUSZ/X2XMwFavryU
+JGEOQFLMAAsEWVMUYbJifwNyeQVuwNV7cJjE5UGEzFDLbazmdrPVmDeSt4nQYCYN
+zy/nAkEhOcJqFzXb2PW1E2MK7qGOswGNr1EifKIF5Tn//nCmpfDSH7G7VXH2IqPC
+X6P0wdhzr72Gy3YmjXoj/CTZ/fK6Vg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICJjCCAeUCCQCg3U8Mc7XCPTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxN1oXDTEwMDExNDIxMzAxN1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMjU2cjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHEs0
+EFQnApDDnOBH0DZtSu7mDqzv3BEwm43BWfjQbuvWtKZxTzCc6Pv3dxLgdblE3Fl5
+MK/8Gk3ugDZwe563KzAJBgcqhkjOPQQBAzAAMC0CFQD8O8WJ7okGjHRs/J6rWo+n
+FNrwCgIUcFcuAK3K1tfYuE3QGm4smu2n8iM=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICLzCCAeUCCQCg3U8Mc7XCPjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAxOFoXDTEwMDExNDIxMzAxOFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMjU2cjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6I/f
+uxD+wYynPua+enF00uSb3hHLi105QljhMjfpXRyMt7jW7N0N44AeQLqvUuX/Ou0B
+zXDtE8R5tbU5n1p9vjAJBgcqhkjOPQQBAzkAMDYCGQCRU8ROxYXzP4UclxGtca7W
+b03WyYZAva8CGQCTE3650WcJy0ka07FL3RuScknp/D4SZh0=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICRTCCAe0CCQCwSXFmzpBH6zAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl
+ciAoc2VjcDI1NnIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu
+dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAxOVoXDTEwMDExNDIxMzAxOVowgasx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
+dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV
+BAsMIlRlc3QgU2VydmVyIChzZWNwMjU2cjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB
+BwNCAAQtDOsv5pQz7RzsMK68LUeAIDtdJddk55oLsrd2+93FHIr1CiqOwr/3sH3V
+USapRS4Xlb7VvtkFmCGLMna0TEdiMAkGByqGSM49BAEDRwAwRAIgGqI3kC9COsLQ
+nUnZmwVaNp6le9PQwro6m6b0r6MgaOgCIFH1x+AgAV+HvbGkPTjIW+Cp1oUcbMgd
+iDnA5kk037nh
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDczCCAvqgAwIBAgIJAMKpQMf1IUoCMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE
+CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg
+Q0EgKHNlY3AzODRyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j
+b20wHhcNMDUxMjA2MjEyOTU0WhcNMTAwMTE0MjEyOTU0WjCBnDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD
+QSAoc2VjcDM4NHIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv
+bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMaXMYyVYpN6QWe+5TpTN8r9jbAPUEO/
+YuR23HOX5Kq1bP0GoF96uXx53X0V0EOncf/navTd9e7oF4BOgkCsHe0bD2p8b82I
+IbQ953K3DDT6eIW4TXF7YvS/xF9ByIx/iaOCAQUwggEBMB0GA1UdDgQWBBTqywJZ
+V6bCSeOnSQ3riDM0TDfIMTCB0QYDVR0jBIHJMIHGgBTqywJZV6bCSeOnSQ3riDM0
+TDfIMaGBoqSBnzCBnDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9y
+YXRvcmllczEcMBoGA1UECwwTVGVzdCBDQSAoc2VjcDM4NHIxKTEiMCAGA1UEAwwZ
+ZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNvbYIJAMKpQMf1IUoCMAwGA1UdEwQFMAMB
+Af8wCQYHKoZIzj0EAQNoADBlAjBb8D7U8OiqO8ZU9gUrkMo0Y23AN58o3TSapRge
+7qiAuUOVraWioNrrNVpC2z2YI2YCMQC53bKQvlqIQ+GbGMY6C5v+F/zESmVie06v
+ba7qe2vIl6OIBiPOP5c5gCj4Nj1g3uI=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICnjCCAgcCCQCg3U8Mc7XCRzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMjVaFw0xMDAxMTQyMTMwMjVaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDM4NHIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR+
++z6+8do8BpOuYXtGlnKN6jwDj1MdbcUM9sqJBdvVnBJdHfOCL+nVGSvyTY5BUxJ7
+FT5XG+9H0+juJlC7iUu7guxwXdhkChnOQ28buUqsWYH0yHiKJe5F/Re2ESERPi8w
+DQYJKoZIhvcNAQEFBQADgYEAPPio0j09V6vXhN3GYwa3ARjboJIO53kTNa65UGgC
+qvdLNufcBRldt2vezR0NKj3CTY+/uD+lNwTp+HdnIGkz0hHA722nv0VZGX2MWdMs
+/2/D36kJA89IIPLKkQjzmmjIQ9wNDSAt31j9b/TiUfeodaEZZR/iST5UHDvkSIZE
+EHs=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDHzCCAgcCCQCg3U8Mc7XCSDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMjVaFw0xMDAxMTQyMTMwMjVaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDM4NHIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASw
+i3q++pOW/2tqHTpGB6X85pKO+oCQa/1KSQhKCjVExJxwfQlClNkHgerFUnMr1Zvu
+e468EX7/r4gdnMQn+8FPWcYZ+2PYLHaNa4zmLPZq1YJRq5gjIU96uE9nJLoCJO8w
+DQYJKoZIhvcNAQEFBQADggEBAE5R94CP/nqChXrMPmHThRReMGXc65FOXtXrQvNb
+YKa26EKHy50fqh0sZkfIMqF8CVYhpMM96f7xJgHBJ1GY20Ayp4Om+nmC1U6in5yk
+G+LO1H5uDwn3be9tLXW9Jiif/FSDJvY7GhWMys9W9QpojHrNT1eVGPu5zmZxfvDn
+nPlrxOxx2yVSkc04zAfBibKd+iNBLI9x1hEWv9gVILow/nsF+HEceGqCKrKtw3CB
+vRek+mUZCUDD6gKsN0LeGnRbEFTjyYp3iqbA7/zaCsXi0C9RowKD/uhQmmsduxFT
++mRBNP2Ni4BGJoFGt6ynkhQMKMcZOgCfG9qu9xFpRa2wn+s=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICRDCCAgICCQCg3U8Mc7XCQTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyMFoXDTEwMDExNDIxMzAyMFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEeU60tao/
+d69lrHxMAx6xC9aIXgbFzDxSl39sQORDuiv7YgqxSNxusAnCCER5YT7i0WfH2LEh
+kSO16D40edXpxFXXctF6uOT9KK84oCT2ciV1QbArI1ROExKum1U/qYd3MAkGByqG
+SM49BAEDMQAwLgIVAJNssWK3wbZ17bXdaVCc2oydMEqBAhUApNb51n/19FEejcXt
+msPefDlmlWA=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICWzCCAgICCQCg3U8Mc7XCQjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyMVoXDTEwMDExNDIxMzAyMVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEUKGBne87
+l7cssaiEtxw1EOATJFv/yHz1811mfKPqCJjpVi5NVLt5q2b7DfWvi4839ywNdD5l
+ne3mzh6WT20lH52LkS/sMj2shtx0NAIWQM+SJMi7BrBRtymaXtRZQQxdMAkGByqG
+SM49BAEDSAAwRQIgBmcyaM69Ryota/XMkDJzkW8a3zCZahsE5DlTrg+Y+VkCIQD1
+Sp6MuZy6JzwtASW/l/Z313mvQduVpzdtezQtvhXqMw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICfDCCAgICCQCg3U8Mc7XCQzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyMloXDTEwMDExNDIxMzAyMlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAELraTwEbQ
+rTk40nU76I/MUWvDrX4HEhnNt2Wor50zzHpNtcWlDh64xyDIUO6IgwPumY93PMUR
+E2ObEw1zm2jLx+ld32CHZhVD3NFg1eyUzxUWXlnV5YyMQg4kM+Q4RfSoMAkGByqG
+SM49BAEDaQAwZgIxAJp22vZKPO/FetlqwLIcghqoy0rueCskFQC53fhU0zAybTiI
+zDLzM3AwwwIjHHIvOQIxALyleafaqz+Uh10WWnhenZ4wEcGtnvMq7NOLA26DttBq
+Hda4UJnBkRFBo5+N0m+l6Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICoDCCAgICCQCg3U8Mc7XCRDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyMloXDTEwMDExNDIxMzAyMlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEtyVcUCcJ
+RsoFtoxLIFg32suhU2Vsm3HjI5+uMg/04EdQWsSZ20b2aPZ0G9eOI//t4LT9ha7D
+Q8XjDRQl4+MMpcQZPz05CPeM3V+51ORa0TsU5H55mkaI6jzyqjBqU1zMMAkGByqG
+SM49BAEDgYwAMIGIAkIApq6d1qKZ5OzFIEJQ2eqFa4TRW2BH18BhK/5+LHv4hI5Q
+yIFU0wvnWufrlDpPd0sHZs4Rtyv7DXKLalafI0rt8wMCQgF3KIktGZN0ppn42anJ
+UgxeryI8lssrz6y7o1t8bgkCSpPUHFOJiaPcAMaCJIy9/pTkNqItAS6vD9OXvLCq
+qkTIUg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICQzCCAgICCQCg3U8Mc7XCRTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyM1oXDTEwMDExNDIxMzAyM1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMzg0cjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEkRuBmaS+
+693na8/kbscQtkKYQyhZ1w+fRbK8vSoPey6GxxDsFU01DAZtxhAiFKDh5Eh1s8ur
+goSjJFGjIJWSzgzK2NN6zrvlpuNFYeIbM4ALvRsYDAMJ+3tl3Vq30BWhMAkGByqG
+SM49BAEDMAAwLQIUDc0O2pwXZTxjX/TO4dmxlMoBUUYCFQL051eCJ9zO3XAww5Rv
+n2Obyhhq6w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICTDCCAgICCQCg3U8Mc7XCRjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyNFoXDTEwMDExNDIxMzAyNFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwMzg0cjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENttarKTc
+CJ4k1b8Fd14pSbGQprsbAFfxk7QhONku4iyam7bmVM5b9Q0SjfNzKIT8yW2swCdi
+cFFOcMlpYFGbGNk9kV3mkMhHi5qgbw4iv6/U3WiT7kxfbJjNzWAcGQOQMAkGByqG
+SM49BAEDOQAwNgIZAIDGXPjGWx96qYTgjUzg80VsiRV5TINzjQIZAIoa/jec5ioW
+ZAvx7piEzY3fRw/YpRMF1A==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICgjCCAgoCCQCROG+IEgiARDAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl
+ciAoc2VjcDM4NHIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu
+dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAyNloXDTEwMDExNDIxMzAyNlowgasx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
+dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV
+BAsMIlRlc3QgU2VydmVyIChzZWNwMzg0cjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNi
+AASCHyVEN+D1kiuu8teqNLvuT/r0cNoE7RyKEt9wpkOMB9NdcFEzVClX9A0AmovZ
++OGwM4ltWN40BFkImyHmwzGRwZEJYdgmFtZOwRKJaMWadbqpto5PtuB+SpFhtQmO
+dDMwCQYHKoZIzj0EAQNnADBkAjBCpsIVKSYpyYXCWfeYVf5odGJ7ZAgnT7iYstM3
+HZBfdXA6t8zjXICA2ICOqrR1xUoCMDm7poy6GrsHEOMsBoVS5T9U0p3ouMyOhkIm
+0EykkGk1wK+9Z6QM/DLP8lLJB0IrDA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDvjCCAyCgAwIBAgIJANErVg+ok6iAMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE
+CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg
+Q0EgKHNlY3A1MjFyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j
+b20wHhcNMDUxMjA2MjEyOTU1WhcNMTAwMTE0MjEyOTU1WjCBnDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD
+QSAoc2VjcDUyMXIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv
+bTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEADNScfIghIZGN1TI9A6iM8F+LrAg
+xrInc7nmKIBtdYYfsFWwT4P6bQqNrOZixrSmTiZXSGWhzaj+gGAdF8vfr81YAVNe
+1hkuP3iC/4iaRk9vyMDHNvKDHQeUxFNIL2UTAfSTl0vYmL1C5KkpYU3+qBVFTLpa
+7uImk1s3wQIkTTHyFLLMo4IBBTCCAQEwHQYDVR0OBBYEFAwP2eZOjIq6F87PsSjp
+qniRzxZpMIHRBgNVHSMEgckwgcaAFAwP2eZOjIq6F87PsSjpqniRzxZpoYGipIGf
+MIGcMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWlu
+IFZpZXcxJjAkBgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRww
+GgYDVQQLDBNUZXN0IENBIChzZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJp
+bWVudGFsc3R1ZmYuY29tggkA0StWD6iTqIAwDAYDVR0TBAUwAwEB/zAJBgcqhkjO
+PQQBA4GMADCBiAJCAYD/Rk9FMPk0ZzNrXCHKRdXkjBqfsoB5VYRjFIQnIz8+xEAC
+KqHjdmYd4djR6l6NA4olKQn+LUwE2hmtom6res2GAkIBPDlBcwGzoDxU4CQQb/rP
+cFEMaA5I4fpGdSNYtIJDkXNluVHAPkv+uK9lrhsjuvpVbh76+mM3B9bg4Tq6+Pxb
+KN0=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICxDCCAi0CCQCg3U8Mc7XCTzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMzRaFw0xMDAxMTQyMTMwMzRaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDUyMXIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYA
+BAB+Wp/To8yXNzzp1Iw12ACR2Zc2s8o19H3E8cgC26eDcDYzlAf67/ldZyQ0WDzI
+xUlxeJjmNcdiavR5usOo/2lE2AEK1tWu/xVhZZZHWiNQ0vZdZ43BHtBPcqdHRZKv
+RRZWrP1pd9ubq1UDzegZdFQ5JwwQjPXz4jpOfTYO5TrmftxZjzANBgkqhkiG9w0B
+AQUFAAOBgQAMYv77n1SJ+MDneFbJ2ssBd6aw+hbVqwBVopd0YC+i1Kt5bDe649d/
+vMAtnEmOF8G9/ugg5XVoB0M+6DINC/a5HYYZEYAW/g3Q44XaZCJWOvEVYhFAeUNb
+BigmNP4yGv3vP+1rqwEqhb9quxYF2n1e3BuBbi9HkIf2Gp0sMP3pcA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDRTCCAi0CCQCg3U8Mc7XCUDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwMzVaFw0xMDAxMTQyMTMwMzVaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjcDUyMXIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYA
+BABjwtNCj8IRxv8e0qyePjKGqOvlcPDzx54bcokXDVHxWOL3OEljqi8qWxJm+Mzg
+Xhr888VBZdWjF8iXGgtGPEyNRwF635gdYvpcJoz+I1Jg5XzJYo+kLpf/xt5V44/P
+EizJQyx/aJ4thsf2gCfFg/zWpDQbcjrwjz10fzLW7rkt7otbAjANBgkqhkiG9w0B
+AQUFAAOCAQEAK88ka6Xlvl/Bg2W9TyAh6zPEtDHU3WPN10LxU4ghbStUGx/YupTr
+LSg7nLOQo9CI8LKb+tpTaMPmCSTH5Cfwh+f7Uw20wbvPBg06GiBdQjuK3Dvk64B6
+41s4Y75J0wpXJfgezARRlLe0VLAWwH9ZnZRiqtndF527dPBi8EF3qc8X1sGaQ8tn
+EVCd2ifptLgp+eI78QdKsgDFpjDOSJNbLDI1yQcm/0EafyJLKd+xH3EBkaaiw+OV
+ctYsD3ebQ6tldDnopgbisTmtwvHGqzVGTG8DDX1El2YhVe4bwZTtLBjcbtJxDg/V
+0FLkpRjQ/sDqMbDMb6CUoHRa8Urq13e0Cg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICaDCCAigCCQCg3U8Mc7XCSTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyN1oXDTEwMDExNDIxMzAyN1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBQ/O2
+98Fp8ZlEDVNNUHEHYrdrhmofdEsOMsyaabFAWp4cexMjGYgOZaD4/sCYjc1N9sXp
+1LqIlBVeAfQ5BCSdqJYAaUQrvL/4evYANvIiymw/peV60y6Vchz/XuKH3M4RVCxa
+8d7eeobwzCbM2PjR1loiInAhdFrKJHF2z3M84MPgQJswCQYHKoZIzj0EAQMvADAs
+AhQ7SDvm2UNjV6SQf5HoMMrh+K1V4wIUBIIDOf2vtxEmVLXZvaoJGbOf9Vs=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICgTCCAigCCQCg3U8Mc7XCSjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyOFoXDTEwMDExNDIxMzAyOFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAqYn6
+hGbL5dTx1gnWnUBp40JXPKxlrAi4p6ofvM6Kd1HwtQLgeNpIqi1TtxXPc4HkHu9F
+gqV5pOJhEUAF9ABqeigBCGHqHtp7eqq8ZKVfIdQKDUTGsHZe1mkQA9JHqBwi35Mo
+TOkUlws3aEFtXyfZcjgUd7PYzOM5Ry/m56RiZGdMu+EwCQYHKoZIzj0EAQNIADBF
+AiEAzxdUODAqmgqDDM13NLrIREDlN8BlRgFUW4AFxOg87Y4CICW2qf+ioupQuvWE
+da8fLQVnCbVbLUKFZlJd02uIsud7
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICojCCAigCCQCg3U8Mc7XCSzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAyOVoXDTEwMDExNDIxMzAyOVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAx9bl
+XZ1Voix3FACqRqpURu5ZjoPPMIY93jbYEL6wZdDU4FFbXOiTYt2At+aQPi8Rjy8a
+DI3CxXQ5PCPrCPip8gwABVTtjfQzwJwbqIlZuE/HZL6ZmRkz1iCOmWhk4qDqGUpw
+/k78Wgl4GYPBdsZOxzSa0g+XIQEW3MeLGzpEH86zKY8wCQYHKoZIzj0EAQNpADBm
+AjEAv1WKxcvLV9MQWHIu1rWic1soAGPIt30b/7Q8VZB7HnRTBtOQUteQevoHHxjo
+DZWaAjEA43j2Sh07TKD1c6lglFFONNNuR7orVCapEgoXNgcMceF8cwIuYyCqW75A
+EneclLfr
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICxjCCAigCCQCg3U8Mc7XCTDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzMFoXDTEwMDExNDIxMzAzMFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAyY+l
+SUAwJE5hPEUCwuccerdfzoZMp3c9Hkw/fnvVjQpA0Vvb0piBJ39MRCGYi63RbaRs
+QexmUq3XGdbL8mwoV0YB5niOZ9cg6YeqXRAnkcS/GboHNjtYQWysta+D+dfX8S1g
+YBuXdNZrbGdAj9UP7+gz/9WrPOctz6gwyeiKLKsvosMwCQYHKoZIzj0EAQOBjAAw
+gYgCQgErxOvqzrTt5eHrdH4ZxUn4AM9dBAqX33jKXBKNuRgmyYIxoIO2c2tqkdxC
+rXmeudFZmFGEEBor5bg2RMI6pkcoWwJCAe6TIx0KcaF6D1wW9tlmRXZ+888SS6Fq
+BdVwn4a8/6TrTxQGmDD6qVTwGco76umjHnam50Kcvg6iBAjfSUmwj/56
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICajCCAigCCQCg3U8Mc7XCTTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzMloXDTEwMDExNDIxMzAzMlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwNTIxcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB3xU0
+hOYQMnJ7L+TLdSkB7ruVnjWo6iwLe0N2GlpCc5jSmBfhGr0NyoKrNY1Zy+VcnGCu
+vYgT/aqN7nOnZ86qoQQAq8o2wpdlTbeyzzE26txGTVi+7IN3sVB7DFmqI/R6ngKK
+GdkmE6ZOBBcyipzOc/eXRpqoRaIRA+FP2LAPdBnsuNkwCQYHKoZIzj0EAQMxADAu
+AhUBOyoJaoo5E6UZ8ICdSZAsL7FpwcMCFQJ1wcD/KuK0g+2WMgpCAuElR+dZIg==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICcDCCAigCCQCg3U8Mc7XCTjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzM1oXDTEwMDExNDIxMzAzM1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWNwNTIxcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBvNN+
+2syVq0vx/Qj1W5IYpeUdyswTzyBNdz0LveNcNEV07jql3o25dPHNGZcVcCvPFw2H
+2zpaWV8t0YHjHETM3mEBxgyxwpbM3dkdCuM0VlKEA+rUY64QU8/f0WYU+1cFPBBi
+fMOuMKXfb1JNK93W9A9jzmFSVJJVauXYs6JURy60Z+8wCQYHKoZIzj0EAQM3ADA0
+AhgoBo+CqnLTn7UxFzNYtHabS0zMzBzBhN0CGAaNavBCHkk1eX0xmp+7BIxHnWOl
+bbeeYQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICzjCCAjACCQCYUruIqLYp5jAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl
+ciAoc2VjcDUyMXIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu
+dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAzNloXDTEwMDExNDIxMzAzNlowgasx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
+dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV
+BAsMIlRlc3QgU2VydmVyIChzZWNwNTIxcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMD
+gYYABAH3WSHvJZH8mqyGfVxtoyF5pCUVJZTnebvRphld+jK1PFKlzglYN22J8yN9
+l7Ca2h2OjuuEVj3fZAwSAInZtZQzxAEHFMZEVAzoHUPjx9qEAJiNjXcVV79cvrvc
+Q8SbYBF3vGB0su2Qydig+VEjmkyklGhxFLQE8fo7fEZh+FfwGG3x6TAJBgcqhkjO
+PQQBA4GMADCBiAJCAYLsxXVifQfzuyZRMNqzldUcASTgs1L/MMtJcEvYtFpeaGXd
+Nn1jIynPkC3rgjbejtLe4OypPymrkVE0Bjn3rKU/AkIB1TtXqfmYkTdOO/AUriRl
+GSatOobx7QQ+CyOtziObl1UPe7hDYGX8quZPxWnx6MgtO4I4sSZWA7/0C6N61XSq
+NPs=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDBjCCAsSgAwIBAgIJAJUfXqNiGl4gMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE
+CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg
+Q0EgKHNlY3QxNjNyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j
+b20wHhcNMDUxMjA2MjEyOTU2WhcNMTAwMTE0MjEyOTU2WjCBnDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD
+QSAoc2VjdDE2M3IxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv
+bTBAMBAGByqGSM49AgEGBSuBBAACAywABATc2/gR5Sk1spq3ktZK4UCWH8ILGQJy
+xhua4tLSekXuk3joLxw7GVD/K6OCAQUwggEBMB0GA1UdDgQWBBTRQhIcGNnfzY1r
+7mAO0j6l4jrt1jCB0QYDVR0jBIHJMIHGgBTRQhIcGNnfzY1r7mAO0j6l4jrt1qGB
+oqSBnzCBnDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3Vu
+dGFpbiBWaWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmll
+czEcMBoGA1UECwwTVGVzdCBDQSAoc2VjdDE2M3IxKTEiMCAGA1UEAwwZZGV2LmV4
+cGVyaW1lbnRhbHN0dWZmLmNvbYIJAJUfXqNiGl4gMAwGA1UdEwQFMAMBAf8wCQYH
+KoZIzj0EAQMxADAuAhUD5UVJP72K01PbvDeANWleHbjxd48CFQN6Qt34E0JeefbC
+NVkYG6pXLegBvQ==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICaDCCAdECCQCg3U8Mc7XCVzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwNDBaFw0xMDAxMTQyMTMwNDBaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjdDE2M3Ixc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wQDAQBgcqhkjOPQIBBgUrgQQAAgMsAAQE
+/r8twiEWpvxX4VUSmCw1JJNHF9IDvIxktMTtZqcK2/57GElqT5Hmi1swDQYJKoZI
+hvcNAQEFBQADgYEAHmeOaUdqT4x1o7UCpXTW8D2+XCTCFMpPENH0plL7ALUj5R2D
+av2TvKKSwpbyOJa26Rx5KEMNntGpSN1X4+a+wPHZ87J3wmtU7B6nEaHIkFM/iGRQ
+M2Ip+lBhebd1e+itwIRnpFcNt5dD276F30928E6kxwSge2uoQJySFV+Xuho=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC6TCCAdECCQCg3U8Mc7XCWDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwNDFaFw0xMDAxMTQyMTMwNDFaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjdDE2M3Ixc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wQDAQBgcqhkjOPQIBBgUrgQQAAgMsAAQD
+jbQ3J7+yvmgc++WxXN52nfRQWnkFc1DUqspljUJyusmdPI1+8ki7FcMwDQYJKoZI
+hvcNAQEFBQADggEBAAF3SF1Wmlk6F/IeQs0hlLHF/ik0xWngsO/Qgqrax6MGLdPW
+jjJDE1UY6mjNXo8kuV9nIr4+27RN1q3hlSaVC47BX9kZNOs+nO/8h4mFXSV3osq4
+7RrJ5RJ/seXk6s7QItfmZslv7LR/FrzTF7pDv385WwwRXpfhCIY3X24bSt7dgK4j
+CkXf6GV9WTrICmNRBeV8/LJAbETU6XPhBXpIlYO0sasSfbCd/j4voIUhwZgPXdGx
+iNVWcwgntcOwx4wXJOoWoiiU/j+eS6YDrsxqgdV3j0+JYWQNUvFhrotI/HjbZ8RU
+rUiYpAcbghxkent0pcmkcHbJJcj/8/AzQcp+iYg=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICDTCCAcwCCQCg3U8Mc7XCUTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzN1oXDTEwMDExNDIxMzAzN1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEBW5dGOJD
+CIYYqj8GEUDWGalB2d6wAQzBC6qR3h5seNsC212ApAdfYdTUMAkGByqGSM49BAED
+MAAwLQIVANtclGRvcbIOV+XiYhSBeiuj/XAZAhQjQSZ21bwoOnKjnybeDYMhqEIG
+1w==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICJTCCAcwCCQCg3U8Mc7XCUjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzN1oXDTEwMDExNDIxMzAzN1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEAEvhHRk9
+YT/OvjnDdKuUpfv4RLbvA+ea8m5+4zH4agPsJFjEgC+Tl2AoMAkGByqGSM49BAED
+SAAwRQIgEE8zOqy0HkGCnAqdj0xUdpN43vyhBy08G6wx5tWFYekCIQDk0Rc/a8Mz
+id0zWgeo4cFUv75+S86WaSSxnkbgKD/PfA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICRDCCAcwCCQCg3U8Mc7XCUzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzOFoXDTEwMDExNDIxMzAzOFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEBLc5EQ+F
+QABNsN7pyoOE60q/aokmAgE6Su1TfwZKvAGjxcAF4+l/I015MAkGByqGSM49BAED
+ZwAwZAIwD2i5VWRPgSSx/Q2JgJTN96q/T/rmDW+IzyqEU78KwzVIhf8zUIjQH5Pv
+az+KrObIAjBNUjCd2rUJorAOrDcf/s8d7KFBnxoiRjNCRKO6SiPvI8Cc4jaXfja5
+XZJjzk8P/nc=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICajCCAcwCCQCg3U8Mc7XCVDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzOFoXDTEwMDExNDIxMzAzOFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEAcPPApQN
+hrXdgu0Rxv5SSy9Exry/Ag78xFNPzTR9mJxS1X8tN1wfiJOBMAkGByqGSM49BAED
+gYwAMIGIAkIA1Fm7h0vZAywp1Wf3xNI3wm29lK0BSWOVO6fQyWYmKghKi325Tkbw
+MbyO3D9YXC2K1G7zQrG5GXA1Jo82ndhpsKUCQgHK67lXzYtfCndSWDrPftXEqn0T
+epSGI3I5vxlJuvx2UW1fvZt098Ku4bR8ixKVgDHo8TuEEsJJg+johh0oZHQj7Q==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICDTCCAcwCCQCg3U8Mc7XCVTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzOVoXDTEwMDExNDIxMzAzOVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTYzcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEBd4sp9FM
+F2RQWVjZqhqKPRhVhcOrB20Iqn3MfUIXpKnZWBugJZYgQVIvMAkGByqGSM49BAED
+MAAwLQIUAwzB/r2hCllysJwxwC4VKKF90igCFQCO0ik9fYlw5RInDzDH/f7xjOOS
+gw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICFTCCAcwCCQCg3U8Mc7XCVjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzAzOVoXDTEwMDExNDIxMzAzOVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTYzcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEAgD1SibB
+UQJtSvkK42sdggot73fzBk2J+aj3WSvDHwMXsYslaPQG71lYMAkGByqGSM49BAED
+OAAwNQIZANBEfel7WcTKFV0q3UTeod1T3K7ClZQpQgIYZe6dll2Llj3A2S6eRB1G
+qjDJaejrFGxR
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICFjCCAdQCCQCKZ9MLoj/3JDAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl
+ciAoc2VjdDE2M3Ixc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu
+dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzA0MVoXDTEwMDExNDIxMzA0MVowgasx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
+dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV
+BAsMIlRlc3QgU2VydmVyIChzZWN0MTYzcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wQDAQBgcqhkjOPQIBBgUrgQQAAgMs
+AAQAbsGEXvpTlsxcf5b1S0Uv+CW6aDIAD1SB5MwpErkmq6eCFPVF2c3iIZ4wCQYH
+KoZIzj0EAQMxADAuAhUAhh4DeqrebKZ7IoIO+gYcs1tT4IsCFQD51UVBnZrYhqHT
+tKfswmapHLXMzA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIDFTCCAsygAwIBAgIJAI4aIMim8fazMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT
+AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE
+CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg
+Q0EgKHNlY3QxOTNyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j
+b20wHhcNMDUxMjA2MjEyOTU2WhcNMTAwMTE0MjEyOTU2WjCBnDELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD
+QSAoc2VjdDE5M3IxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv
+bTBIMBAGByqGSM49AgEGBSuBBAAYAzQABADC/YtwwrsyHusPx05mHRMV3Rjw5dcw
+LLUAIh3jrWVGFFLWZl0QCs2xBnGF6KfjKnOdo4IBBTCCAQEwHQYDVR0OBBYEFHVx
+jVCVss3ZetdFkR0auNgmLXljMIHRBgNVHSMEgckwgcaAFHVxjVCVss3ZetdFkR0a
+uNgmLXljoYGipIGfMIGcMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNV
+BAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFi
+b3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChzZWN0MTkzcjEpMSIwIAYDVQQD
+DBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tggkAjhogyKbx9rMwDAYDVR0TBAUw
+AwEB/zAJBgcqhkjOPQQBAzgAMDUCGFVX2d9M0NbxeusbaUjMcWwviXPQpNEHvwIZ
+AOPKXDtDGAwkb42kO7ms7rzN7R4LN788MA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICcDCCAdkCCQCg3U8Mc7XCXzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwNDVaFw0xMDAxMTQyMTMwNDVaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjdDE5M3Ixc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wSDAQBgcqhkjOPQIBBgUrgQQAGAM0AAQA
+vZA91W5lNk3Ru3pALBexkJpZ9K0WjZrLASMO9wZGvbukocKAPYTfDYdcSwdwqHuU
+RzANBgkqhkiG9w0BAQUFAAOBgQB/Gcwd09VVyOWJq9cIA5tga/ZBYwgXv+T3eAUU
+Ert7tGQgD/eysWYvTB+Vu9zUvGyWWtUfzoFMP1R2MeuxnDMiXyhhQ+7UKl3P7AQy
+P060oo1DP7RWK8D8oz8IFeP6ttaiRgetE3hnHUwbxnO30bdiN61EdWBT0Dp+0LuP
+Yg6Ndw==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIC8TCCAdkCCQCg3U8Mc7XCYDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC
+VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK
+DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT
+ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm
+LmNvbTAeFw0wNTEyMDYyMTMwNDZaFw0xMDAxMTQyMTMwNDZaMIGwMQswCQYDVQQG
+EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV
+BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0
+IFNlcnZlciAoc2VjdDE5M3Ixc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl
+di5leHBlcmltZW50YWxzdHVmZi5jb20wSDAQBgcqhkjOPQIBBgUrgQQAGAM0AAQA
+qMKb0SJmrWoWnZxXZh5jhRZnF9vRyljvARAR7/z2+gU/qkOTcxuE9RYxgqHtDVRE
+fjANBgkqhkiG9w0BAQUFAAOCAQEAScWVdynbg9B9VCtF4Ct8sXMRRYuwCLUt5Yp/
+rtLXmhUuZR0qCvuCMoDo2+HdQNcwEZr7teH2jZ9gYcfq1GWouwA36rafR8e4GQ4P
+egySyKLYkZ7sKhrKacN4k1XItlxHsWWtVRs79smAVgpVIu5IA2Pm5BZEuIUPCIAF
+3gSHM6Y0UHWGazxaToUEiPh7jVh5eUA8wAdhKFhiLtrIlZo9u2BCXmPiwBj71fSY
+iyEArag7u/n5pfoBYzwiiAFLddQiuwaxe8jPt0+RJI5Dhs0IzX6L/Xzu06qkKPjF
+9AX5PkBWj5GAjPCU/8t3O2wrMBvCw7G7epMXNXjTqJf6no5sig==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICFTCCAdQCCQCg3U8Mc7XCWTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA0MloXDTEwMDExNDIxMzA0MlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTkzcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEANui7TQR
+XIBnrqvvP9zgztIKdqeIwISmzQBKKwC3FMR/Ma/MJCuBuXANUV3Xbi/rwwswCQYH
+KoZIzj0EAQMwADAtAhUAhNmGbEAG/eht1YE9KUUf7v/k9ywCFDO9YqZLm7mvDe2Q
+Vp2EWIS8AFw0
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICLjCCAdQCCQCg3U8Mc7XCWjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA0MloXDTEwMDExNDIxMzA0MlowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTkzcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEAE/bjnPS
+yBqy8ageF1ZpfzHTAoEzcV5UywAlrF6AsP5UDVbbxWzEYENodBbIAyu5gmswCQYH
+KoZIzj0EAQNJADBGAiEAyOvzEV5o/+YRAkIQY/+Le1n3wzUvr9QMwVlOg/yZMvsC
+IQCFFD9AOt0tQTxWsDgGzCoVbz9MnnWzptIsGx4HXUm4YA==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICTTCCAdQCCQCg3U8Mc7XCWzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA0M1oXDTEwMDExNDIxMzA0M1owgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTkzcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEASNBKWzJ
++B+4G2UTsTqBM0cjsdS6C5cmHwC1oYKyagdGeWkSzI3wsNJri29OBB3wg1YwCQYH
+KoZIzj0EAQNoADBlAjEAvCF43f3XJZHJ43dChTwVcMxrvrkEg33BCdkpab3ZzQGc
+4z8YLxgXwNgQtoWakxepAjAT9zi78gOcvIOLt+cONUWX1Q3dwsqz7ELfB51+H9EC
+njcMe07enAwPTGZhifhBqfQ=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICFjCCAdQCCQCg3U8Mc7XCXTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA0NFoXDTEwMDExNDIxMzA0NFowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTkzcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEAInznYj4
+XfwSdi2XrqLF6uQ1/sJoFEveBQCqz+XoSsXKgRmMCO2iMHVGctNbcz8RptMwCQYH
+KoZIzj0EAQMxADAuAhUBfBAH/3ROR9VsZKAhW0fR6i/ud9gCFQCdjuAk1NhSTtAD
+AcZ+gSnBmESa1g==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICHDCCAdQCCQCg3U8Mc7XCXjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz
+ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X
+DTA1MTIwNjIxMzA0NVoXDTEwMDExNDIxMzA0NVowgbIxCzAJBgNVBAYTAlVTMQsw
+CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu
+IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy
+IChzZWN0MTkzcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw
+ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEAGJbRZVS
+qbKx8P+C60EaCmnuolgSDf7fqwE0oMSo8dtSmq1vSmqXjbQHWaze3zev50swCQYH
+KoZIzj0EAQM3ADA0AhhsmuN8sbGYzItLtNqk/kXRvBSk+gOeKaECGBAT5pnVqKan
+q4wuATzeJEv5LeT9H3GU1A==
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICJDCCAdwCCQCzW7zGCDpEhzAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL
+MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1
+biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl
+ciAoc2VjdDE5M3Ixc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu
+dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzA0N1oXDTEwMDExNDIxMzA0N1owgasx
+CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll
+dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV
+BAsMIlRlc3QgU2VydmVyIChzZWN0MTkzcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM
+GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wSDAQBgcqhkjOPQIBBgUrgQQAGAM0
+AAQAjhf42KmZLPPrcBCdsOJpU9uDCZDh7CD7Af3pMkj8friWXyIZBoKwChbkPOnT
+wq4XMTAJBgcqhkjOPQQBAzcAMDQCGD0nycV04j9b/1/l1cnRJWtuaHUK2LPmdAIY
+fDH6KdS9OQSXMHdiCLnK5mWYTDG0g0em
+-----END CERTIFICATE-----
Binary file jdk/test/sun/security/ec/keystore has changed
Binary file jdk/test/sun/security/ec/truststore has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/krb5/IPv6.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,127 @@
+/*
+ * 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 6877357
+ * @summary IPv6 address does not work
+ */
+
+import com.sun.security.auth.module.Krb5LoginModule;
+import java.io.*;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.security.auth.Subject;
+
+public class IPv6 {
+
+    public static void main(String[] args) throws Exception {
+
+        String[][] kdcs = {
+                {"simple.host", null},  // These are legal settings
+                {"simple.host", ""},
+                {"simple.host", "8080"},
+                {"0.0.0.1", null},
+                {"0.0.0.1", ""},
+                {"0.0.0.1", "8080"},
+                {"1::1", null},
+                {"[1::1]", null},
+                {"[1::1]", ""},
+                {"[1::1]", "8080"},
+                {"[1::1", null},        // Two illegal settings
+                {"[1::1]abc", null},
+        };
+        // Prepares a krb5.conf with every kind of KDC settings
+        PrintStream out = new PrintStream(new FileOutputStream("ipv6.conf"));
+        out.println("[libdefaults]");
+        out.println("default_realm = V6");
+        out.println("[realms]");
+        out.println("V6 = {");
+        for (String[] hp: kdcs) {
+            if (hp[1] != null) out.println("    kdc = "+hp[0]+":"+hp[1]);
+            else out.println("    kdc = " + hp[0]);
+        }
+        out.println("}");
+        out.close();
+
+        System.setProperty("sun.security.krb5.debug", "true");
+        System.setProperty("java.security.krb5.conf", "ipv6.conf");
+
+        ByteArrayOutputStream bo = new ByteArrayOutputStream();
+        PrintStream po = new PrintStream(bo);
+        PrintStream oldout = System.out;
+        System.setOut(po);
+
+        try {
+            Subject subject = new Subject();
+            Krb5LoginModule krb5 = new Krb5LoginModule();
+            Map<String, String> map = new HashMap<String, String>();
+            Map<String, Object> shared = new HashMap<String, Object>();
+
+            map.put("debug", "true");
+            map.put("doNotPrompt", "true");
+            map.put("useTicketCache", "false");
+            map.put("useFirstPass", "true");
+            shared.put("javax.security.auth.login.name", "any");
+            shared.put("javax.security.auth.login.password", "any".toCharArray());
+            krb5.initialize(subject, null, shared, map);
+            krb5.login();
+        } catch (Exception e) {
+            // Ignore
+        }
+
+        po.flush();
+
+        System.setOut(oldout);
+        String[] lines = new String(bo.toByteArray()).split("\n");
+        int cc = 0;
+        Pattern r = Pattern.compile(".*KrbKdcReq send: kdc=(.*) UDP:(\\d+),.*");
+        for (String line: lines) {
+            Matcher m = r.matcher(line.subSequence(0, line.length()));
+            if (m.matches()) {
+                System.out.println("------------------");
+                System.out.println(line);
+                String h = m.group(1), p = m.group(2);
+                String eh = kdcs[cc][0], ep = kdcs[cc][1];
+                if (eh.charAt(0) == '[') {
+                    eh = eh.substring(1, eh.length()-1);
+                }
+                System.out.println("Expected: " + eh + " : " + ep);
+                System.out.println("Actual: " + h + " : " + p);
+                if (!eh.equals(h) ||
+                        (ep == null || ep.length() == 0) && !p.equals("88") ||
+                        (ep != null && ep.length() > 0) && !p.equals(ep)) {
+                    throw new Exception("Mismatch");
+                }
+                cc++;
+            }
+        }
+        if (cc != kdcs.length - 2) {    // 2 illegal settings at the end
+            throw new Exception("Not traversed");
+        }
+    }
+}
+
+
--- a/jdk/test/sun/security/pkcs11/ec/ReadCertificates.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/test/sun/security/pkcs11/ec/ReadCertificates.java	Wed Jul 05 17:01:09 2017 +0200
@@ -100,7 +100,15 @@
             X509Certificate issuer = certs.get(cert.getIssuerX500Principal());
             System.out.println("Verifying " + cert.getSubjectX500Principal() + "...");
             PublicKey key = issuer.getPublicKey();
-            cert.verify(key, p.getName());
+            // First try the provider under test (if it does not support the
+            // necessary algorithm then try any registered provider).
+            try {
+                cert.verify(key, p.getName());
+            } catch (NoSuchAlgorithmException e) {
+                System.out.println("Warning: " + e.getMessage() +
+                ". Trying another provider...");
+                cert.verify(key);
+            }
         }
 
         // try some random invalid signatures to make sure we get the correct
--- a/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Mon Sep 28 19:38:55 2009 -0700
+++ b/jdk/test/sun/security/pkcs11/sslecc/CipherTest.java	Wed Jul 05 17:01:09 2017 +0200
@@ -298,7 +298,7 @@
             throws Exception {
         long time = System.currentTimeMillis();
         String relPath;
-        if ((args.length > 0) && args[0].equals("sh")) {
+        if ((args != null) && (args.length > 0) && args[0].equals("sh")) {
             relPath = pathToStoresSH;
         } else {
             relPath = pathToStores;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/util/logging/PlatformLoggerTest.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,111 @@
+/*
+ * 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     6882376
+ * @summary Test if java.util.logging.Logger is created before and after
+ *          logging is enabled.  Also validate some basic PlatformLogger
+ *          operations.
+ *
+ * @build PlatformLoggerTest
+ * @run main PlatformLoggerTest
+ */
+
+import java.util.logging.*;
+import sun.util.logging.PlatformLogger;
+
+public class PlatformLoggerTest {
+    private static final int defaultEffectiveLevel = 0;
+    public static void main(String[] args) throws Exception {
+        final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo";
+        final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar";
+        final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo";
+        final String BAR_LOGGER = "test.logger.bar";
+        PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER);
+
+        // Create a platform logger using the default
+        PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER);
+        checkPlatformLogger(foo, FOO_PLATFORM_LOGGER);
+
+        // create a java.util.logging.Logger
+        // now java.util.logging.Logger should be created for each platform logger
+        Logger logger = Logger.getLogger(BAR_LOGGER);
+        logger.setLevel(Level.WARNING);
+
+        PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER);
+        checkPlatformLogger(bar, BAR_PLATFORM_LOGGER);
+
+        checkLogger(FOO_PLATFORM_LOGGER, Level.FINER);
+        checkLogger(BAR_PLATFORM_LOGGER, Level.FINER);
+
+        checkLogger(GOO_PLATFORM_LOGGER, null);
+        checkLogger(BAR_LOGGER, Level.WARNING);
+
+        foo.setLevel(PlatformLogger.SEVERE);
+        checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE);
+    }
+
+    private static void checkPlatformLogger(PlatformLogger logger, String name) {
+        if (!logger.getName().equals(name)) {
+            throw new RuntimeException("Invalid logger's name " +
+                logger.getName() + " but expected " + name);
+        }
+
+        if (logger.getLevel() != defaultEffectiveLevel) {
+            throw new RuntimeException("Invalid default level for logger " +
+                logger.getName());
+        }
+
+        if (logger.isLoggable(PlatformLogger.FINE) != false) {
+            throw new RuntimeException("isLoggerable(FINE) returns true for logger " +
+                logger.getName() + " but expected false");
+        }
+
+        logger.setLevel(PlatformLogger.FINER);
+        if (logger.getLevel() != Level.FINER.intValue()) {
+            throw new RuntimeException("Invalid level for logger " +
+                logger.getName() + " " + logger.getLevel());
+        }
+
+        if (logger.isLoggable(PlatformLogger.FINE) != true) {
+            throw new RuntimeException("isLoggerable(FINE) returns false for logger " +
+                logger.getName() + " but expected true");
+        }
+
+        logger.info("OK: Testing log message");
+    }
+
+    private static void checkLogger(String name, Level level) {
+        Logger logger = LogManager.getLogManager().getLogger(name);
+        if (logger == null) {
+            throw new RuntimeException("Logger " + name +
+                " does not exist");
+        }
+
+        if (logger.getLevel() != level) {
+            throw new RuntimeException("Invalid level for logger " +
+                logger.getName() + " " + logger.getLevel());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/6842838/CreateBadJar.java	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,168 @@
+/*
+ * 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.
+ */
+
+/*
+ * Borrowing significantly from Martin Buchholz's CorruptedZipFiles.java
+ *
+ * Needed a way of testing the checks for corrupt zip/jar entry in
+ * inflate_file from file j2se/src/share/bin/parse_manifest.c
+ * and running them with the 64-bit launcher. e.g.
+ * sparcv9/bin/java -jar badjar.jar
+ *
+ * Run from a script driver Test6842838.sh as we want to specifically run
+ * bin/sparcv9/java, the 64-bit launcher.
+ *
+ * So this program will create a zip file and damage it in the way
+ * required to tickle this bug.
+ *
+ * It will cause a buffer overrun: but that will not always crash.
+ * Use libumem preloaded by the script driver in order to
+ * abort quickly when the overrun happens.  That makes the test
+ * Solaris-specific.
+ */
+
+import java.util.*;
+import java.util.zip.*;
+import java.io.*;
+import static java.lang.System.*;
+import static java.util.zip.ZipFile.*;
+
+public class CreateBadJar {
+
+public static void main(String [] arguments) {
+
+        if (arguments.length != 2) {
+            throw new RuntimeException("Arguments: jarfilename entryname");
+        }
+        String outFile = arguments[0];
+        String entryName = arguments[1];
+
+        try {
+        // If the named file doesn't exist, create it.
+        // If it does, we are expecting it to contain the named entry, for
+        // alteration.
+        if (!new File(outFile).exists()) {
+          System.out.println("Creating file " + outFile);
+
+          // Create the requested zip/jar file.
+          ZipOutputStream zos = null;
+          zos = new ZipOutputStream(
+            new FileOutputStream(outFile));
+
+          ZipEntry e = new ZipEntry(entryName);
+          zos.putNextEntry(e);
+          for (int j=0; j<50000; j++) {
+            zos.write((int)'a');
+          }
+          zos.closeEntry();
+          zos.close();
+          zos = null;
+        }
+
+        // Read it.
+        int len = (int)(new File(outFile).length());
+        byte[] good = new byte[len];
+        FileInputStream fis = new FileInputStream(outFile);
+        fis.read(good);
+        fis.close();
+        fis = null;
+
+        int endpos = len - ENDHDR;
+        int cenpos = u16(good, endpos+ENDOFF);
+        if (u32(good, cenpos) != CENSIG) throw new RuntimeException("Where's CENSIG?");
+
+        byte[] bad;
+        bad = good.clone();
+
+        // Corrupt it...
+        int pos = findInCEN(bad, cenpos, entryName);
+
+        // What bad stuff are we doing to it?
+        // Store a 32-bit -1 in uncomp size.
+        bad[pos+0x18]=(byte)0xff;
+        bad[pos+0x19]=(byte)0xff;
+        bad[pos+0x1a]=(byte)0xff;
+        bad[pos+0x1b]=(byte)0xff;
+
+        // Bad work complete, delete the original.
+        new File(outFile).delete();
+
+        // Write it.
+        FileOutputStream fos = new FileOutputStream(outFile);
+        fos.write(bad);
+        fos.close();
+        fos = null;
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+}
+
+        /*
+         * Scan Central Directory File Headers looking for the named entry.
+         */
+
+    static int findInCEN(byte[] bytes, int cenpos, String entryName) {
+        int pos = cenpos;
+        int nextPos = 0;
+        String filename = null;
+        do {
+            if (nextPos != 0) {
+                pos = nextPos;
+            }
+            System.out.println("entry at pos = " + pos);
+            if (u32(bytes, pos) != CENSIG) throw new RuntimeException ("entry not found in CEN or premature end...");
+
+            int csize = u32(bytes, pos+0x14);          // +0x14 1 dword csize
+            int uncompsize = u32(bytes, pos+0x18);     // +0x18 1 dword uncomp size
+            int filenameLength = u16(bytes, pos+0x1c); // +0x1c 1 word length of filename
+            int extraLength = u16(bytes, pos+0x1e);    // +0x1e 1 world length of extra field
+            int commentLength = u16(bytes, pos+0x20);  // +0x20 1 world length of file comment
+            filename = new String(bytes, pos+0x2e, filenameLength); // +0x2e chars of filename
+            int offset = u32(bytes, pos+0x2a);         // +0x2a chars of filename
+
+            System.out.println("filename = " + filename + "\ncsize = " + csize +
+                               " uncomp.size = " + uncompsize +" file offset = " + offset);
+            nextPos =  pos + 0x2e + filenameLength + extraLength + commentLength;
+
+        } while (!filename.equals(entryName));
+
+        System.out.println("entry found at pos = " + pos);
+        return pos;
+    }
+
+    static int u8(byte[] data, int offset) {
+        return data[offset]&0xff;
+    }
+
+    static int u16(byte[] data, int offset) {
+        return u8(data,offset) + (u8(data,offset+1)<<8);
+    }
+
+    static int u32(byte[] data, int offset) {
+        return u16(data,offset) + (u16(data,offset+2)<<16);
+    }
+
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/tools/launcher/6842838/Test6842838.sh	Wed Jul 05 17:01:09 2017 +0200
@@ -0,0 +1,76 @@
+#
+# 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 Test6842838.sh
+# @bug 6842838
+# @summary Test 6842838 64-bit launcher failure due to corrupt jar
+# @compile CreateBadJar.java
+# @run shell Test6842838.sh
+
+set -x
+
+if [ "${TESTJAVA}" = "" ]; then
+  PARENT=`dirname \`which java\``
+  TESTJAVA=`dirname ${PARENT}`
+  printf "TESTJAVA not set.  Test cannot execute.  Failed.\n"
+fi
+
+if [ "${TESTCLASSES}" = "" ]; then
+  printf "TESTCLASSES not set.  Test cannot execute.  Failed.\n"
+  exit 1
+fi
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+  SunOS )
+    NULL=/dev/null
+    PS=":"
+    FS="/"
+    JAVA_EXE=${TESTJAVA}${FS}bin${FS}sparcv9${FS}java
+    ;;
+  * )
+    printf "Only testing on sparcv9 (use libumem to reliably catch buffer overrun)\n"
+    exit 0;
+    ;;
+esac
+
+if [ ! -x ${JAVA_EXE} ]; then
+    printf "Warning: sparcv9 components not installed - skipping test.\n"
+    exit 0
+fi
+
+LIBUMEM=/lib/64/libumem.so
+if [ ! -x ${LIBUMEM} ]; then
+    printf "Warning: libumem not installed - skipping test.\n"
+    exit 0
+fi
+
+BADFILE=newbadjar.jar
+${JAVA_EXE} -version
+${JAVA_EXE} -cp ${TESTCLASSES} CreateBadJar ${BADFILE} "META-INF/MANIFEST.MF"
+LD_PRELOAD=${LIBUMEM} ${JAVA_EXE} -jar ${BADFILE} > test.out 2>&1
+
+grep "Invalid or corrupt jarfile" test.out
+exit $?
--- a/make/Defs-internal.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/Defs-internal.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -28,6 +28,23 @@
 # not contain rules.
 #
 
+# Indicate that we are visiting a separate repo or component 
+define MakeStart
+$(PRINTF) "\n\n%s\n%s\n##### %-60.60s #####\n%s\n" \
+"########################################################################" \
+"########################################################################" \
+"Entering $1 for target $2" \
+"########################################################################"
+endef
+
+define MakeFinish
+$(PRINTF) "%s\n##### %-60.60s #####\n%s\n%s\n\n" \
+"########################################################################" \
+"Leaving $1 for target $2" \
+"########################################################################" \
+"########################################################################"
+endef
+
 ifdef OPENJDK
   ifneq ($(OPENJDK),true)
     x:=$(error "OPENJDK (if defined) can only be set to true")
--- a/make/corba-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/corba-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2001-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
@@ -40,13 +40,17 @@
 corba: corba-build
 corba-build:
 	$(MKDIR) -p $(CORBA_OUTPUTDIR)
+	@$(call MakeStart, corba, all)
 	($(CD) $(CORBA_TOPDIR)/make && \
 	 $(MAKE) $(CORBA_BUILD_ARGUMENTS) all)
+	@$(call MakeFinish, corba, all)
 
 corba-clobber::
 	$(MKDIR) -p $(CORBA_OUTPUTDIR)
+	@$(call MakeStart, corba, clobber)
 	($(CD) $(CORBA_TOPDIR)/make &&  \
 	 $(MAKE) $(CORBA_BUILD_ARGUMENTS) clobber)
+	@$(call MakeFinish, corba, clobber)
 
 .PHONY: corba corba-build corba-clobber 
 
--- a/make/deploy-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/deploy-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -121,14 +121,18 @@
 
 deploy-build:
 ifeq ($(BUILD_DEPLOY), true)
+	@$(call MakeStart, deploy, $(DEPLOY_BUILD_TARGETS))
 	($(CD) $(DEPLOY_TOPDIR)/make && \
-	$(MAKE) $(DEPLOY_BUILD_TARGETS) $(DEPLOY_BUILD_ARGUMENTS))
+	  $(MAKE) $(DEPLOY_BUILD_TARGETS) $(DEPLOY_BUILD_ARGUMENTS))
+	@$(call MakeFinish, deploy, $(DEPLOY_BUILD_TARGETS))
 endif
 
 deploy-clobber::
 ifeq ($(BUILD_DEPLOY), true)
+	@$(call MakeStart, deploy, clobber)
 	($(CD) $(DEPLOY_TOPDIR)/make && \
-	$(MAKE) clobber $(DEPLOY_BUILD_ARGUMENTS))
+	  $(MAKE) clobber $(DEPLOY_BUILD_ARGUMENTS))
+	@$(call MakeFinish, deploy, clobber)
 endif 
 
 deploy-sanity::
--- a/make/hotspot-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/hotspot-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2001-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
@@ -88,8 +88,10 @@
 hotspot-build::
 	$(MKDIR) -p $(HOTSPOT_OUTPUTDIR)
 	$(MKDIR) -p $(HOTSPOT_EXPORT_PATH)
+	@$(call MakeStart, hotspot, $(HOTSPOT_TARGET))
 	$(CD) $(HOTSPOT_TOPDIR)/make && \
 	    $(MAKE) $(HOTSPOT_BUILD_ARGUMENTS) $(HOTSPOT_TARGET)
+	@$(call MakeFinish, hotspot, $(HOTSPOT_TARGET))
 
 #####################
 # .PHONY
--- a/make/install-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/install-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2002-2007 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
@@ -57,38 +57,48 @@
 
 install-build:
 ifeq ($(BUILD_INSTALL), true)
+	@$(call MakeStart, install, $(INSTALL_BUILD_TARGETS))
 	($(CD) $(INSTALL_TOPDIR)/make && \
 	  $(MAKE) $(INSTALL_BUILD_TARGETS) $(INSTALL_BUILD_ARGUMENTS))
+	@$(call MakeFinish, install, $(INSTALL_BUILD_TARGETS))
 endif
 
 update-patcher:
 ifeq ($(BUILD_INSTALL), true)
 	if [ -r $(INSTALL_TOPDIR)/make/update/Makefile ]; then \
+	  $(call MakeStart, install update, all); \
 	  ( $(CD) $(INSTALL_TOPDIR)/make/update && \
 	    $(MAKE) all $(INSTALL_BUILD_ARGUMENTS) ); \
+	  $(call MakeFinish, install, all); \
 	fi
 endif
 
 update-patchgen:
 ifeq ($(BUILD_INSTALL), true)
 	if [ -r $(INSTALL_TOPDIR)/make/update/Makefile ]; then \
+	  $(call MakeStart, install update, patchgen); \
 	  ( $(CD) $(INSTALL_TOPDIR)/make/update && \
 	    $(MAKE) patchgen $(INSTALL_BUILD_ARGUMENTS) ); \
+	  $(call MakeFinish, install, patchgen); \
 	fi
 endif
 
 installer:
 ifeq ($(BUILD_INSTALL), true)
 	if [ -r $(INSTALL_TOPDIR)/make/installer/Makefile ]; then \
+	  $(call MakeStart, install installer, all); \
 	  ( $(CD) $(INSTALL_TOPDIR)/make/installer && \
 	    $(MAKE) all $(INSTALL_BUILD_ARGUMENTS) ); \
+	  $(call MakeFinish, install, all); \
 	fi
 endif
 
 install-clobber:
 ifeq ($(BUILD_INSTALL), true)
+	@$(call MakeStart, install, clobber)
 	($(CD) $(INSTALL_TOPDIR)/make && \
 	  $(MAKE) clobber $(INSTALL_BUILD_ARGUMENTS))
+	@$(call MakeFinish, install, clobber)
 endif
 
 install-sanity:: 
--- a/make/jaxp-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/jaxp-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2001-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
@@ -40,13 +40,17 @@
 jaxp: jaxp-build
 jaxp-build:
 	$(MKDIR) -p $(JAXP_OUTPUTDIR)
+	@$(call MakeStart, jaxp, all)
 	($(CD) $(JAXP_TOPDIR)/make && \
 	 $(MAKE) $(JAXP_BUILD_ARGUMENTS) all)
+	@$(call MakeFinish, jaxp, all)
 
 jaxp-clobber::
 	$(MKDIR) -p $(JAXP_OUTPUTDIR)
+	@$(call MakeStart, jaxp, clobber)
 	($(CD) $(JAXP_TOPDIR)/make &&  \
 	 $(MAKE) $(JAXP_BUILD_ARGUMENTS) clobber)
+	@$(call MakeFinish, jaxp, clobber)
 
 .PHONY: jaxp jaxp-build jaxp-clobber
 
--- a/make/jaxws-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/jaxws-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2001-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
@@ -40,13 +40,17 @@
 jaxws: jaxws-build
 jaxws-build:
 	$(MKDIR) -p $(JAXWS_OUTPUTDIR)
+	@$(call MakeStart, jaxws, all)
 	($(CD) $(JAXWS_TOPDIR)/make && \
 	 $(MAKE) $(JAXWS_BUILD_ARGUMENTS) all)
+	@$(call MakeFinish, jaxws, all)
 
 jaxws-clobber::
 	$(MKDIR) -p $(JAXWS_OUTPUTDIR)
+	@$(call MakeStart, jaxws, clobber)
 	($(CD) $(JAXWS_TOPDIR)/make &&  \
 	 $(MAKE) $(JAXWS_BUILD_ARGUMENTS) clobber)
+	@$(call MakeFinish, jaxws, clobber)
 
 .PHONY: jaxws jaxws-build jaxws-clobber
 
--- a/make/jdk-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/jdk-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -98,12 +98,16 @@
 
 jdk: jdk-build
 jdk-build:
+	@$(call MakeStart, jdk, $(JDK_BUILD_TARGETS))
 	( $(CD) $(JDK_TOPDIR)/make && \
 	  $(MAKE) $(JDK_BUILD_TARGETS) $(JDK_BUILD_ARGUMENTS) ; )
+	@$(call MakeFinish, jdk, $(JDK_BUILD_TARGETS))
 
 jdk-clobber::
+	@$(call MakeStart, jdk, $(JDK_CLOBBER_TARGETS))
 	( $(CD) $(JDK_TOPDIR)/make && \
 	  $(MAKE) $(JDK_CLOBBER_TARGETS) $(JDK_BUILD_ARGUMENTS) ; )
+	@$(call MakeFinish, jdk, $(JDK_CLOBBER_TARGETS))
 
 jdk-sanity::
 	( $(CD) $(JDK_TOPDIR)/make && \
@@ -111,13 +115,17 @@
 
 compare-images: compare-image
 compare-image:
+	@$(call MakeStart, jdk, compare-image)
 	( $(CD) $(JDK_TOPDIR)/make && \
 	  $(MAKE) ALT_OUTPUTDIR=$(ABS_OUTPUTDIR) compare-image )
+	@$(call MakeFinish, jdk, compare-image)
 
 compare-images-clobber: compare-image-clobber
 compare-image-clobber:
+	@$(call MakeStart, jdk, compare-image-clobber)
 	( $(CD) $(JDK_TOPDIR)/make && \
 	  $(MAKE) ALT_OUTPUTDIR=$(ABS_OUTPUTDIR) compare-image-clobber )
+	@$(call MakeFinish, jdk, compare-image-clobber)
 
 .PHONY: jdk jdk-build jdk-clobber jdk-sanity 
 
--- a/make/langtools-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/langtools-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2001-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2001-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,13 +35,17 @@
 langtools: langtools-build
 langtools-build:
 	$(MKDIR) -p $(LANGTOOLS_OUTPUTDIR)
+	@$(call MakeStart, langtools, all)
 	($(CD) $(LANGTOOLS_TOPDIR)/make && \
-	 $(MAKE) $(LANGTOOLS_BUILD_ARGUMENTS) all)
+	  $(MAKE) $(LANGTOOLS_BUILD_ARGUMENTS) all)
+	@$(call MakeFinish, langtools, all)
 
 langtools-clobber::
 	$(MKDIR) -p $(LANGTOOLS_OUTPUTDIR)
+	@$(call MakeStart, langtools, clobber)
 	($(CD) $(LANGTOOLS_TOPDIR)/make &&  \
-	 $(MAKE) $(LANGTOOLS_BUILD_ARGUMENTS) clobber)
+	  $(MAKE) $(LANGTOOLS_BUILD_ARGUMENTS) clobber)
+	@$(call MakeFinish, langtools, clobber)
 
 .PHONY: langtools langtools-build langtools-clobber
 
--- a/make/sponsors-rules.gmk	Mon Sep 28 19:38:55 2009 -0700
+++ b/make/sponsors-rules.gmk	Wed Jul 05 17:01:09 2017 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright 2006-2007 Sun Microsystems, Inc.  All Rights Reserved.
+# Copyright 2006-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
@@ -59,8 +59,10 @@
 sponsors-build:
 ifeq ($(ARCH_DATA_MODEL), 32)
   ifeq ($(BUILD_SPONSORS), true)
+	@$(call MakeStart, sponsors, $(SPONSORS_BUILD_TARGETS))
 	($(CD) $(SPONSORS_TOPDIR)/make && \
-	 $(MAKE) $(SPONSORS_BUILD_TARGETS) $(SPONSORS_BUILD_ARGUMENTS))
+	  $(MAKE) $(SPONSORS_BUILD_TARGETS) $(SPONSORS_BUILD_ARGUMENTS))
+	@$(call MakeFinish, sponsors, $(SPONSORS_BUILD_TARGETS))
   endif
 endif