From 99c5ea5368b2a58c6e93d4c76fccf5707c9469f8 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 29 Apr 2009 20:03:09 +0400 Subject: [PATCH 01/70] 6660539: Introspector shares cache of mutable BeanInfo between AppContexts Reviewed-by: peterz --- .../classes/java/beans/Introspector.java | 29 ++++++-- .../java/beans/Introspector/Test6660539.java | 68 +++++++++++++++++++ 2 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 jdk/test/java/beans/Introspector/Test6660539.java diff --git a/jdk/src/share/classes/java/beans/Introspector.java b/jdk/src/share/classes/java/beans/Introspector.java index 6a50cbe7f7d..2a49db1794c 100644 --- a/jdk/src/share/classes/java/beans/Introspector.java +++ b/jdk/src/share/classes/java/beans/Introspector.java @@ -1,5 +1,5 @@ /* - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ import java.util.EventListener; import java.util.List; import java.util.WeakHashMap; import java.util.TreeMap; +import sun.awt.AppContext; import sun.reflect.misc.ReflectUtil; /** @@ -111,8 +112,8 @@ public class Introspector { // Static Caches to speed up introspection. private static Map declaredMethodCache = Collections.synchronizedMap(new WeakHashMap()); - private static Map beanInfoCache = - Collections.synchronizedMap(new WeakHashMap()); + + private static final Object BEANINFO_CACHE = new Object(); private Class beanClass; private BeanInfo explicitBeanInfo; @@ -175,10 +176,18 @@ public class Introspector { if (!ReflectUtil.isPackageAccessible(beanClass)) { return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); } - BeanInfo bi = (BeanInfo)beanInfoCache.get(beanClass); + Map, BeanInfo> map; + synchronized (BEANINFO_CACHE) { + map = (Map, BeanInfo>) AppContext.getAppContext().get(BEANINFO_CACHE); + if (map == null) { + map = Collections.synchronizedMap(new WeakHashMap, BeanInfo>()); + AppContext.getAppContext().put(BEANINFO_CACHE, map); + } + } + BeanInfo bi = map.get(beanClass); if (bi == null) { bi = (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo(); - beanInfoCache.put(beanClass, bi); + map.put(beanClass, bi); } return bi; } @@ -351,7 +360,10 @@ public class Introspector { */ public static void flushCaches() { - beanInfoCache.clear(); + Map map = (Map) AppContext.getAppContext().get(BEANINFO_CACHE); + if (map != null) { + map.clear(); + } declaredMethodCache.clear(); } @@ -374,7 +386,10 @@ public class Introspector { if (clz == null) { throw new NullPointerException(); } - beanInfoCache.remove(clz); + Map map = (Map) AppContext.getAppContext().get(BEANINFO_CACHE); + if (map != null) { + map.remove(clz); + } declaredMethodCache.remove(clz); } diff --git a/jdk/test/java/beans/Introspector/Test6660539.java b/jdk/test/java/beans/Introspector/Test6660539.java new file mode 100644 index 00000000000..b0678a5a04b --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test6660539.java @@ -0,0 +1,68 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6660539 + * @summary Tests changeable BeanInfo cache in different application contexts + * @author Sergey Malenkov + */ + +import sun.awt.SunToolkit; + +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +public class Test6660539 implements Runnable { + private static final String NAME = "$$$"; + + public static void main(String[] args) throws Exception { + for (PropertyDescriptor pd : getPropertyDescriptors()) { + pd.setDisplayName(NAME); + } + ThreadGroup group = new ThreadGroup(NAME); + Thread thread = new Thread(group, new Test6660539()); + thread.start(); + thread.join(); + } + + public void run() { + SunToolkit.createNewAppContext(); + for (PropertyDescriptor pd : getPropertyDescriptors()) { + if (pd.getDisplayName().equals(NAME)) + throw new Error("shared BeanInfo cache"); + } + } + + private static PropertyDescriptor[] getPropertyDescriptors() { + try { + BeanInfo info = Introspector.getBeanInfo(Test6660539.class); + return info.getPropertyDescriptors(); + } + catch (IntrospectionException exception) { + throw new Error("unexpected", exception); + } + } +} From de6e2fb6e267b377c94c9179cd474d1689b4a0e6 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Wed, 29 Apr 2009 20:55:13 +0400 Subject: [PATCH 02/70] 6777487: Encoder allows reading private variables with certain names Reviewed-by: peterz --- .../share/classes/java/beans/MetaData.java | 83 ++++++++++--------- .../beans/XMLEncoder/6777487/TestBox.java | 52 ++++++++++++ .../6777487/TestCheckedCollection.java | 48 +++++++++++ .../XMLEncoder/6777487/TestCheckedList.java | 48 +++++++++++ .../XMLEncoder/6777487/TestCheckedMap.java | 49 +++++++++++ .../6777487/TestCheckedRandomAccessList.java | 48 +++++++++++ .../XMLEncoder/6777487/TestCheckedSet.java | 48 +++++++++++ .../6777487/TestCheckedSortedMap.java | 49 +++++++++++ .../6777487/TestCheckedSortedSet.java | 48 +++++++++++ .../beans/XMLEncoder/6777487/TestEncoder.java | 60 ++++++++++++++ .../beans/XMLEncoder/6777487/TestEnumMap.java | 47 +++++++++++ .../beans/XMLEncoder/6777487/TestEnumSet.java | 47 +++++++++++ 12 files changed, 589 insertions(+), 38 deletions(-) create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestBox.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedCollection.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedList.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedMap.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedRandomAccessList.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSet.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedMap.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedSet.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestEncoder.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestEnumMap.java create mode 100644 jdk/test/java/beans/XMLEncoder/6777487/TestEnumSet.java diff --git a/jdk/src/share/classes/java/beans/MetaData.java b/jdk/src/share/classes/java/beans/MetaData.java index defd196457e..75c3945106d 100644 --- a/jdk/src/share/classes/java/beans/MetaData.java +++ b/jdk/src/share/classes/java/beans/MetaData.java @@ -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 @@ -333,31 +333,6 @@ abstract class java_util_Collections extends PersistenceDelegate { return (oldC.size() == newC.size()) && oldC.containsAll(newC); } - static Object getPrivateField(final Object instance, final String name) { - return AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - Class type = instance.getClass(); - while ( true ) { - try { - Field field = type.getDeclaredField(name); - field.setAccessible(true); - return field.get( instance ); - } - catch (NoSuchFieldException exception) { - type = type.getSuperclass(); - if (type == null) { - throw new IllegalStateException("Could not find field " + name, exception); - } - } - catch (Exception exception) { - throw new IllegalStateException("Could not get value " + type.getName() + '.' + name, exception); - } - } - } - } ); - } - static final class EmptyList_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { return new Expression(oldInstance, Collections.class, "emptyList", null); @@ -498,7 +473,7 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedCollection_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object type = getPrivateField(oldInstance, "type"); + Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type"); List list = new ArrayList((Collection) oldInstance); return new Expression(oldInstance, Collections.class, "checkedCollection", new Object[]{list, type}); } @@ -506,7 +481,7 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedList_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object type = getPrivateField(oldInstance, "type"); + Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type"); List list = new LinkedList((Collection) oldInstance); return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type}); } @@ -514,7 +489,7 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedRandomAccessList_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object type = getPrivateField(oldInstance, "type"); + Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type"); List list = new ArrayList((Collection) oldInstance); return new Expression(oldInstance, Collections.class, "checkedList", new Object[]{list, type}); } @@ -522,7 +497,7 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedSet_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object type = getPrivateField(oldInstance, "type"); + Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type"); Set set = new HashSet((Set) oldInstance); return new Expression(oldInstance, Collections.class, "checkedSet", new Object[]{set, type}); } @@ -530,7 +505,7 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedSortedSet_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object type = getPrivateField(oldInstance, "type"); + Object type = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedCollection.type"); SortedSet set = new TreeSet((SortedSet) oldInstance); return new Expression(oldInstance, Collections.class, "checkedSortedSet", new Object[]{set, type}); } @@ -538,8 +513,8 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedMap_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object keyType = getPrivateField(oldInstance, "keyType"); - Object valueType = getPrivateField(oldInstance, "valueType"); + Object keyType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType"); + Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType"); Map map = new HashMap((Map) oldInstance); return new Expression(oldInstance, Collections.class, "checkedMap", new Object[]{map, keyType, valueType}); } @@ -547,8 +522,8 @@ abstract class java_util_Collections extends PersistenceDelegate { static final class CheckedSortedMap_PersistenceDelegate extends java_util_Collections { protected Expression instantiate(Object oldInstance, Encoder out) { - Object keyType = getPrivateField(oldInstance, "keyType"); - Object valueType = getPrivateField(oldInstance, "valueType"); + Object keyType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.keyType"); + Object valueType = MetaData.getPrivateFieldValue(oldInstance, "java.util.Collections$CheckedMap.valueType"); SortedMap map = new TreeMap((SortedMap) oldInstance); return new Expression(oldInstance, Collections.class, "checkedSortedMap", new Object[]{map, keyType, valueType}); } @@ -570,7 +545,7 @@ class java_util_EnumMap_PersistenceDelegate extends PersistenceDelegate { } private static Object getType(Object instance) { - return java_util_Collections.getPrivateField(instance, "keyType"); + return MetaData.getPrivateFieldValue(instance, "java.util.EnumMap.keyType"); } } @@ -589,7 +564,7 @@ class java_util_EnumSet_PersistenceDelegate extends PersistenceDelegate { } private static Object getType(Object instance) { - return java_util_Collections.getPrivateField(instance, "elementType"); + return MetaData.getPrivateFieldValue(instance, "java.util.EnumSet.elementType"); } } @@ -1280,7 +1255,7 @@ class javax_swing_Box_PersistenceDelegate extends DefaultPersistenceDelegate { private Integer getAxis(Object object) { Box box = (Box) object; - return (Integer) java_util_Collections.getPrivateField(box.getLayout(), "axis"); + return (Integer) MetaData.getPrivateFieldValue(box.getLayout(), "javax.swing.BoxLayout.axis"); } } @@ -1363,6 +1338,7 @@ final class sun_swing_PrintColorUIResource_PersistenceDelegate extends Persisten } class MetaData { + private static final Map fields = Collections.synchronizedMap(new WeakHashMap()); private static Hashtable internalPersistenceDelegates = new Hashtable(); private static PersistenceDelegate nullPersistenceDelegate = new NullPersistenceDelegate(); @@ -1501,4 +1477,35 @@ class MetaData { return null; } } + + static Object getPrivateFieldValue(Object instance, String name) { + Field field = fields.get(name); + if (field == null) { + int index = name.lastIndexOf('.'); + final String className = name.substring(0, index); + final String fieldName = name.substring(1 + index); + field = AccessController.doPrivileged(new PrivilegedAction() { + public Field run() { + try { + Field field = Class.forName(className).getDeclaredField(fieldName); + field.setAccessible(true); + return field; + } + catch (ClassNotFoundException exception) { + throw new IllegalStateException("Could not find class", exception); + } + catch (NoSuchFieldException exception) { + throw new IllegalStateException("Could not find field", exception); + } + } + }); + fields.put(name, field); + } + try { + return field.get(instance); + } + catch (IllegalAccessException exception) { + throw new IllegalStateException("Could not get value of the field", exception); + } + } } diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestBox.java b/jdk/test/java/beans/XMLEncoder/6777487/TestBox.java new file mode 100644 index 00000000000..1287f4414b5 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestBox.java @@ -0,0 +1,52 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for BoxLayout + * @author Sergey Malenkov + */ + +import java.awt.FlowLayout; +import javax.swing.Box; +import javax.swing.BoxLayout; + +public final class TestBox { + private static final Integer OBJECT = Integer.valueOf(-123); + + public static void main(String[] args) { + TestEncoder.test( + new Box(BoxLayout.LINE_AXIS), + new Box(BoxLayout.PAGE_AXIS) { + @Override + public FlowLayout getLayout() { + return new FlowLayout() { + private final Object axis = OBJECT; + }; + } + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedCollection.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedCollection.java new file mode 100644 index 00000000000..805f05f4299 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedCollection.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedCollection + * @author Sergey Malenkov + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class TestCheckedCollection { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + List list = Collections.emptyList(); + TestEncoder.test( + Collections.checkedCollection(list, String.class), + new ArrayList() { + private final Object type = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedList.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedList.java new file mode 100644 index 00000000000..69d6ca9c8ba --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedList.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedList + * @author Sergey Malenkov + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class TestCheckedList { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + List list = Collections.emptyList(); + TestEncoder.test( + Collections.checkedList(list, String.class), + new ArrayList() { + private final Object type = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedMap.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedMap.java new file mode 100644 index 00000000000..7105782b179 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedMap.java @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedMap + * @author Sergey Malenkov + */ + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public final class TestCheckedMap { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + Map map = Collections.emptyMap(); + TestEncoder.test( + Collections.checkedMap(map, String.class, String.class), + new HashMap() { + private final Object keyType = OBJECT; + private final Object valueType = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedRandomAccessList.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedRandomAccessList.java new file mode 100644 index 00000000000..5141bc80620 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedRandomAccessList.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedRandomAccessList + * @author Sergey Malenkov + */ + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class TestCheckedRandomAccessList { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + List list = new ArrayList(); + TestEncoder.test( + Collections.checkedList(list, String.class), + new ArrayList() { + private final Object type = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSet.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSet.java new file mode 100644 index 00000000000..d4dd04160b0 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSet.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedSet + * @author Sergey Malenkov + */ + +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public final class TestCheckedSet { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + Set set = Collections.emptySet(); + TestEncoder.test( + Collections.checkedSet(set, String.class), + new HashSet() { + private final Object type = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedMap.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedMap.java new file mode 100644 index 00000000000..f39e7e2e060 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedMap.java @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedSortedMap + * @author Sergey Malenkov + */ + +import java.util.Collections; +import java.util.SortedMap; +import java.util.TreeMap; + +public final class TestCheckedSortedMap { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + SortedMap map = new TreeMap(); + TestEncoder.test( + Collections.checkedSortedMap(map, String.class, String.class), + new TreeMap() { + private final Object keyType = OBJECT; + private final Object valueType = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedSet.java b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedSet.java new file mode 100644 index 00000000000..f49c6ea3d94 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestCheckedSortedSet.java @@ -0,0 +1,48 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for CheckedSortedSet + * @author Sergey Malenkov + */ + +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; + +public final class TestCheckedSortedSet { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + SortedSet set = new TreeSet(); + TestEncoder.test( + Collections.checkedSortedSet(set, String.class), + new TreeSet() { + private final Object type = OBJECT; + }, + OBJECT + ); + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestEncoder.java b/jdk/test/java/beans/XMLEncoder/6777487/TestEncoder.java new file mode 100644 index 00000000000..a06289c8738 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestEncoder.java @@ -0,0 +1,60 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.beans.Expression; +import java.beans.XMLEncoder; + +final class TestEncoder extends XMLEncoder { + private Expression expression; + + private TestEncoder() { + super(System.out); + } + + @Override + public void writeExpression(Expression expression) { + if (this.expression == null) { + this.expression = expression; + } + super.writeExpression(expression); + } + + public static void test(Object provider, Object object, Object value) { + System.setSecurityManager(new SecurityManager()); + + TestEncoder encoder = new TestEncoder(); + encoder.setPersistenceDelegate( + object.getClass(), + encoder.getPersistenceDelegate(provider.getClass())); + encoder.writeObject(object); + encoder.close(); + + if (encoder.expression != null) { + for (Object argument : encoder.expression.getArguments()) { + if (value.equals(argument)) { + throw new Error("Found private value!"); + } + } + } + } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestEnumMap.java b/jdk/test/java/beans/XMLEncoder/6777487/TestEnumMap.java new file mode 100644 index 00000000000..1d046c63e88 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestEnumMap.java @@ -0,0 +1,47 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for EnumMap + * @author Sergey Malenkov + */ + +import java.util.EnumMap; +import java.util.HashMap; + +public final class TestEnumMap { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + TestEncoder.test( + new EnumMap(Point.class), + new HashMap() { + private final Object keyType = OBJECT; + }, + OBJECT); + } + + public enum Point { X, Y, Z } +} diff --git a/jdk/test/java/beans/XMLEncoder/6777487/TestEnumSet.java b/jdk/test/java/beans/XMLEncoder/6777487/TestEnumSet.java new file mode 100644 index 00000000000..b9f518d9979 --- /dev/null +++ b/jdk/test/java/beans/XMLEncoder/6777487/TestEnumSet.java @@ -0,0 +1,47 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6777487 + * @summary Tests private field access for EnumSet + * @author Sergey Malenkov + */ + +import java.util.EnumSet; +import java.util.HashSet; + +public final class TestEnumSet { + private static final Object OBJECT = new Object(); + + public static void main(String[] args) { + TestEncoder.test( + EnumSet.noneOf(Point.class), + new HashSet() { + private final Object elementType = OBJECT; + }, + OBJECT); + } + + public enum Point { X, Y, Z } +} From d663bac9312a84730da246fa8fcd8ce080e220fd Mon Sep 17 00:00:00 2001 From: Peter Zhelezniakov Date: Tue, 5 May 2009 12:07:37 +0400 Subject: [PATCH 03/70] 6837293: Reapply fix for 6588003 to JDK7 Reviewed-by: alexp --- .../classes/javax/swing/text/LayoutQueue.java | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/text/LayoutQueue.java b/jdk/src/share/classes/javax/swing/text/LayoutQueue.java index 38fd665c40e..f1d73ffc0d8 100644 --- a/jdk/src/share/classes/javax/swing/text/LayoutQueue.java +++ b/jdk/src/share/classes/javax/swing/text/LayoutQueue.java @@ -25,6 +25,7 @@ package javax.swing.text; import java.util.Vector; +import sun.awt.AppContext; /** * A queue of text layout tasks. @@ -35,10 +36,10 @@ import java.util.Vector; */ public class LayoutQueue { - Vector tasks; - Thread worker; + private static final Object DEFAULT_QUEUE = new Object(); - static LayoutQueue defaultQueue; + private Vector tasks; + private Thread worker; /** * Construct a layout queue. @@ -51,10 +52,15 @@ public class LayoutQueue { * Fetch the default layout queue. */ public static LayoutQueue getDefaultQueue() { - if (defaultQueue == null) { - defaultQueue = new LayoutQueue(); + AppContext ac = AppContext.getAppContext(); + synchronized (DEFAULT_QUEUE) { + LayoutQueue defaultQueue = (LayoutQueue) ac.get(DEFAULT_QUEUE); + if (defaultQueue == null) { + defaultQueue = new LayoutQueue(); + ac.put(DEFAULT_QUEUE, defaultQueue); + } + return defaultQueue; } - return defaultQueue; } /** @@ -63,7 +69,9 @@ public class LayoutQueue { * @param q the new queue. */ public static void setDefaultQueue(LayoutQueue q) { - defaultQueue = q; + synchronized (DEFAULT_QUEUE) { + AppContext.getAppContext().put(DEFAULT_QUEUE, q); + } } /** From b23fe07b43057fcb66d2a463e8e8371ce6b2069c Mon Sep 17 00:00:00 2001 From: Jean-Christophe Collet Date: Tue, 5 May 2009 11:02:51 +0200 Subject: [PATCH 04/70] 6801497: Proxy is assumed to be immutable but is non-final Cloned the proxy instance when necessary Reviewed-by: chegar --- jdk/src/share/classes/java/net/Socket.java | 13 +++++++++---- jdk/src/share/classes/java/net/URL.java | 8 +++++--- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/jdk/src/share/classes/java/net/Socket.java b/jdk/src/share/classes/java/net/Socket.java index e0769176af3..110a6a5f1a9 100644 --- a/jdk/src/share/classes/java/net/Socket.java +++ b/jdk/src/share/classes/java/net/Socket.java @@ -114,9 +114,14 @@ class Socket implements java.io.Closeable { * @since 1.5 */ public Socket(Proxy proxy) { - if (proxy != null && proxy.type() == Proxy.Type.SOCKS) { + // Create a copy of Proxy as a security measure + if (proxy == null) { + throw new IllegalArgumentException("Invalid Proxy"); + } + Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : new Proxy(proxy.type(), proxy.address()); + if (p.type() == Proxy.Type.SOCKS) { SecurityManager security = System.getSecurityManager(); - InetSocketAddress epoint = (InetSocketAddress) proxy.address(); + InetSocketAddress epoint = (InetSocketAddress) p.address(); if (security != null) { if (epoint.isUnresolved()) security.checkConnect(epoint.getHostName(), @@ -125,10 +130,10 @@ class Socket implements java.io.Closeable { security.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort()); } - impl = new SocksSocketImpl(proxy); + impl = new SocksSocketImpl(p); impl.setSocket(this); } else { - if (proxy == Proxy.NO_PROXY) { + if (p == Proxy.NO_PROXY) { if (factory == null) { impl = new PlainSocketImpl(); impl.setSocket(this); diff --git a/jdk/src/share/classes/java/net/URL.java b/jdk/src/share/classes/java/net/URL.java index bb934d9b745..73818e960d8 100644 --- a/jdk/src/share/classes/java/net/URL.java +++ b/jdk/src/share/classes/java/net/URL.java @@ -1004,16 +1004,18 @@ public final class URL implements java.io.Serializable { throw new IllegalArgumentException("proxy can not be null"); } + // Create a copy of Proxy as a security measure + Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : new Proxy(proxy.type(), proxy.address()); SecurityManager sm = System.getSecurityManager(); - if (proxy.type() != Proxy.Type.DIRECT && sm != null) { - InetSocketAddress epoint = (InetSocketAddress) proxy.address(); + if (p.type() != Proxy.Type.DIRECT && sm != null) { + InetSocketAddress epoint = (InetSocketAddress) p.address(); if (epoint.isUnresolved()) sm.checkConnect(epoint.getHostName(), epoint.getPort()); else sm.checkConnect(epoint.getAddress().getHostAddress(), epoint.getPort()); } - return handler.openConnection(this, proxy); + return handler.openConnection(this, p); } /** From 2453a64fc4954f7a2b13cf20f13583cc542fa0a3 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Tue, 5 May 2009 17:47:04 +0400 Subject: [PATCH 05/70] 6805231: Security Warning Icon is missing in Windows 2000 Prof from Jdk build 6u12 The icon becomes layered only when the fading-out effect is being performed. Reviewed-by: art, dcherepanov --- .../windows/native/sun/windows/awt_Window.cpp | 36 ++++++++++++++----- .../windows/native/sun/windows/awt_Window.h | 3 ++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/jdk/src/windows/native/sun/windows/awt_Window.cpp b/jdk/src/windows/native/sun/windows/awt_Window.cpp index 88bcd8ecc45..3e31a1c8db8 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp @@ -524,7 +524,7 @@ void AwtWindow::CreateWarningWindow(JNIEnv *env) RegisterWarningWindowClass(); warningWindow = ::CreateWindowEx( - WS_EX_NOACTIVATE | WS_EX_LAYERED, + WS_EX_NOACTIVATE, GetWarningWindowClassName(), warningString, WS_POPUP, @@ -536,7 +536,7 @@ void AwtWindow::CreateWarningWindow(JNIEnv *env) NULL // lParam ); if (warningWindow == NULL) { - //XXX: actually this is bad... We didn't manage to create the widow. + //XXX: actually this is bad... We didn't manage to create the window. return; } @@ -836,6 +836,19 @@ void AwtWindow::RepaintWarningWindow() ::ReleaseDC(warningWindow, hdc); } +void AwtWindow::SetLayered(HWND window, bool layered) +{ + const LONG ex_style = ::GetWindowLong(window, GWL_EXSTYLE); + ::SetWindowLong(window, GWL_EXSTYLE, layered ? + ex_style | WS_EX_LAYERED : ex_style & ~WS_EX_LAYERED); +} + +bool AwtWindow::IsLayered(HWND window) +{ + const LONG ex_style = ::GetWindowLong(window, GWL_EXSTYLE); + return ex_style & WS_EX_LAYERED; +} + void AwtWindow::StartSecurityAnimation(AnimationKind kind) { if (!IsUntrusted()) { @@ -858,8 +871,14 @@ void AwtWindow::StartSecurityAnimation(AnimationKind kind) ::SetLayeredWindowAttributes(warningWindow, RGB(0, 0, 0), 0xFF, LWA_ALPHA); + AwtWindow::SetLayered(warningWindow, false); ::RedrawWindow(warningWindow, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN); + } else if (securityAnimationKind == akPreHide) { + // Pre-hiding means fading-out. We have to make the window layered. + // Note: Some VNC clients do not support layered windows, hence + // we dynamically turn it on and off. See 6805231. + AwtWindow::SetLayered(warningWindow, true); } } @@ -2528,8 +2547,6 @@ void AwtWindow::SetTranslucency(BYTE opacity, BOOL opaque) HWND hwnd = GetHWnd(); - LONG ex_style = ::GetWindowLong(hwnd, GWL_EXSTYLE); - if (opaque != old_opaque) { ::EnterCriticalSection(&contentBitmapCS); if (hContentBitmap != NULL) { @@ -2541,21 +2558,22 @@ void AwtWindow::SetTranslucency(BYTE opacity, BOOL opaque) if (opaque && opacity == 0xff) { // Turn off all the effects - ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style & ~WS_EX_LAYERED); + AwtWindow::SetLayered(hwnd, false); + // Ask the window to repaint itself and all the children RedrawWindow(); } else { // We're going to enable some effects - if (!(ex_style & WS_EX_LAYERED)) { - ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED); + if (!AwtWindow::IsLayered(hwnd)) { + AwtWindow::SetLayered(hwnd, true); } else { if ((opaque && opacity < 0xff) ^ (old_opaque && old_opacity < 0xff)) { // _One_ of the modes uses the SetLayeredWindowAttributes. // Need to reset the style in this case. // If both modes are simple (i.e. just changing the opacity level), // no need to reset the style. - ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style & ~WS_EX_LAYERED); - ::SetWindowLong(hwnd, GWL_EXSTYLE, ex_style | WS_EX_LAYERED); + AwtWindow::SetLayered(hwnd, false); + AwtWindow::SetLayered(hwnd, true); } } diff --git a/jdk/src/windows/native/sun/windows/awt_Window.h b/jdk/src/windows/native/sun/windows/awt_Window.h index bf43150a7e8..40da9979bcd 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.h +++ b/jdk/src/windows/native/sun/windows/awt_Window.h @@ -332,6 +332,9 @@ private: void RepositionSecurityWarning(JNIEnv *env); + static void SetLayered(HWND window, bool layered); + static bool IsLayered(HWND window); + public: void UpdateSecurityWarningVisibility(); static bool IsWarningWindow(HWND hWnd); From dfb6852a1624bfa42b89ad993ec832bfab0b5d89 Mon Sep 17 00:00:00 2001 From: Anthony Petrov Date: Tue, 5 May 2009 17:56:31 +0400 Subject: [PATCH 06/70] 6818787: It is possible to reposition the security icon too far from the border of the window on X11 The constraints for the position of the icon are moved to the shared code Reviewed-by: art, dcherepanov --- jdk/src/share/classes/java/awt/Window.java | 54 ++++++++++++++++--- .../windows/native/sun/windows/awt_Window.cpp | 25 --------- 2 files changed, 47 insertions(+), 32 deletions(-) diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 01d9ff59d00..faff2758726 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -3593,16 +3593,56 @@ public class Window extends Container implements Accessible { // ****************** END OF MIXING CODE ******************************** - // This method gets the window location/size as reported by the native - // system since the locally cached values may represent outdated data. - // NOTE: this method is invoked on the toolkit thread, and therefore - // is not supposed to become public/user-overridable. + /** + * Limit the given double value with the given range. + */ + private static double limit(double value, double min, double max) { + value = Math.max(value, min); + value = Math.min(value, max); + return value; + } + + /** + * Calculate the position of the security warning. + * + * This method gets the window location/size as reported by the native + * system since the locally cached values may represent outdated data. + * + * The method is used from the native code, or via AWTAccessor. + * + * NOTE: this method is invoked on the toolkit thread, and therefore is not + * supposed to become public/user-overridable. + */ private Point2D calculateSecurityWarningPosition(double x, double y, double w, double h) { - return new Point2D.Double( - x + w * securityWarningAlignmentX + securityWarningPointX, - y + h * securityWarningAlignmentY + securityWarningPointY); + // The position according to the spec of SecurityWarning.setPosition() + double wx = x + w * securityWarningAlignmentX + securityWarningPointX; + double wy = y + h * securityWarningAlignmentY + securityWarningPointY; + + // First, make sure the warning is not too far from the window bounds + wx = Window.limit(wx, + x - securityWarningWidth - 2, + x + w + 2); + wy = Window.limit(wy, + y - securityWarningHeight - 2, + y + h + 2); + + // Now make sure the warning window is visible on the screen + Rectangle screenBounds = graphicsConfig.getBounds(); + Insets screenInsets = + Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfig); + + wx = Window.limit(wx, + screenBounds.x + screenInsets.left, + screenBounds.x + screenBounds.width - screenInsets.right + - securityWarningWidth); + wy = Window.limit(wy, + screenBounds.y + screenInsets.top, + screenBounds.y + screenBounds.height - screenInsets.bottom + - securityWarningHeight); + + return new Point2D.Double(wx, wy); } static { diff --git a/jdk/src/windows/native/sun/windows/awt_Window.cpp b/jdk/src/windows/native/sun/windows/awt_Window.cpp index 3e31a1c8db8..39f61bb7543 100644 --- a/jdk/src/windows/native/sun/windows/awt_Window.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp @@ -707,31 +707,6 @@ void AwtWindow::CalculateWarningWindowBounds(JNIEnv *env, LPRECT rect) env->DeleteLocalRef(point2D); - //Make sure the warning is not far from the window bounds - x = max(x, windowBounds.left - (int)warningWindowWidth - 2); - x = min(x, windowBounds.right + (int)warningWindowWidth + 2); - - y = max(y, windowBounds.top - (int)warningWindowHeight - 2); - y = min(y, windowBounds.bottom + (int)warningWindowHeight + 2); - - // Now make sure the warning window is visible on the screen - HMONITOR hmon = MonitorFromWindow(GetHWnd(), MONITOR_DEFAULTTOPRIMARY); - DASSERT(hmon != NULL); - - RECT monitorBounds; - RECT monitorInsets; - - MonitorBounds(hmon, &monitorBounds); - if (!AwtToolkit::GetScreenInsets(m_screenNum, &monitorInsets)) { - ::ZeroMemory(&monitorInsets, sizeof(monitorInsets)); - } - - x = max(x, monitorBounds.left + monitorInsets.left); - x = min(x, monitorBounds.right - monitorInsets.right - (int)warningWindowWidth); - - y = max(y, monitorBounds.top + monitorInsets.top); - y = min(y, monitorBounds.bottom - monitorInsets.bottom - (int)warningWindowHeight); - rect->left = x; rect->top = y; rect->right = rect->left + warningWindowWidth; From f6e8569c858067188a8d84e91d91dafa4aaa0a71 Mon Sep 17 00:00:00 2001 From: Artem Ananiev Date: Wed, 6 May 2009 15:17:22 +0400 Subject: [PATCH 07/70] 6656586: Cursor.predefined is protected static mutable (findbugs) Reviewed-by: hawtin, igor --- jdk/src/share/classes/java/awt/Cursor.java | 21 ++++++-- .../PredefinedPrivate/PredefinedPrivate.java | 49 +++++++++++++++++++ 2 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 jdk/test/java/awt/Cursor/PredefinedPrivate/PredefinedPrivate.java diff --git a/jdk/src/share/classes/java/awt/Cursor.java b/jdk/src/share/classes/java/awt/Cursor.java index cc1b20b999a..0187eac69b9 100644 --- a/jdk/src/share/classes/java/awt/Cursor.java +++ b/jdk/src/share/classes/java/awt/Cursor.java @@ -118,8 +118,18 @@ public class Cursor implements java.io.Serializable { */ public static final int MOVE_CURSOR = 13; + /** + * @deprecated As of JDK version 1.7, the {@link #getPredefinedCursor()} + * method should be used instead. + */ + @Deprecated protected static Cursor predefined[] = new Cursor[14]; + /** + * This field is a private replacement for 'predefined' array. + */ + private final static Cursor[] predefinedPrivate = new Cursor[14]; + /* Localization names and default values */ static final String[][] cursorProperties = { { "AWT.DefaultCursor", "Default Cursor" }, @@ -253,10 +263,15 @@ public class Cursor implements java.io.Serializable { if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) { throw new IllegalArgumentException("illegal cursor type"); } - if (predefined[type] == null) { - predefined[type] = new Cursor(type); + Cursor c = predefinedPrivate[type]; + if (c == null) { + predefinedPrivate[type] = c = new Cursor(type); } - return predefined[type]; + // fill 'predefined' array for backwards compatibility. + if (predefined[type] == null) { + predefined[type] = c; + } + return c; } /** diff --git a/jdk/test/java/awt/Cursor/PredefinedPrivate/PredefinedPrivate.java b/jdk/test/java/awt/Cursor/PredefinedPrivate/PredefinedPrivate.java new file mode 100644 index 00000000000..a4ba1daaca4 --- /dev/null +++ b/jdk/test/java/awt/Cursor/PredefinedPrivate/PredefinedPrivate.java @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6656586 + * @summary Test that Cursor.predefined array is not used in +Cursor.getPredefinedCursor() method + * @author Artem Ananiev + * @run main PredefinedPrivate + */ + +import java.awt.*; + +public class PredefinedPrivate { + public static void main(String args[]) { + new MyCursor(); + if (Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR) instanceof MyCursor) { + throw new RuntimeException("Test FAILED: getPredefinedCursor() returned modified cursor"); + } + } +} + +class MyCursor extends Cursor { + public MyCursor() { + super(DEFAULT_CURSOR); + Cursor.predefined[DEFAULT_CURSOR] = this; + } +} From ec41d4d0e931bf22dbfbcda44d506c9a44a3091d Mon Sep 17 00:00:00 2001 From: Eamonn McManus Date: Thu, 7 May 2009 10:44:45 +0200 Subject: [PATCH 08/70] 6736293: OpenType checks can be bypassed through finalizer resurrection Reviewed-by: hawtin --- jdk/src/share/classes/java/awt/Window.java | 2 ++ .../openmbean/OpenMBeanAttributeInfoSupport.java | 8 ++++---- .../classes/javax/management/openmbean/OpenType.java | 5 +++++ 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index faff2758726..920b499c9a3 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -3629,6 +3629,8 @@ public class Window extends Container implements Accessible { y + h + 2); // Now make sure the warning window is visible on the screen + GraphicsConfiguration graphicsConfig = + getGraphicsConfiguration_NoClientCode(); Rectangle screenBounds = graphicsConfig.getBounds(); Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(graphicsConfig); diff --git a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java index 3ad03ef58ae..f2f86e1bf72 100644 --- a/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java +++ b/jdk/src/share/classes/javax/management/openmbean/OpenMBeanAttributeInfoSupport.java @@ -690,7 +690,7 @@ public class OpenMBeanAttributeInfoSupport private static T convertFromString(String s, OpenType openType) { Class c; try { - c = cast(Class.forName(openType.getClassName())); + c = cast(Class.forName(openType.safeGetClassName())); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.toString()); // can't happen } @@ -711,7 +711,7 @@ public class OpenMBeanAttributeInfoSupport } catch (Exception e) { final String msg = "Could not convert \"" + s + "\" using method: " + valueOf; - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException(msg, e); } } @@ -728,7 +728,7 @@ public class OpenMBeanAttributeInfoSupport } catch (Exception e) { final String msg = "Could not convert \"" + s + "\" using constructor: " + con; - throw new IllegalArgumentException(msg); + throw new IllegalArgumentException(msg, e); } } @@ -757,7 +757,7 @@ public class OpenMBeanAttributeInfoSupport stringArrayClass = Class.forName(squareBrackets + "Ljava.lang.String;"); targetArrayClass = - Class.forName(squareBrackets + "L" + baseType.getClassName() + + Class.forName(squareBrackets + "L" + baseType.safeGetClassName() + ";"); } catch (ClassNotFoundException e) { throw new NoClassDefFoundError(e.toString()); // can't happen diff --git a/jdk/src/share/classes/javax/management/openmbean/OpenType.java b/jdk/src/share/classes/javax/management/openmbean/OpenType.java index 3f74c3cda60..b6d40d008c7 100644 --- a/jdk/src/share/classes/javax/management/openmbean/OpenType.java +++ b/jdk/src/share/classes/javax/management/openmbean/OpenType.java @@ -304,7 +304,12 @@ public abstract class OpenType implements Serializable { * @return the class name. */ public String getClassName() { + return className; + } + // A version of getClassName() that can only be called from within this + // package and that cannot be overridden. + String safeGetClassName() { return className; } From 10f62128a45fa6384621e57b86cc18475ee7fa27 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 8 May 2009 15:38:21 +0400 Subject: [PATCH 09/70] 6656625: ImageReaderSpi.STANDARD_INPUT_TYPE/ImageWriterSpi.STANDARD_OUTPUT_TYPE are mutable static (findbugs) Reviewed-by: prr --- .../sun/imageio/plugins/bmp/BMPImageReaderSpi.java | 2 +- .../sun/imageio/plugins/bmp/BMPImageWriterSpi.java | 3 ++- .../sun/imageio/plugins/gif/GIFImageReaderSpi.java | 2 +- .../sun/imageio/plugins/gif/GIFImageWriterSpi.java | 3 ++- .../imageio/plugins/jpeg/JPEGImageReaderSpi.java | 2 +- .../imageio/plugins/jpeg/JPEGImageWriterSpi.java | 3 ++- .../sun/imageio/plugins/png/PNGImageReaderSpi.java | 2 +- .../sun/imageio/plugins/png/PNGImageWriterSpi.java | 3 ++- .../imageio/plugins/wbmp/WBMPImageReaderSpi.java | 2 +- .../imageio/plugins/wbmp/WBMPImageWriterSpi.java | 3 ++- .../classes/javax/imageio/spi/ImageReaderSpi.java | 9 ++++++++- .../classes/javax/imageio/spi/ImageWriterSpi.java | 13 ++++++++++--- 12 files changed, 33 insertions(+), 14 deletions(-) diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java index 9cea55911f7..2966a4b883c 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReaderSpi.java @@ -51,7 +51,7 @@ public class BMPImageReaderSpi extends ImageReaderSpi { entensions, mimeType, "com.sun.imageio.plugins.bmp.BMPImageReader", - STANDARD_INPUT_TYPE, + new Class[] { ImageInputStream.class }, writerSpiNames, false, null, null, null, null, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java index f5e322e01da..4ae73d4c897 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageWriterSpi.java @@ -32,6 +32,7 @@ import java.awt.image.SinglePixelPackedSampleModel; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; +import javax.imageio.stream.ImageOutputStream; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; @@ -55,7 +56,7 @@ public class BMPImageWriterSpi extends ImageWriterSpi { entensions, mimeType, "com.sun.imageio.plugins.bmp.BMPImageWriter", - STANDARD_OUTPUT_TYPE, + new Class[] { ImageOutputStream.class }, readerSpiNames, false, null, null, null, null, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java index 0dc0a40a6d7..3832b1eb923 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageReaderSpi.java @@ -60,7 +60,7 @@ public class GIFImageReaderSpi extends ImageReaderSpi { suffixes, MIMETypes, readerClassName, - STANDARD_INPUT_TYPE, + new Class[] { ImageInputStream.class }, writerSpiNames, true, GIFStreamMetadata.nativeMetadataFormatName, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java index 796e3b2a458..42b81e4c8b8 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/gif/GIFImageWriterSpi.java @@ -31,6 +31,7 @@ import java.util.Locale; import javax.imageio.ImageTypeSpecifier; import javax.imageio.ImageWriter; import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.stream.ImageOutputStream; import com.sun.imageio.plugins.common.PaletteBuilder; public class GIFImageWriterSpi extends ImageWriterSpi { @@ -59,7 +60,7 @@ public class GIFImageWriterSpi extends ImageWriterSpi { suffixes, MIMETypes, writerClassName, - STANDARD_OUTPUT_TYPE, + new Class[] { ImageOutputStream.class }, readerSpiNames, true, GIFWritableStreamMetadata.NATIVE_FORMAT_NAME, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java index 13327e3ea9c..25aabe32e90 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReaderSpi.java @@ -46,7 +46,7 @@ public class JPEGImageReaderSpi extends ImageReaderSpi { JPEG.suffixes, JPEG.MIMETypes, "com.sun.imageio.plugins.jpeg.JPEGImageReader", - STANDARD_INPUT_TYPE, + new Class[] { ImageInputStream.class }, writerSpiNames, true, JPEG.nativeStreamMetadataFormatName, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java index 717b4360794..02fade632ed 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriterSpi.java @@ -28,6 +28,7 @@ package com.sun.imageio.plugins.jpeg; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; +import javax.imageio.stream.ImageOutputStream; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; @@ -49,7 +50,7 @@ public class JPEGImageWriterSpi extends ImageWriterSpi { JPEG.suffixes, JPEG.MIMETypes, "com.sun.imageio.plugins.jpeg.JPEGImageWriter", - STANDARD_OUTPUT_TYPE, + new Class[] { ImageOutputStream.class }, readerSpiNames, true, JPEG.nativeStreamMetadataFormatName, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java index 44ee5b80101..6576b83df58 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageReaderSpi.java @@ -60,7 +60,7 @@ public class PNGImageReaderSpi extends ImageReaderSpi { suffixes, MIMETypes, readerClassName, - STANDARD_INPUT_TYPE, + new Class[] { ImageInputStream.class }, writerSpiNames, false, null, null, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java index 0dabd881816..4f69fcd70de 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/png/PNGImageWriterSpi.java @@ -34,6 +34,7 @@ import javax.imageio.ImageTypeSpecifier; import javax.imageio.metadata.IIOMetadataFormat; import javax.imageio.metadata.IIOMetadataFormatImpl; import javax.imageio.spi.ImageWriterSpi; +import javax.imageio.stream.ImageOutputStream; public class PNGImageWriterSpi extends ImageWriterSpi { @@ -61,7 +62,7 @@ public class PNGImageWriterSpi extends ImageWriterSpi { suffixes, MIMETypes, writerClassName, - STANDARD_OUTPUT_TYPE, + new Class[] { ImageOutputStream.class }, readerSpiNames, false, null, null, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java index 2d882ab6b2c..7e5e6e61e0e 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageReaderSpi.java @@ -51,7 +51,7 @@ public class WBMPImageReaderSpi extends ImageReaderSpi { entensions, mimeType, "com.sun.imageio.plugins.wbmp.WBMPImageReader", - STANDARD_INPUT_TYPE, + new Class[] { ImageInputStream.class }, writerSpiNames, true, null, null, null, null, diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java index 1da8420dc32..82106f981f5 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/wbmp/WBMPImageWriterSpi.java @@ -28,6 +28,7 @@ package com.sun.imageio.plugins.wbmp; import javax.imageio.spi.ImageWriterSpi; import javax.imageio.spi.ServiceRegistry; import javax.imageio.spi.IIORegistry; +import javax.imageio.stream.ImageOutputStream; import javax.imageio.ImageWriter; import javax.imageio.ImageTypeSpecifier; import javax.imageio.IIOException; @@ -54,7 +55,7 @@ public class WBMPImageWriterSpi extends ImageWriterSpi { entensions, mimeType, "com.sun.imageio.plugins.wbmp.WBMPImageWriter", - STANDARD_OUTPUT_TYPE, + new Class[] { ImageOutputStream.class }, readerSpiNames, true, null, null, null, null, diff --git a/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java b/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java index 4f0b7fa6ac5..0de66188ba8 100644 --- a/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java +++ b/jdk/src/share/classes/javax/imageio/spi/ImageReaderSpi.java @@ -77,7 +77,10 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { * A single-element array, initially containing * ImageInputStream.class, to be returned from * getInputTypes. + * @deprecated Instead of using this field, directly create + * the equivalent array { ImageInputStream.class }. */ + @Deprecated public static final Class[] STANDARD_INPUT_TYPE = { ImageInputStream.class }; @@ -227,7 +230,11 @@ public abstract class ImageReaderSpi extends ImageReaderWriterSpi { throw new IllegalArgumentException ("inputTypes.length == 0!"); } - this.inputTypes = (Class[])inputTypes.clone(); + + this.inputTypes = (inputTypes == STANDARD_INPUT_TYPE) ? + new Class[] { ImageInputStream.class } : + inputTypes.clone(); + // If length == 0, leave it null if (writerSpiNames != null && writerSpiNames.length > 0) { this.writerSpiNames = (String[])writerSpiNames.clone(); diff --git a/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java b/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java index 324c5cd3d05..f3ff947a4f4 100644 --- a/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java +++ b/jdk/src/share/classes/javax/imageio/spi/ImageWriterSpi.java @@ -77,9 +77,12 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { /** * A single-element array, initially containing - * ImageInputStream.class, to be returned from - * getInputTypes. + * ImageOutputStream.class, to be returned from + * getOutputTypes. + * @deprecated Instead of using this field, directly create + * the equivalent array { ImageOutputStream.class }. */ + @Deprecated public static final Class[] STANDARD_OUTPUT_TYPE = { ImageOutputStream.class }; @@ -228,7 +231,11 @@ public abstract class ImageWriterSpi extends ImageReaderWriterSpi { throw new IllegalArgumentException ("outputTypes.length == 0!"); } - this.outputTypes = (Class[])outputTypes.clone(); + + this.outputTypes = (outputTypes == STANDARD_OUTPUT_TYPE) ? + new Class[] { ImageOutputStream.class } : + outputTypes.clone(); + // If length == 0, leave it null if (readerSpiNames != null && readerSpiNames.length > 0) { this.readerSpiNames = (String[])readerSpiNames.clone(); From 8fdb1d367a6988246045d77dba7ce3e9b4eab893 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 8 May 2009 15:57:33 +0400 Subject: [PATCH 10/70] 6657133: Mutable statics in imageio plugins (findbugs) Reviewed-by: prr --- .../com/sun/imageio/stream/StreamCloser.java | 44 +++++++++++++------ .../plugins/bmp/BMPImageWriteParam.java | 2 +- .../stream/FileCacheImageInputStream.java | 10 ++++- .../stream/FileCacheImageOutputStream.java | 10 ++++- jdk/src/share/lib/security/java.security | 2 +- .../share/lib/security/java.security-solaris | 2 +- .../share/lib/security/java.security-windows | 2 +- 7 files changed, 51 insertions(+), 21 deletions(-) diff --git a/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java b/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java index 03c6ce32364..96e5646f782 100644 --- a/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java +++ b/jdk/src/share/classes/com/sun/imageio/stream/StreamCloser.java @@ -43,35 +43,35 @@ import javax.imageio.stream.ImageInputStream; */ public class StreamCloser { - private static WeakHashMap toCloseQueue; + private static WeakHashMap toCloseQueue; private static Thread streamCloser; - public static void addToQueue(ImageInputStream iis) { + public static void addToQueue(CloseAction ca) { synchronized (StreamCloser.class) { if (toCloseQueue == null) { toCloseQueue = - new WeakHashMap(); + new WeakHashMap(); } - toCloseQueue.put(iis, null); + toCloseQueue.put(ca, null); if (streamCloser == null) { final Runnable streamCloserRunnable = new Runnable() { public void run() { if (toCloseQueue != null) { synchronized (StreamCloser.class) { - Set set = + Set set = toCloseQueue.keySet(); // Make a copy of the set in order to avoid // concurrent modification (the is.close() // will in turn call removeFromQueue()) - ImageInputStream[] streams = - new ImageInputStream[set.size()]; - streams = set.toArray(streams); - for (ImageInputStream is : streams) { - if (is != null) { + CloseAction[] actions = + new CloseAction[set.size()]; + actions = set.toArray(actions); + for (CloseAction ca : actions) { + if (ca != null) { try { - is.close(); + ca.performAction(); } catch (IOException e) { } } @@ -106,10 +106,28 @@ public class StreamCloser { } } - public static void removeFromQueue(ImageInputStream iis) { + public static void removeFromQueue(CloseAction ca) { synchronized (StreamCloser.class) { if (toCloseQueue != null) { - toCloseQueue.remove(iis); + toCloseQueue.remove(ca); + } + } + } + + public static CloseAction createCloseAction(ImageInputStream iis) { + return new CloseAction(iis); + } + + public static final class CloseAction { + private ImageInputStream iis; + + private CloseAction(ImageInputStream iis) { + this.iis = iis; + } + + public void performAction() throws IOException { + if (iis != null) { + iis.close(); } } } diff --git a/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java b/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java index ec3acf2e9db..e11057f2a48 100644 --- a/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java +++ b/jdk/src/share/classes/javax/imageio/plugins/bmp/BMPImageWriteParam.java @@ -78,7 +78,7 @@ public class BMPImageWriteParam extends ImageWriteParam { super(locale); // Set compression types ("BI_RGB" denotes uncompressed). - compressionTypes = BMPConstants.compressionTypeNames; + compressionTypes = BMPConstants.compressionTypeNames.clone(); // Set compression flag. canWriteCompressed = true; diff --git a/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java b/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java index ad03d65c04d..1bff7746344 100644 --- a/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java +++ b/jdk/src/share/classes/javax/imageio/stream/FileCacheImageInputStream.java @@ -62,6 +62,10 @@ public class FileCacheImageInputStream extends ImageInputStreamImpl { /** The DisposerRecord that closes the underlying cache. */ private final DisposerRecord disposerRecord; + /** The CloseAction that closes the stream in + * the StreamCloser's shutdown hook */ + private final StreamCloser.CloseAction closeAction; + /** * Constructs a FileCacheImageInputStream that will read * from a given InputStream. @@ -96,7 +100,9 @@ public class FileCacheImageInputStream extends ImageInputStreamImpl { this.cacheFile = File.createTempFile("imageio", ".tmp", cacheDir); this.cache = new RandomAccessFile(cacheFile, "rw"); - StreamCloser.addToQueue(this); + + this.closeAction = StreamCloser.createCloseAction(this); + StreamCloser.addToQueue(closeAction); disposerRecord = new StreamDisposerRecord(cacheFile, cache); if (getClass() == FileCacheImageInputStream.class) { @@ -242,7 +248,7 @@ public class FileCacheImageInputStream extends ImageInputStreamImpl { stream = null; cache = null; cacheFile = null; - StreamCloser.removeFromQueue(this); + StreamCloser.removeFromQueue(closeAction); } /** diff --git a/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java b/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java index f6387125499..f079e8e81fa 100644 --- a/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java +++ b/jdk/src/share/classes/javax/imageio/stream/FileCacheImageOutputStream.java @@ -48,6 +48,10 @@ public class FileCacheImageOutputStream extends ImageOutputStreamImpl { // Pos after last (rightmost) byte written private long maxStreamPos = 0L; + /** The CloseAction that closes the stream in + * the StreamCloser's shutdown hook */ + private final StreamCloser.CloseAction closeAction; + /** * Constructs a FileCacheImageOutputStream that will write * to a given outputStream. @@ -82,7 +86,9 @@ public class FileCacheImageOutputStream extends ImageOutputStreamImpl { this.cacheFile = File.createTempFile("imageio", ".tmp", cacheDir); this.cache = new RandomAccessFile(cacheFile, "rw"); - StreamCloser.addToQueue(this); + + this.closeAction = StreamCloser.createCloseAction(this); + StreamCloser.addToQueue(closeAction); } public int read() throws IOException { @@ -227,7 +233,7 @@ public class FileCacheImageOutputStream extends ImageOutputStreamImpl { cacheFile = null; stream.flush(); stream = null; - StreamCloser.removeFromQueue(this); + StreamCloser.removeFromQueue(closeAction); } public void flushBefore(long pos) throws IOException { diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security index eadfe715b51..c2a07506c15 100644 --- a/jdk/src/share/lib/security/java.security +++ b/jdk/src/share/lib/security/java.security @@ -127,7 +127,7 @@ system.scope=sun.security.provider.IdentityDatabase # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun. +package.access=sun.,com.sun.imageio. # # List of comma-separated packages that start with or equal this string diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris index 58fbc9d15cd..05dfcb17728 100644 --- a/jdk/src/share/lib/security/java.security-solaris +++ b/jdk/src/share/lib/security/java.security-solaris @@ -128,7 +128,7 @@ system.scope=sun.security.provider.IdentityDatabase # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun. +package.access=sun.,com.sun.imageio. # # List of comma-separated packages that start with or equal this string diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows index 25de17d5247..062b85b63c3 100644 --- a/jdk/src/share/lib/security/java.security-windows +++ b/jdk/src/share/lib/security/java.security-windows @@ -128,7 +128,7 @@ system.scope=sun.security.provider.IdentityDatabase # passed to checkPackageAccess unless the # corresponding RuntimePermission ("accessClassInPackage."+package) has # been granted. -package.access=sun. +package.access=sun.,com.sun.imageio. # # List of comma-separated packages that start with or equal this string From 813ad65e9a7847816c206e194c4b8d297ed3ca17 Mon Sep 17 00:00:00 2001 From: Andrew Brygin Date: Fri, 8 May 2009 16:15:15 +0400 Subject: [PATCH 11/70] 6823373: [ZDI-CAN-460] Java Web Start JPEG header parsing needs more scruity Reviewed-by: igor --- .../sun/awt/splashscreen/splashscreen_jpeg.c | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c index 09d38fcb422..5d250e9e4b3 100644 --- a/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c +++ b/jdk/src/share/native/sun/awt/splashscreen/splashscreen_jpeg.c @@ -139,21 +139,45 @@ SplashDecodeJpeg(Splash * splash, struct jpeg_decompress_struct *cinfo) splash->width = cinfo->output_width; splash->height = cinfo->output_height; + + if (!SAFE_TO_ALLOC(splash->imageFormat.depthBytes, splash->width)) { + return 0; + } stride = splash->width * splash->imageFormat.depthBytes; + if (!SAFE_TO_ALLOC(stride, splash->height)) { + return 0; + } + if (!SAFE_TO_ALLOC(cinfo->output_width, cinfo->output_components)) { + return 0; + } + splash->frameCount = 1; splash->frames = (SplashImage *) malloc(sizeof(SplashImage) * splash->frameCount); + if (splash->frames == NULL) { + return 0; + } memset(splash->frames, 0, sizeof(SplashImage) * splash->frameCount); + splash->loopCount = 1; - splash->frames[0].bitmapBits = malloc(stride * splash->height); splash->frames[0].delay = 0; + splash->frames[0].bitmapBits = malloc(stride * splash->height); + if (splash->frames[0].bitmapBits == NULL) { + free(splash->frames); + return 0; + } rowStride = cinfo->output_width * cinfo->output_components; buffer = (*cinfo->mem->alloc_sarray) ((j_common_ptr) cinfo, JPOOL_IMAGE, rowStride, 1); + if (buffer == NULL) { + free(splash->frames[0].bitmapBits); + free(splash->frames); + return 0; + } initFormat(&srcFormat, 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000); srcFormat.byteOrder = BYTE_ORDER_LSBFIRST; From ce7e28f3e6e44f6558968cb731d6fb5a90f29d9d Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Tue, 12 May 2009 16:32:34 +0100 Subject: [PATCH 12/70] 6801071: Remote sites can compromise user privacy and possibly hijack web sessions Reviewed-by: jccollet, hawtin --- jdk/make/sun/net/FILES_java.gmk | 1 + jdk/src/share/classes/java/net/Socket.java | 2 +- .../classes/java/net/SocksSocketImpl.java | 25 ++++++++--- jdk/src/share/classes/java/net/URL.java | 2 +- .../classes/sun/net/ApplicationProxy.java | 43 +++++++++++++++++++ .../www/protocol/http/HttpURLConnection.java | 18 +++++--- 6 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 jdk/src/share/classes/sun/net/ApplicationProxy.java diff --git a/jdk/make/sun/net/FILES_java.gmk b/jdk/make/sun/net/FILES_java.gmk index 1ab771a37f1..00b6223b8da 100644 --- a/jdk/make/sun/net/FILES_java.gmk +++ b/jdk/make/sun/net/FILES_java.gmk @@ -24,6 +24,7 @@ # FILES_java = \ + sun/net/ApplicationProxy.java \ sun/net/InetAddressCachePolicy.java \ sun/net/URLCanonicalizer.java \ sun/net/NetworkClient.java \ diff --git a/jdk/src/share/classes/java/net/Socket.java b/jdk/src/share/classes/java/net/Socket.java index 110a6a5f1a9..39dfebd4180 100644 --- a/jdk/src/share/classes/java/net/Socket.java +++ b/jdk/src/share/classes/java/net/Socket.java @@ -118,7 +118,7 @@ class Socket implements java.io.Closeable { if (proxy == null) { throw new IllegalArgumentException("Invalid Proxy"); } - Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : new Proxy(proxy.type(), proxy.address()); + Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy); if (p.type() == Proxy.Type.SOCKS) { SecurityManager security = System.getSecurityManager(); InetSocketAddress epoint = (InetSocketAddress) p.address(); diff --git a/jdk/src/share/classes/java/net/SocksSocketImpl.java b/jdk/src/share/classes/java/net/SocksSocketImpl.java index e73b6c9467e..4561b6e1e56 100644 --- a/jdk/src/share/classes/java/net/SocksSocketImpl.java +++ b/jdk/src/share/classes/java/net/SocksSocketImpl.java @@ -47,6 +47,9 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { private Socket cmdsock = null; private InputStream cmdIn = null; private OutputStream cmdOut = null; + /* true if the Proxy has been set programatically */ + private boolean applicationSetProxy; /* false */ + SocksSocketImpl() { // Nothing needed @@ -64,6 +67,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { // Use getHostString() to avoid reverse lookups server = ad.getHostString(); port = ad.getPort(); + applicationSetProxy = true; } } @@ -165,8 +169,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { throw (IOException) pae.getException(); } } else { - userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + userName = getUserName(); } } if (userName == null) @@ -267,8 +270,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { out.write((endpoint.getPort() >> 8) & 0xff); out.write((endpoint.getPort() >> 0) & 0xff); out.write(endpoint.getAddress().getAddress()); - String userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + String userName = getUserName(); try { out.write(userName.getBytes("ISO-8859-1")); } catch (java.io.UnsupportedEncodingException uee) { @@ -588,8 +590,7 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { out.write((super.getLocalPort() >> 8) & 0xff); out.write((super.getLocalPort() >> 0) & 0xff); out.write(addr1); - String userName = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("user.name")); + String userName = getUserName(); try { out.write(userName.getBytes("ISO-8859-1")); } catch (java.io.UnsupportedEncodingException uee) { @@ -1052,4 +1053,16 @@ class SocksSocketImpl extends PlainSocketImpl implements SocksConsts { super.close(); } + private String getUserName() { + String userName = ""; + if (applicationSetProxy) { + try { + userName = System.getProperty("user.name"); + } catch (SecurityException se) { /* swallow Exception */ } + } else { + userName = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("user.name")); + } + return userName; + } } diff --git a/jdk/src/share/classes/java/net/URL.java b/jdk/src/share/classes/java/net/URL.java index 73818e960d8..33cfe039654 100644 --- a/jdk/src/share/classes/java/net/URL.java +++ b/jdk/src/share/classes/java/net/URL.java @@ -1005,7 +1005,7 @@ public final class URL implements java.io.Serializable { } // Create a copy of Proxy as a security measure - Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : new Proxy(proxy.type(), proxy.address()); + Proxy p = proxy == Proxy.NO_PROXY ? Proxy.NO_PROXY : sun.net.ApplicationProxy.create(proxy); SecurityManager sm = System.getSecurityManager(); if (p.type() != Proxy.Type.DIRECT && sm != null) { InetSocketAddress epoint = (InetSocketAddress) p.address(); diff --git a/jdk/src/share/classes/sun/net/ApplicationProxy.java b/jdk/src/share/classes/sun/net/ApplicationProxy.java new file mode 100644 index 00000000000..2c84e3649e3 --- /dev/null +++ b/jdk/src/share/classes/sun/net/ApplicationProxy.java @@ -0,0 +1,43 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.net; + +import java.net.Proxy; +import java.net.SocketAddress; + +/** + * Proxy wrapper class so that we can determine application set + * proxies by type. + */ +public final class ApplicationProxy extends Proxy { + private ApplicationProxy(Proxy proxy) { + super(proxy.type(), proxy.address()); + } + + public static ApplicationProxy create(Proxy proxy) { + return new ApplicationProxy(proxy); + } +} diff --git a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 6f3250b30eb..9f5d7303abc 100644 --- a/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -575,12 +575,20 @@ public class HttpURLConnection extends java.net.HttpURLConnection { responses = new MessageHeader(); this.handler = handler; instProxy = p; - cookieHandler = java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { + if (instProxy instanceof sun.net.ApplicationProxy) { + /* Application set Proxies should not have access to cookies + * in a secure environment unless explicitly allowed. */ + try { + cookieHandler = CookieHandler.getDefault(); + } catch (SecurityException se) { /* swallow exception */ } + } else { + cookieHandler = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { public CookieHandler run() { - return CookieHandler.getDefault(); - } - }); + return CookieHandler.getDefault(); + } + }); + } cacheHandler = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public ResponseCache run() { From 28848d3300bdbb324ab81bdf4b4d9d14d349ed1a Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Wed, 13 May 2009 13:52:52 +0400 Subject: [PATCH 13/70] 6657625: RmfFileReader/StandardMidiFileWriter.types are public mutable statics (findbugs) Reviewed-by: hawtin --- .../classes/com/sun/media/sound/StandardMidiFileWriter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileWriter.java b/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileWriter.java index 533104fa707..fce29478ada 100644 --- a/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileWriter.java +++ b/jdk/src/share/classes/com/sun/media/sound/StandardMidiFileWriter.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,7 +82,7 @@ public class StandardMidiFileWriter extends MidiFileWriter { /** * MIDI parser types */ - public static final int types[] = { + private static final int types[] = { MIDI_TYPE_0, MIDI_TYPE_1 }; From 00b701fedae519097ea4f8c3b1f5f95c6d2cd117 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Wed, 13 May 2009 14:32:14 +0400 Subject: [PATCH 14/70] 6738524: JDK13Services allows read access to system properties from untrusted code Reviewed-by: hawtin --- .../com/sun/media/sound/JDK13Services.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java index 2b588ceef8d..fd477285770 100644 --- a/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java +++ b/jdk/src/share/classes/com/sun/media/sound/JDK13Services.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,15 @@ import javax.sound.midi.spi.MidiFileWriter; import javax.sound.midi.spi.SoundbankReader; import javax.sound.midi.spi.MidiDeviceProvider; +import javax.sound.midi.Receiver; +import javax.sound.midi.Sequencer; +import javax.sound.midi.Synthesizer; +import javax.sound.midi.Transmitter; +import javax.sound.sampled.Clip; +import javax.sound.sampled.Port; +import javax.sound.sampled.SourceDataLine; +import javax.sound.sampled.TargetDataLine; + /** * JDK13Services uses the Service class in JDK 1.3 @@ -186,6 +195,16 @@ public class JDK13Services { If the property is not set, null is returned. */ private static synchronized String getDefaultProvider(Class typeClass) { + if (!SourceDataLine.class.equals(typeClass) + && !TargetDataLine.class.equals(typeClass) + && !Clip.class.equals(typeClass) + && !Port.class.equals(typeClass) + && !Receiver.class.equals(typeClass) + && !Transmitter.class.equals(typeClass) + && !Synthesizer.class.equals(typeClass) + && !Sequencer.class.equals(typeClass)) { + return null; + } String value; String propertyName = typeClass.getName(); value = JSSecurityManager.getProperty(propertyName); From 272f5e12f9e369834173681913c17b7e5c23a3c3 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Wed, 13 May 2009 14:32:33 +0400 Subject: [PATCH 15/70] 6777448: JDK13Services.getProviders creates instances with full privileges [hawtin, alexp] Reviewed-by: hawtin, alexp --- .../sun/media/sound/JSSecurityManager.java | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java index 253d22c1e93..064e5c4ba04 100644 --- a/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java +++ b/jdk/src/share/classes/com/sun/media/sound/JSSecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -283,28 +283,37 @@ class JSSecurityManager { static List getProviders(final Class providerClass) { - PrivilegedAction action = new PrivilegedAction() { - public Object run() { - List p = new ArrayList(); - Iterator ps = Service.providers(providerClass); - while (ps.hasNext()) { - try { - Object provider = ps.next(); - if (providerClass.isInstance(provider)) { - // $$mp 2003-08-22 - // Always adding at the beginning reverses the - // order of the providers. So we no longer have - // to do this in AudioSystem and MidiSystem. - p.add(0, provider); - } - } catch (Throwable t) { - //$$fb 2002-11-07: do not fail on SPI not found - if (Printer.err) t.printStackTrace(); - } } - return p; + List p = new ArrayList(); + // Service.providers(Class) just creates "lazy" iterator instance, + // so it doesn't require do be called from privileged section + final Iterator ps = Service.providers(providerClass); + + // the iterator's hasNext() method looks through classpath for + // the provider class names, so it requires read permissions + PrivilegedAction hasNextAction = new PrivilegedAction() { + public Boolean run() { + return ps.hasNext(); + } + }; + + while (AccessController.doPrivileged(hasNextAction)) { + try { + // the iterator's next() method creates instances of the + // providers and it should be called in the current security + // context + Object provider = ps.next(); + if (providerClass.isInstance(provider)) { + // $$mp 2003-08-22 + // Always adding at the beginning reverses the + // order of the providers. So we no longer have + // to do this in AudioSystem and MidiSystem. + p.add(0, provider); } - }; - List providers = (List) AccessController.doPrivileged(action); - return providers; + } catch (Throwable t) { + //$$fb 2002-11-07: do not fail on SPI not found + if (Printer.err) t.printStackTrace(); + } + } + return p; } } From 0681d1454c1758bbb76ba3073b2f4116a66109da Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Thu, 18 Jun 2009 14:08:07 +0400 Subject: [PATCH 16/70] 6660049: Synth Region.uiToRegionMap/lowerCaseNameMap are mutable statics Reviewed-by: hawtin --- .../javax/swing/plaf/synth/Region.java | 288 ++++++++++-------- .../javax/swing/plaf/synth/Test6660049.java | 123 ++++++++ 2 files changed, 287 insertions(+), 124 deletions(-) create mode 100644 jdk/test/javax/swing/plaf/synth/Test6660049.java diff --git a/jdk/src/share/classes/javax/swing/plaf/synth/Region.java b/jdk/src/share/classes/javax/swing/plaf/synth/Region.java index c7de782ba59..1ecd999896d 100644 --- a/jdk/src/share/classes/javax/swing/plaf/synth/Region.java +++ b/jdk/src/share/classes/javax/swing/plaf/synth/Region.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,13 @@ */ package javax.swing.plaf.synth; -import javax.swing.*; -import java.util.*; +import sun.awt.AppContext; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import javax.swing.JComponent; +import javax.swing.UIDefaults; /** * A distinct rendering area of a Swing component. A component may @@ -67,8 +72,8 @@ import java.util.*; * @author Scott Violet */ public class Region { - private static final Map uiToRegionMap = new HashMap(); - private static final Map lowerCaseNameMap = new HashMap(); + private static final Object UI_TO_REGION_MAP_KEY = new Object(); + private static final Object LOWER_CASE_NAME_MAP_KEY = new Object(); /** * ArrowButton's are special types of buttons that also render a @@ -77,396 +82,433 @@ public class Region { * To bind a style to this Region use the name * ArrowButton. */ - public static final Region ARROW_BUTTON = new Region("ArrowButton", - "ArrowButtonUI"); + public static final Region ARROW_BUTTON = new Region("ArrowButton", false); /** * Button region. To bind a style to this Region use the name * Button. */ - public static final Region BUTTON = new Region("Button", - "ButtonUI"); + public static final Region BUTTON = new Region("Button", false); /** * CheckBox region. To bind a style to this Region use the name * CheckBox. */ - public static final Region CHECK_BOX = new Region("CheckBox", - "CheckBoxUI"); + public static final Region CHECK_BOX = new Region("CheckBox", false); /** * CheckBoxMenuItem region. To bind a style to this Region use * the name CheckBoxMenuItem. */ - public static final Region CHECK_BOX_MENU_ITEM = new Region( - "CheckBoxMenuItem", "CheckBoxMenuItemUI"); + public static final Region CHECK_BOX_MENU_ITEM = new Region("CheckBoxMenuItem", false); /** * ColorChooser region. To bind a style to this Region use * the name ColorChooser. */ - public static final Region COLOR_CHOOSER = new Region( - "ColorChooser", "ColorChooserUI"); + public static final Region COLOR_CHOOSER = new Region("ColorChooser", false); /** * ComboBox region. To bind a style to this Region use * the name ComboBox. */ - public static final Region COMBO_BOX = new Region( - "ComboBox", "ComboBoxUI"); + public static final Region COMBO_BOX = new Region("ComboBox", false); /** * DesktopPane region. To bind a style to this Region use * the name DesktopPane. */ - public static final Region DESKTOP_PANE = new Region("DesktopPane", - "DesktopPaneUI"); + public static final Region DESKTOP_PANE = new Region("DesktopPane", false); + /** * DesktopIcon region. To bind a style to this Region use * the name DesktopIcon. */ - public static final Region DESKTOP_ICON = new Region("DesktopIcon", - "DesktopIconUI"); + public static final Region DESKTOP_ICON = new Region("DesktopIcon", false); /** * EditorPane region. To bind a style to this Region use * the name EditorPane. */ - public static final Region EDITOR_PANE = new Region("EditorPane", - "EditorPaneUI"); + public static final Region EDITOR_PANE = new Region("EditorPane", false); /** * FileChooser region. To bind a style to this Region use * the name FileChooser. */ - public static final Region FILE_CHOOSER = new Region("FileChooser", - "FileChooserUI"); + public static final Region FILE_CHOOSER = new Region("FileChooser", false); /** * FormattedTextField region. To bind a style to this Region use * the name FormattedTextField. */ - public static final Region FORMATTED_TEXT_FIELD = new Region( - "FormattedTextField", "FormattedTextFieldUI"); + public static final Region FORMATTED_TEXT_FIELD = new Region("FormattedTextField", false); /** * InternalFrame region. To bind a style to this Region use * the name InternalFrame. */ - public static final Region INTERNAL_FRAME = new Region("InternalFrame", - "InternalFrameUI"); + public static final Region INTERNAL_FRAME = new Region("InternalFrame", false); + /** * TitlePane of an InternalFrame. The TitlePane typically * shows a menu, title, widgets to manipulate the internal frame. * To bind a style to this Region use the name * InternalFrameTitlePane. */ - public static final Region INTERNAL_FRAME_TITLE_PANE = - new Region("InternalFrameTitlePane", - "InternalFrameTitlePaneUI"); + public static final Region INTERNAL_FRAME_TITLE_PANE = new Region("InternalFrameTitlePane", false); /** * Label region. To bind a style to this Region use the name * Label. */ - public static final Region LABEL = new Region("Label", "LabelUI"); + public static final Region LABEL = new Region("Label", false); /** * List region. To bind a style to this Region use the name * List. */ - public static final Region LIST = new Region("List", "ListUI"); + public static final Region LIST = new Region("List", false); /** * Menu region. To bind a style to this Region use the name * Menu. */ - public static final Region MENU = new Region("Menu", "MenuUI"); + public static final Region MENU = new Region("Menu", false); /** * MenuBar region. To bind a style to this Region use the name * MenuBar. */ - public static final Region MENU_BAR = new Region("MenuBar", "MenuBarUI"); + public static final Region MENU_BAR = new Region("MenuBar", false); /** * MenuItem region. To bind a style to this Region use the name * MenuItem. */ - public static final Region MENU_ITEM = new Region("MenuItem","MenuItemUI"); + public static final Region MENU_ITEM = new Region("MenuItem", false); /** * Accelerator region of a MenuItem. To bind a style to this * Region use the name MenuItemAccelerator. */ - public static final Region MENU_ITEM_ACCELERATOR = new Region( - "MenuItemAccelerator"); + public static final Region MENU_ITEM_ACCELERATOR = new Region("MenuItemAccelerator", true); /** * OptionPane region. To bind a style to this Region use * the name OptionPane. */ - public static final Region OPTION_PANE = new Region("OptionPane", - "OptionPaneUI"); + public static final Region OPTION_PANE = new Region("OptionPane", false); /** * Panel region. To bind a style to this Region use the name * Panel. */ - public static final Region PANEL = new Region("Panel", "PanelUI"); + public static final Region PANEL = new Region("Panel", false); /** * PasswordField region. To bind a style to this Region use * the name PasswordField. */ - public static final Region PASSWORD_FIELD = new Region("PasswordField", - "PasswordFieldUI"); + public static final Region PASSWORD_FIELD = new Region("PasswordField", false); /** * PopupMenu region. To bind a style to this Region use * the name PopupMenu. */ - public static final Region POPUP_MENU = new Region("PopupMenu", - "PopupMenuUI"); + public static final Region POPUP_MENU = new Region("PopupMenu", false); /** * PopupMenuSeparator region. To bind a style to this Region * use the name PopupMenuSeparator. */ - public static final Region POPUP_MENU_SEPARATOR = new Region( - "PopupMenuSeparator", "PopupMenuSeparatorUI"); + public static final Region POPUP_MENU_SEPARATOR = new Region("PopupMenuSeparator", false); /** * ProgressBar region. To bind a style to this Region * use the name ProgressBar. */ - public static final Region PROGRESS_BAR = new Region("ProgressBar", - "ProgressBarUI"); + public static final Region PROGRESS_BAR = new Region("ProgressBar", false); /** * RadioButton region. To bind a style to this Region * use the name RadioButton. */ - public static final Region RADIO_BUTTON = new Region( - "RadioButton", "RadioButtonUI"); + public static final Region RADIO_BUTTON = new Region("RadioButton", false); /** * RegionButtonMenuItem region. To bind a style to this Region * use the name RadioButtonMenuItem. */ - public static final Region RADIO_BUTTON_MENU_ITEM = new Region( - "RadioButtonMenuItem", "RadioButtonMenuItemUI"); + public static final Region RADIO_BUTTON_MENU_ITEM = new Region("RadioButtonMenuItem", false); /** * RootPane region. To bind a style to this Region use * the name RootPane. */ - public static final Region ROOT_PANE = new Region("RootPane", - "RootPaneUI"); + public static final Region ROOT_PANE = new Region("RootPane", false); /** * ScrollBar region. To bind a style to this Region use * the name ScrollBar. */ - public static final Region SCROLL_BAR = new Region("ScrollBar", - "ScrollBarUI"); + public static final Region SCROLL_BAR = new Region("ScrollBar", false); + /** * Track of the ScrollBar. To bind a style to this Region use * the name ScrollBarTrack. */ - public static final Region SCROLL_BAR_TRACK = new Region("ScrollBarTrack"); + public static final Region SCROLL_BAR_TRACK = new Region("ScrollBarTrack", true); + /** * Thumb of the ScrollBar. The thumb is the region of the ScrollBar * that gives a graphical depiction of what percentage of the View is * currently visible. To bind a style to this Region use * the name ScrollBarThumb. */ - public static final Region SCROLL_BAR_THUMB = new Region("ScrollBarThumb"); + public static final Region SCROLL_BAR_THUMB = new Region("ScrollBarThumb", true); /** * ScrollPane region. To bind a style to this Region use * the name ScrollPane. */ - public static final Region SCROLL_PANE = new Region("ScrollPane", - "ScrollPaneUI"); + public static final Region SCROLL_PANE = new Region("ScrollPane", false); /** * Separator region. To bind a style to this Region use * the name Separator. */ - public static final Region SEPARATOR = new Region("Separator", - "SeparatorUI"); + public static final Region SEPARATOR = new Region("Separator", false); /** * Slider region. To bind a style to this Region use * the name Slider. */ - public static final Region SLIDER = new Region("Slider", "SliderUI"); + public static final Region SLIDER = new Region("Slider", false); + /** * Track of the Slider. To bind a style to this Region use * the name SliderTrack. */ - public static final Region SLIDER_TRACK = new Region("SliderTrack"); + public static final Region SLIDER_TRACK = new Region("SliderTrack", true); + /** * Thumb of the Slider. The thumb of the Slider identifies the current * value. To bind a style to this Region use the name * SliderThumb. */ - public static final Region SLIDER_THUMB = new Region("SliderThumb"); + public static final Region SLIDER_THUMB = new Region("SliderThumb", true); /** * Spinner region. To bind a style to this Region use the name * Spinner. */ - public static final Region SPINNER = new Region("Spinner", "SpinnerUI"); + public static final Region SPINNER = new Region("Spinner", false); /** * SplitPane region. To bind a style to this Region use the name * SplitPane. */ - public static final Region SPLIT_PANE = new Region("SplitPane", - "SplitPaneUI"); + public static final Region SPLIT_PANE = new Region("SplitPane", false); /** * Divider of the SplitPane. To bind a style to this Region * use the name SplitPaneDivider. */ - public static final Region SPLIT_PANE_DIVIDER = new Region( - "SplitPaneDivider"); + public static final Region SPLIT_PANE_DIVIDER = new Region("SplitPaneDivider", true); /** * TabbedPane region. To bind a style to this Region use * the name TabbedPane. */ - public static final Region TABBED_PANE = new Region("TabbedPane", - "TabbedPaneUI"); + public static final Region TABBED_PANE = new Region("TabbedPane", false); + /** * Region of a TabbedPane for one tab. To bind a style to this * Region use the name TabbedPaneTab. */ - public static final Region TABBED_PANE_TAB = new Region("TabbedPaneTab"); + public static final Region TABBED_PANE_TAB = new Region("TabbedPaneTab", true); + /** * Region of a TabbedPane containing the tabs. To bind a style to this * Region use the name TabbedPaneTabArea. */ - public static final Region TABBED_PANE_TAB_AREA = - new Region("TabbedPaneTabArea"); + public static final Region TABBED_PANE_TAB_AREA = new Region("TabbedPaneTabArea", true); + /** * Region of a TabbedPane containing the content. To bind a style to this * Region use the name TabbedPaneContent. */ - public static final Region TABBED_PANE_CONTENT = - new Region("TabbedPaneContent"); + public static final Region TABBED_PANE_CONTENT = new Region("TabbedPaneContent", true); /** * Table region. To bind a style to this Region use * the name Table. */ - public static final Region TABLE = new Region("Table", "TableUI"); + public static final Region TABLE = new Region("Table", false); /** * TableHeader region. To bind a style to this Region use * the name TableHeader. */ - public static final Region TABLE_HEADER = new Region("TableHeader", - "TableHeaderUI"); + public static final Region TABLE_HEADER = new Region("TableHeader", false); + /** * TextArea region. To bind a style to this Region use * the name TextArea. */ - public static final Region TEXT_AREA = new Region("TextArea", - "TextAreaUI"); + public static final Region TEXT_AREA = new Region("TextArea", false); /** * TextField region. To bind a style to this Region use * the name TextField. */ - public static final Region TEXT_FIELD = new Region("TextField", - "TextFieldUI"); + public static final Region TEXT_FIELD = new Region("TextField", false); /** * TextPane region. To bind a style to this Region use * the name TextPane. */ - public static final Region TEXT_PANE = new Region("TextPane", - "TextPaneUI"); + public static final Region TEXT_PANE = new Region("TextPane", false); /** * ToggleButton region. To bind a style to this Region use * the name ToggleButton. */ - public static final Region TOGGLE_BUTTON = new Region("ToggleButton", - "ToggleButtonUI"); + public static final Region TOGGLE_BUTTON = new Region("ToggleButton", false); /** * ToolBar region. To bind a style to this Region use * the name ToolBar. */ - public static final Region TOOL_BAR = new Region("ToolBar", "ToolBarUI"); + public static final Region TOOL_BAR = new Region("ToolBar", false); + /** * Region of the ToolBar containing the content. To bind a style to this * Region use the name ToolBarContent. */ - public static final Region TOOL_BAR_CONTENT = new Region("ToolBarContent"); + public static final Region TOOL_BAR_CONTENT = new Region("ToolBarContent", true); + /** * Region for the Window containing the ToolBar. To bind a style to this * Region use the name ToolBarDragWindow. */ - public static final Region TOOL_BAR_DRAG_WINDOW = new Region( - "ToolBarDragWindow", null, false); + public static final Region TOOL_BAR_DRAG_WINDOW = new Region("ToolBarDragWindow", false); /** * ToolTip region. To bind a style to this Region use * the name ToolTip. */ - public static final Region TOOL_TIP = new Region("ToolTip", "ToolTipUI"); + public static final Region TOOL_TIP = new Region("ToolTip", false); /** * ToolBar separator region. To bind a style to this Region use * the name ToolBarSeparator. */ - public static final Region TOOL_BAR_SEPARATOR = new Region( - "ToolBarSeparator", "ToolBarSeparatorUI"); + public static final Region TOOL_BAR_SEPARATOR = new Region("ToolBarSeparator", false); /** * Tree region. To bind a style to this Region use the name * Tree. */ - public static final Region TREE = new Region("Tree", "TreeUI"); + public static final Region TREE = new Region("Tree", false); + /** * Region of the Tree for one cell. To bind a style to this * Region use the name TreeCell. */ - public static final Region TREE_CELL = new Region("TreeCell"); + public static final Region TREE_CELL = new Region("TreeCell", true); /** * Viewport region. To bind a style to this Region use * the name Viewport. */ - public static final Region VIEWPORT = new Region("Viewport", "ViewportUI"); + public static final Region VIEWPORT = new Region("Viewport", false); + private static Map getUItoRegionMap() { + AppContext context = AppContext.getAppContext(); + Map map = (Map) context.get(UI_TO_REGION_MAP_KEY); + if (map == null) { + map = new HashMap(); + map.put("ArrowButtonUI", ARROW_BUTTON); + map.put("ButtonUI", BUTTON); + map.put("CheckBoxUI", CHECK_BOX); + map.put("CheckBoxMenuItemUI", CHECK_BOX_MENU_ITEM); + map.put("ColorChooserUI", COLOR_CHOOSER); + map.put("ComboBoxUI", COMBO_BOX); + map.put("DesktopPaneUI", DESKTOP_PANE); + map.put("DesktopIconUI", DESKTOP_ICON); + map.put("EditorPaneUI", EDITOR_PANE); + map.put("FileChooserUI", FILE_CHOOSER); + map.put("FormattedTextFieldUI", FORMATTED_TEXT_FIELD); + map.put("InternalFrameUI", INTERNAL_FRAME); + map.put("InternalFrameTitlePaneUI", INTERNAL_FRAME_TITLE_PANE); + map.put("LabelUI", LABEL); + map.put("ListUI", LIST); + map.put("MenuUI", MENU); + map.put("MenuBarUI", MENU_BAR); + map.put("MenuItemUI", MENU_ITEM); + map.put("OptionPaneUI", OPTION_PANE); + map.put("PanelUI", PANEL); + map.put("PasswordFieldUI", PASSWORD_FIELD); + map.put("PopupMenuUI", POPUP_MENU); + map.put("PopupMenuSeparatorUI", POPUP_MENU_SEPARATOR); + map.put("ProgressBarUI", PROGRESS_BAR); + map.put("RadioButtonUI", RADIO_BUTTON); + map.put("RadioButtonMenuItemUI", RADIO_BUTTON_MENU_ITEM); + map.put("RootPaneUI", ROOT_PANE); + map.put("ScrollBarUI", SCROLL_BAR); + map.put("ScrollPaneUI", SCROLL_PANE); + map.put("SeparatorUI", SEPARATOR); + map.put("SliderUI", SLIDER); + map.put("SpinnerUI", SPINNER); + map.put("SplitPaneUI", SPLIT_PANE); + map.put("TabbedPaneUI", TABBED_PANE); + map.put("TableUI", TABLE); + map.put("TableHeaderUI", TABLE_HEADER); + map.put("TextAreaUI", TEXT_AREA); + map.put("TextFieldUI", TEXT_FIELD); + map.put("TextPaneUI", TEXT_PANE); + map.put("ToggleButtonUI", TOGGLE_BUTTON); + map.put("ToolBarUI", TOOL_BAR); + map.put("ToolTipUI", TOOL_TIP); + map.put("ToolBarSeparatorUI", TOOL_BAR_SEPARATOR); + map.put("TreeUI", TREE); + map.put("ViewportUI", VIEWPORT); + context.put(UI_TO_REGION_MAP_KEY, map); + } + return map; + } - private String name; - private boolean subregion; - + private static Map getLowerCaseNameMap() { + AppContext context = AppContext.getAppContext(); + Map map = (Map) context.get(LOWER_CASE_NAME_MAP_KEY); + if (map == null) { + map = new HashMap(); + context.put(LOWER_CASE_NAME_MAP_KEY, map); + } + return map; + } static Region getRegion(JComponent c) { - return uiToRegionMap.get(c.getUIClassID()); + return getUItoRegionMap().get(c.getUIClassID()); } static void registerUIs(UIDefaults table) { - for (String key : uiToRegionMap.keySet()) { + for (Object key : getUItoRegionMap().keySet()) { table.put(key, "javax.swing.plaf.synth.SynthLookAndFeel"); } } + private final String name; + private final boolean subregion; - Region(String name) { - this(name, null, true); - } - - Region(String name, String ui) { - this(name, ui, false); + private Region(String name, boolean subregion) { + if (name == null) { + throw new NullPointerException("You must specify a non-null name"); + } + this.name = name; + this.subregion = subregion; } /** @@ -481,14 +523,10 @@ public class Region { * @param subregion Whether or not this is a subregion. */ protected Region(String name, String ui, boolean subregion) { - if (name == null) { - throw new NullPointerException("You must specify a non-null name"); - } - this.name = name; + this(name, subregion); if (ui != null) { - uiToRegionMap.put(ui, this); + getUItoRegionMap().put(ui, this); } - this.subregion = subregion; } /** @@ -514,16 +552,17 @@ public class Region { /** * Returns the name, in lowercase. + * + * @return lower case representation of the name of the Region */ String getLowerCaseName() { - synchronized(lowerCaseNameMap) { - String lowerCaseName = lowerCaseNameMap.get(this); - if (lowerCaseName == null) { - lowerCaseName = getName().toLowerCase(); - lowerCaseNameMap.put(this, lowerCaseName); - } - return lowerCaseName; + Map lowerCaseNameMap = getLowerCaseNameMap(); + String lowerCaseName = lowerCaseNameMap.get(this); + if (lowerCaseName == null) { + lowerCaseName = name.toLowerCase(Locale.ENGLISH); + lowerCaseNameMap.put(this, lowerCaseName); } + return lowerCaseName; } /** @@ -531,6 +570,7 @@ public class Region { * * @return name of the Region. */ + @Override public String toString() { return name; } diff --git a/jdk/test/javax/swing/plaf/synth/Test6660049.java b/jdk/test/javax/swing/plaf/synth/Test6660049.java new file mode 100644 index 00000000000..466453a8a60 --- /dev/null +++ b/jdk/test/javax/swing/plaf/synth/Test6660049.java @@ -0,0 +1,123 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6660049 6849518 + * @summary Tests the Region initialization + * @author Sergey Malenkov + */ + +import sun.awt.SunToolkit; + +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.SwingUtilities; +import javax.swing.plaf.synth.Region; +import javax.swing.plaf.synth.SynthLookAndFeel; + +public class Test6660049 implements Runnable { + public static void main(String[] args) { + SwingUtilities.invokeLater(new Test6660049( + javax.swing.JButton.class, + javax.swing.JCheckBox.class, + javax.swing.JCheckBoxMenuItem.class, + javax.swing.JColorChooser.class, + javax.swing.JComboBox.class, + javax.swing.JDesktopPane.class, + javax.swing.JEditorPane.class, + javax.swing.JFileChooser.class, + javax.swing.JFormattedTextField.class, + javax.swing.JInternalFrame.class, + javax.swing.JLabel.class, + javax.swing.JList.class, + javax.swing.JMenu.class, + javax.swing.JMenuBar.class, + javax.swing.JMenuItem.class, + javax.swing.JOptionPane.class, + javax.swing.JPanel.class, + javax.swing.JPasswordField.class, + javax.swing.JPopupMenu.class, + javax.swing.JProgressBar.class, + javax.swing.JRadioButton.class, + javax.swing.JRadioButtonMenuItem.class, + javax.swing.JRootPane.class, + javax.swing.JScrollBar.class, + javax.swing.JScrollPane.class, + javax.swing.JSeparator.class, + javax.swing.JSlider.class, + javax.swing.JSpinner.class, + javax.swing.JSplitPane.class, + javax.swing.JTabbedPane.class, + javax.swing.JTable.class, + javax.swing.JTextArea.class, + javax.swing.JTextField.class, + javax.swing.JTextPane.class, + javax.swing.JToggleButton.class, + javax.swing.JToolBar.class, + javax.swing.JToolTip.class, + javax.swing.JTree.class, + javax.swing.JViewport.class, + javax.swing.table.JTableHeader.class)); + } + + private final Class[] types; + private final Region region; + + private Test6660049(Class... types) { + this.types = types; + run(); + + this.region = new Region("Button", "ButtonUI", true) { + @Override + public String getName() { + throw new Error("6660049: exploit is available"); + } + }; + } + + public void run() { + if (this.region != null) { + SunToolkit.createNewAppContext(); + } + for (Class type : this.types) { + Region region = getRegion(type); + if (region == null) { + throw new Error("6849518: region is not initialized"); + } + } + getRegion(JButton.class).getName(); + } + + private static Region getRegion(Class type) { + try { + return SynthLookAndFeel.getRegion(type.newInstance()); + } + catch (IllegalAccessException exception) { + throw new Error("unexpected exception", exception); + } + catch (InstantiationException exception) { + throw new Error("unexpected exception", exception); + } + } +} From 6b90310fed55e58b749b5d4b1fbbdc67ef227eca Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Mon, 22 Jun 2009 13:36:37 -0700 Subject: [PATCH 17/70] 6656610: AccessibleResourceBundle.getContents exposes mutable static (findbugs) Reviewed-by: hawtin --- .../accessibility/AccessibleResourceBundle.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java b/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java index b5f23e199fa..ec27c756bde 100644 --- a/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java +++ b/jdk/src/share/classes/javax/accessibility/AccessibleResourceBundle.java @@ -44,15 +44,11 @@ public class AccessibleResourceBundle extends ListResourceBundle { * localized display strings. */ public Object[][] getContents() { - return contents; - } + // The table holding the mapping between the programmatic keys + // and the display strings for the en_US locale. + return new Object[][] { - /** - * The table holding the mapping between the programmatic keys - * and the display strings for the en_US locale. - */ - static final Object[][] contents = { - // LOCALIZE THIS + // LOCALIZE THIS // Role names // { "application","application" }, // { "border","border" }, @@ -151,5 +147,6 @@ public class AccessibleResourceBundle extends ListResourceBundle { { "vertical","vertical" }, { "horizontal","horizontal" } // END OF MATERIAL TO LOCALIZE - }; + }; + } } From 68d0756ea67b3c8655a28193e6725e07d3b8554b Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Tue, 23 Jun 2009 13:54:36 -0400 Subject: [PATCH 18/70] 6824440: XML Signature HMAC issue Reviewed-by: asaha --- .../implementations/IntegrityHmac.java | 76 +++++++---- .../internal/dom/DOMHMACSignatureMethod.java | 53 ++++---- .../xml/internal/security/TruncateHMAC.java | 118 ++++++++++++++++++ ...enveloping-hmac-sha1-trunclen-0-attack.xml | 16 +++ ...enveloping-hmac-sha1-trunclen-8-attack.xml | 17 +++ .../xml/crypto/dsig/GenerationTests.java | 16 ++- .../xml/crypto/dsig/ValidationTests.java | 39 +++++- ...enveloping-hmac-sha1-trunclen-0-attack.xml | 16 +++ ...enveloping-hmac-sha1-trunclen-8-attack.xml | 17 +++ 9 files changed, 311 insertions(+), 57 deletions(-) create mode 100644 jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java create mode 100644 jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-0-attack.xml create mode 100644 jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-8-attack.xml create mode 100644 jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-0-attack.xml create mode 100644 jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-8-attack.xml diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java index d3495bb567f..85cc9e38a68 100644 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java +++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java @@ -60,8 +60,14 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { */ public abstract String engineGetURI(); + /** + * Returns the output length of the hash/digest. + */ + abstract int getDigestLength(); + /** Field _macAlgorithm */ private Mac _macAlgorithm = null; + private boolean _HMACOutputLengthSet = false; /** Field _HMACOutputLength */ int _HMACOutputLength = 0; @@ -115,14 +121,16 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { throws XMLSignatureException { try { - byte[] completeResult = this._macAlgorithm.doFinal(); - - if ((this._HMACOutputLength == 0) || (this._HMACOutputLength >= 160)) { + if (this._HMACOutputLengthSet && this._HMACOutputLength < getDigestLength()) { + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "HMACOutputLength must not be less than " + getDigestLength()); + } + throw new XMLSignatureException("errorMessages.XMLSignatureException"); + } else { + byte[] completeResult = this._macAlgorithm.doFinal(); return MessageDigestAlgorithm.isEqual(completeResult, signature); } - byte[] stripped = IntegrityHmac.reduceBitLength(completeResult, - this._HMACOutputLength); - return MessageDigestAlgorithm.isEqual(stripped, signature); } catch (IllegalStateException ex) { throw new XMLSignatureException("empty", ex); } @@ -176,14 +184,15 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { protected byte[] engineSign() throws XMLSignatureException { try { - byte[] completeResult = this._macAlgorithm.doFinal(); - - if ((this._HMACOutputLength == 0) || (this._HMACOutputLength >= 160)) { - return completeResult; + if (this._HMACOutputLengthSet && this._HMACOutputLength < getDigestLength()) { + if (log.isLoggable(java.util.logging.Level.FINE)) { + log.log(java.util.logging.Level.FINE, + "HMACOutputLength must not be less than " + getDigestLength()); + } + throw new XMLSignatureException("errorMessages.XMLSignatureException"); + } else { + return this._macAlgorithm.doFinal(); } - return IntegrityHmac.reduceBitLength(completeResult, - this._HMACOutputLength); - } catch (IllegalStateException ex) { throw new XMLSignatureException("empty", ex); } @@ -361,6 +370,7 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { */ protected void engineSetHMACOutputLength(int HMACOutputLength) { this._HMACOutputLength = HMACOutputLength; + this._HMACOutputLengthSet = true; } /** @@ -376,12 +386,13 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { throw new IllegalArgumentException("element null"); } - Text hmaclength =XMLUtils.selectDsNodeText(element.getFirstChild(), - Constants._TAG_HMACOUTPUTLENGTH,0); + Text hmaclength =XMLUtils.selectDsNodeText(element.getFirstChild(), + Constants._TAG_HMACOUTPUTLENGTH,0); - if (hmaclength != null) { - this._HMACOutputLength = Integer.parseInt(hmaclength.getData()); - } + if (hmaclength != null) { + this._HMACOutputLength = Integer.parseInt(hmaclength.getData()); + this._HMACOutputLengthSet = true; + } } @@ -390,14 +401,13 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { * * @param element */ - public void engineAddContextToElement(Element element) - { + public void engineAddContextToElement(Element element) { if (element == null) { throw new IllegalArgumentException("null element"); } - if (this._HMACOutputLength != 0) { + if (this._HMACOutputLengthSet) { Document doc = element.getOwnerDocument(); Element HMElem = XMLUtils.createElementInSignatureSpace(doc, Constants._TAG_HMACOUTPUTLENGTH); @@ -436,6 +446,10 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { public String engineGetURI() { return XMLSignature.ALGO_ID_MAC_HMAC_SHA1; } + + int getDigestLength() { + return 160; + } } /** @@ -463,6 +477,10 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { public String engineGetURI() { return XMLSignature.ALGO_ID_MAC_HMAC_SHA256; } + + int getDigestLength() { + return 256; + } } /** @@ -490,6 +508,10 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { public String engineGetURI() { return XMLSignature.ALGO_ID_MAC_HMAC_SHA384; } + + int getDigestLength() { + return 384; + } } /** @@ -517,6 +539,10 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { public String engineGetURI() { return XMLSignature.ALGO_ID_MAC_HMAC_SHA512; } + + int getDigestLength() { + return 512; + } } /** @@ -544,6 +570,10 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { public String engineGetURI() { return XMLSignature.ALGO_ID_MAC_HMAC_RIPEMD160; } + + int getDigestLength() { + return 160; + } } /** @@ -571,5 +601,9 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { public String engineGetURI() { return XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5; } + + int getDigestLength() { + return 128; + } } } diff --git a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java index 5a9000c898c..482283b616e 100644 --- a/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java +++ b/jdk/src/share/classes/org/jcp/xml/dsig/internal/dom/DOMHMACSignatureMethod.java @@ -19,7 +19,7 @@ * */ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All rights reserved. */ /* * $Id: DOMHMACSignatureMethod.java,v 1.2 2008/07/24 15:20:32 mullan Exp $ @@ -58,6 +58,7 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { Logger.getLogger("org.jcp.xml.dsig.internal.dom"); private Mac hmac; private int outputLength; + private boolean outputLengthSet; /** * Creates a DOMHMACSignatureMethod with the specified params @@ -87,6 +88,7 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { ("params must be of type HMACParameterSpec"); } outputLength = ((HMACParameterSpec) params).getOutputLength(); + outputLengthSet = true; if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "Setting outputLength from HMACParameterSpec to: " @@ -101,6 +103,7 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { throws MarshalException { outputLength = new Integer (paramsElem.getFirstChild().getNodeValue()).intValue(); + outputLengthSet = true; if (log.isLoggable(Level.FINE)) { log.log(Level.FINE, "unmarshalled outputLength: " + outputLength); } @@ -135,23 +138,13 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { throw new XMLSignatureException(nsae); } } - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "outputLength = " + outputLength); + if (outputLengthSet && outputLength < getDigestLength()) { + throw new XMLSignatureException + ("HMACOutputLength must not be less than " + getDigestLength()); } hmac.init((SecretKey) key); si.canonicalize(context, new MacOutputStream(hmac)); byte[] result = hmac.doFinal(); - if (log.isLoggable(Level.FINE)) { - log.log(Level.FINE, "resultLength = " + result.length); - } - if (outputLength != -1) { - int byteLength = outputLength/8; - if (result.length > byteLength) { - byte[] truncated = new byte[byteLength]; - System.arraycopy(result, 0, truncated, 0, byteLength); - result = truncated; - } - } return MessageDigest.isEqual(sig, result); } @@ -171,18 +164,13 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { throw new XMLSignatureException(nsae); } } + if (outputLengthSet && outputLength < getDigestLength()) { + throw new XMLSignatureException + ("HMACOutputLength must not be less than " + getDigestLength()); + } hmac.init((SecretKey) key); si.canonicalize(context, new MacOutputStream(hmac)); - byte[] result = hmac.doFinal(); - if (outputLength != -1) { - int byteLength = outputLength/8; - if (result.length > byteLength) { - byte[] truncated = new byte[byteLength]; - System.arraycopy(result, 0, truncated, 0, byteLength); - result = truncated; - } - } - return result; + return hmac.doFinal(); } boolean paramsEqual(AlgorithmParameterSpec spec) { @@ -197,6 +185,11 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { return (outputLength == ospec.getOutputLength()); } + /** + * Returns the output length of the hash/digest. + */ + abstract int getDigestLength(); + static final class SHA1 extends DOMHMACSignatureMethod { SHA1(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { @@ -211,6 +204,9 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { String getSignatureAlgorithm() { return "HmacSHA1"; } + int getDigestLength() { + return 160; + } } static final class SHA256 extends DOMHMACSignatureMethod { @@ -227,6 +223,9 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { String getSignatureAlgorithm() { return "HmacSHA256"; } + int getDigestLength() { + return 256; + } } static final class SHA384 extends DOMHMACSignatureMethod { @@ -243,6 +242,9 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { String getSignatureAlgorithm() { return "HmacSHA384"; } + int getDigestLength() { + return 384; + } } static final class SHA512 extends DOMHMACSignatureMethod { @@ -259,5 +261,8 @@ public abstract class DOMHMACSignatureMethod extends DOMSignatureMethod { String getSignatureAlgorithm() { return "HmacSHA512"; } + int getDigestLength() { + return 512; + } } } diff --git a/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java b/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java new file mode 100644 index 00000000000..ebb424de328 --- /dev/null +++ b/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java @@ -0,0 +1,118 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test %I% %E% + * @bug 6824440 + * @summary Check that Apache XMLSec APIs will not accept HMAC truncation + * lengths less than minimum bound + * @compile -XDignore.symbol.file TruncateHMAC.java + * @run main TruncateHMAC + */ + +import java.io.File; +import javax.crypto.SecretKey; +import javax.xml.parsers.DocumentBuilderFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import com.sun.org.apache.xml.internal.security.Init; +import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; +import com.sun.org.apache.xml.internal.security.signature.XMLSignature; +import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; +import com.sun.org.apache.xml.internal.security.utils.Constants; + + +public class TruncateHMAC { + + private final static String DIR = System.getProperty("test.src", "."); + private static DocumentBuilderFactory dbf = null; + private static boolean atLeastOneFailed = false; + + public static void main(String[] args) throws Exception { + + Init.init(); + dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + validate("signature-enveloping-hmac-sha1-trunclen-0-attack.xml"); + validate("signature-enveloping-hmac-sha1-trunclen-8-attack.xml"); + generate_hmac_sha1_40(); + + if (atLeastOneFailed) { + throw new Exception + ("At least one signature did not validate as expected"); + } + } + + private static void validate(String data) throws Exception { + System.out.println("Validating " + data); + File file = new File(DIR, data); + + Document doc = dbf.newDocumentBuilder().parse(file); + NodeList nl = + doc.getElementsByTagNameNS(Constants.SignatureSpecNS, "Signature"); + if (nl.getLength() == 0) { + throw new Exception("Couldn't find signature Element"); + } + Element sigElement = (Element) nl.item(0); + XMLSignature signature = new XMLSignature + (sigElement, file.toURI().toString()); + SecretKey sk = signature.createSecretKey("secret".getBytes("ASCII")); + try { + System.out.println + ("Validation status: " + signature.checkSignatureValue(sk)); + System.out.println("FAILED"); + atLeastOneFailed = true; + } catch (XMLSignatureException xse) { + System.out.println(xse.getMessage()); + System.out.println("PASSED"); + } + } + + private static void generate_hmac_sha1_40() throws Exception { + System.out.println("Generating "); + + Document doc = dbf.newDocumentBuilder().newDocument(); + XMLSignature sig = new XMLSignature + (doc, null, XMLSignature.ALGO_ID_MAC_HMAC_SHA1, 40, + Canonicalizer.ALGO_ID_C14N_OMIT_COMMENTS); + try { + sig.sign(getSecretKey("secret".getBytes("ASCII"))); + System.out.println("FAILED"); + atLeastOneFailed = true; + } catch (XMLSignatureException xse) { + System.out.println(xse.getMessage()); + System.out.println("PASSED"); + } + } + + private static SecretKey getSecretKey(final byte[] secret) { + return new SecretKey() { + public String getFormat() { return "RAW"; } + public byte[] getEncoded() { return secret; } + public String getAlgorithm(){ return "SECRET"; } + }; + } +} diff --git a/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-0-attack.xml b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-0-attack.xml new file mode 100644 index 00000000000..5008dae5193 --- /dev/null +++ b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-0-attack.xml @@ -0,0 +1,16 @@ + + + + + + 0 + + + + nz4GS0NbH2SrWlD/4fX313CoTzc= + + + + + some other text + diff --git a/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-8-attack.xml b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-8-attack.xml new file mode 100644 index 00000000000..dfe0a0df9a5 --- /dev/null +++ b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1-trunclen-8-attack.xml @@ -0,0 +1,17 @@ + + + + + + 8 + + + + nz4GS0NbH2SrWlD/4fX313CoTzc= + + + + Qw== + + some other text + diff --git a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java index ea4fd610e1e..13881966d32 100644 --- a/jdk/test/javax/xml/crypto/dsig/GenerationTests.java +++ b/jdk/test/javax/xml/crypto/dsig/GenerationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,7 @@ /** * @test - * @bug 4635230 - * @bug 6283345 - * @bug 6303830 + * @bug 4635230 6283345 6303830 6824440 * @summary Basic unit tests for generating XML Signatures with JSR 105 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java * X509KeySelector.java GenerationTests.java @@ -248,8 +246,14 @@ public class GenerationTests { System.out.println("* Generating signature-enveloping-hmac-sha1-40.xml"); SignatureMethod hmacSha1 = fac.newSignatureMethod (SignatureMethod.HMAC_SHA1, new HMACParameterSpec(40)); - test_create_signature_enveloping(sha1, hmacSha1, null, - getSecretKey("secret".getBytes("ASCII")), sks, false); + try { + test_create_signature_enveloping(sha1, hmacSha1, null, + getSecretKey("secret".getBytes("ASCII")), sks, false); + } catch (Exception e) { + if (!(e instanceof XMLSignatureException)) { + throw e; + } + } System.out.println(); } diff --git a/jdk/test/javax/xml/crypto/dsig/ValidationTests.java b/jdk/test/javax/xml/crypto/dsig/ValidationTests.java index 0934de7e921..0604af9bbc5 100644 --- a/jdk/test/javax/xml/crypto/dsig/ValidationTests.java +++ b/jdk/test/javax/xml/crypto/dsig/ValidationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,7 @@ /** * @test - * @bug 4635230 - * @bug 6365103 - * @bug 6366054 + * @bug 4635230 6365103 6366054 6824440 * @summary Basic unit tests for validating XML Signatures with JSR 105 * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java * X509KeySelector.java ValidationTests.java @@ -42,6 +40,7 @@ import javax.xml.crypto.URIDereferencer; import javax.xml.crypto.URIReference; import javax.xml.crypto.URIReferenceException; import javax.xml.crypto.XMLCryptoContext; +import javax.xml.crypto.dsig.XMLSignatureException; import javax.xml.crypto.dsig.XMLSignatureFactory; /** @@ -68,7 +67,6 @@ public class ValidationTests { "signature-enveloping-dsa.xml", "signature-enveloping-rsa.xml", "signature-enveloping-hmac-sha1.xml", - "signature-enveloping-hmac-sha1-40.xml", "signature-external-dsa.xml", "signature-external-b64-dsa.xml", "signature-retrievalmethod-rawx509crt.xml", @@ -106,7 +104,6 @@ public class ValidationTests { KVKS, KVKS, SKKS, - SKKS, KVKS, KVKS, CKS, @@ -146,6 +143,36 @@ public class ValidationTests { atLeastOneFailed = true; } + System.out.println("Validating signature-enveloping-hmac-sha1-40.xml"); + try { + test_signature("signature-enveloping-hmac-sha1-40.xml", SKKS, false); + System.out.println("FAILED"); + atLeastOneFailed = true; + } catch (XMLSignatureException xse) { + System.out.println(xse.getMessage()); + System.out.println("PASSED"); + } + + System.out.println("Validating signature-enveloping-hmac-sha1-trunclen-0-attack.xml"); + try { + test_signature("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", SKKS, false); + System.out.println("FAILED"); + atLeastOneFailed = true; + } catch (XMLSignatureException xse) { + System.out.println(xse.getMessage()); + System.out.println("PASSED"); + } + + System.out.println("Validating signature-enveloping-hmac-sha1-trunclen-8-attack.xml"); + try { + test_signature("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", SKKS, false); + System.out.println("FAILED"); + atLeastOneFailed = true; + } catch (XMLSignatureException xse) { + System.out.println(xse.getMessage()); + System.out.println("PASSED"); + } + if (atLeastOneFailed) { throw new Exception ("At least one signature did not validate as expected"); diff --git a/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-0-attack.xml b/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-0-attack.xml new file mode 100644 index 00000000000..5008dae5193 --- /dev/null +++ b/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-0-attack.xml @@ -0,0 +1,16 @@ + + + + + + 0 + + + + nz4GS0NbH2SrWlD/4fX313CoTzc= + + + + + some other text + diff --git a/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-8-attack.xml b/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-8-attack.xml new file mode 100644 index 00000000000..dfe0a0df9a5 --- /dev/null +++ b/jdk/test/javax/xml/crypto/dsig/data/signature-enveloping-hmac-sha1-trunclen-8-attack.xml @@ -0,0 +1,17 @@ + + + + + + 8 + + + + nz4GS0NbH2SrWlD/4fX313CoTzc= + + + + Qw== + + some other text + From d92c74443f73ee3c282a052d9e5027a5123621d1 Mon Sep 17 00:00:00 2001 From: Kumar Srinivasan Date: Mon, 22 Jun 2009 07:23:20 -0700 Subject: [PATCH 19/70] 6830335: Java JAR Pack200 Decompression Integer Overflow Vulnerability Fixes a potential vulnerability in the unpack200 logic, by adding extra checks, a back-port. Reviewed-by: asaha --- .../share/native/com/sun/java/util/jar/pack/unpack.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp index a6f4ca0c2c8..7ca65c5d61e 100644 --- a/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp +++ b/jdk/src/share/native/com/sun/java/util/jar/pack/unpack.cpp @@ -908,10 +908,12 @@ void cpool::init(unpacker* u_, int counts[NUM_COUNTS]) { // place a limit on future CP growth: int generous = 0; - generous += u->ic_count*3; // implicit name, outer, outer.utf8 - generous += 40; // WKUs, misc - generous += u->class_count; // implicit SourceFile strings - maxentries = nentries + generous; + generous = add_size(generous, u->ic_count); // implicit name + generous = add_size(generous, u->ic_count); // outer + generous = add_size(generous, u->ic_count); // outer.utf8 + generous = add_size(generous, 40); // WKUs, misc + generous = add_size(generous, u->class_count); // implicit SourceFile strings + maxentries = add_size(nentries, generous); // Note that this CP does not include "empty" entries // for longs and doubles. Those are introduced when From 95f53ce57bb36019087a774f46bfeadc843d4d68 Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Mon, 22 Jun 2009 13:56:30 -0700 Subject: [PATCH 20/70] 6845701: Xerces2 Java XML library infinite loop with malformed XML input Reviewed-by: hawtin --- .../com/sun/org/apache/xerces/internal/impl/XMLScanner.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jaxp/src/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/jaxp/src/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java index e7071fde4f1..513dec48f04 100644 --- a/jaxp/src/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +++ b/jaxp/src/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java @@ -1027,6 +1027,9 @@ public abstract class XMLScanner int c = fEntityScanner.peekChar(); if (XMLChar.isMarkup(c) || c == ']') { fStringBuffer.append((char)fEntityScanner.scanChar()); + } else if (c != -1 && isInvalidLiteral(c)) { + reportFatalError("InvalidCharInSystemID", + new Object[] {Integer.toString(c, 16)}); } } while (fEntityScanner.scanLiteral(quote, ident) != quote); fStringBuffer.append(ident); From e4502f3b6fa5fc7bb678e0f02736bd2407883bca Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Wed, 8 Jul 2009 16:57:40 -0400 Subject: [PATCH 21/70] 6858484: If an invalid HMAC XML Signature is validated, all subsequent valid HMAC signatures are invalid Reviewed-by: asaha --- .../implementations/IntegrityHmac.java | 4 +++- .../xml/internal/security/TruncateHMAC.java | 24 +++++++++++++------ .../signature-enveloping-hmac-sha1.xml | 15 ++++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1.xml diff --git a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java index 85cc9e38a68..7231b069a18 100644 --- a/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java +++ b/jdk/src/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/IntegrityHmac.java @@ -106,7 +106,9 @@ public abstract class IntegrityHmac extends SignatureAlgorithmSpi { } public void reset() { - _HMACOutputLength=0; + _HMACOutputLength=0; + _HMACOutputLengthSet = false; + _macAlgorithm.reset(); } /** diff --git a/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java b/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java index ebb424de328..a77d02b84f9 100644 --- a/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java +++ b/jdk/test/com/sun/org/apache/xml/internal/security/TruncateHMAC.java @@ -23,7 +23,7 @@ /** * @test %I% %E% - * @bug 6824440 + * @bug 6824440 6858484 * @summary Check that Apache XMLSec APIs will not accept HMAC truncation * lengths less than minimum bound * @compile -XDignore.symbol.file TruncateHMAC.java @@ -56,8 +56,10 @@ public class TruncateHMAC { dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); dbf.setValidating(false); - validate("signature-enveloping-hmac-sha1-trunclen-0-attack.xml"); - validate("signature-enveloping-hmac-sha1-trunclen-8-attack.xml"); + validate("signature-enveloping-hmac-sha1-trunclen-0-attack.xml", false); + validate("signature-enveloping-hmac-sha1-trunclen-8-attack.xml", false); + // this one should pass + validate("signature-enveloping-hmac-sha1.xml", true); generate_hmac_sha1_40(); if (atLeastOneFailed) { @@ -66,7 +68,7 @@ public class TruncateHMAC { } } - private static void validate(String data) throws Exception { + private static void validate(String data, boolean pass) throws Exception { System.out.println("Validating " + data); File file = new File(DIR, data); @@ -83,11 +85,19 @@ public class TruncateHMAC { try { System.out.println ("Validation status: " + signature.checkSignatureValue(sk)); - System.out.println("FAILED"); - atLeastOneFailed = true; + if (!pass) { + System.out.println("FAILED"); + atLeastOneFailed = true; + } else { + System.out.println("PASSED"); + } } catch (XMLSignatureException xse) { System.out.println(xse.getMessage()); - System.out.println("PASSED"); + if (!pass) { + System.out.println("PASSED"); + } else { + System.out.println("FAILED"); + } } } diff --git a/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1.xml b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1.xml new file mode 100644 index 00000000000..c0c8343a895 --- /dev/null +++ b/jdk/test/com/sun/org/apache/xml/internal/security/signature-enveloping-hmac-sha1.xml @@ -0,0 +1,15 @@ + + + + + + + + 7/XTsHaBSOnJ/jXD5v0zL6VKYsk= + + + + JElPttIT4Am7Q+MNoMyv+WDfAZw= + + some text + From 97bb9bff6fec0de4d29248cdea3d535c57666157 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Fri, 17 Jul 2009 20:29:41 +0100 Subject: [PATCH 22/70] 6657619: DnsContext.debug is public static mutable (findbugs) Reviewed-by: alanb --- .../classes/com/sun/jndi/dns/DnsContext.java | 4 +- jdk/test/com/sun/jndi/dns/CheckAccess.java | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 jdk/test/com/sun/jndi/dns/CheckAccess.java diff --git a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java index a5c8f01f3c1..3b30bb96a6e 100644 --- a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java +++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -922,7 +922,7 @@ public class DnsContext extends ComponentDirContext { //---------- Debugging - public static boolean debug = false; + private static final boolean debug = false; private static final void dprint(String msg) { if (debug) { diff --git a/jdk/test/com/sun/jndi/dns/CheckAccess.java b/jdk/test/com/sun/jndi/dns/CheckAccess.java new file mode 100644 index 00000000000..478575167a5 --- /dev/null +++ b/jdk/test/com/sun/jndi/dns/CheckAccess.java @@ -0,0 +1,49 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6657619 + * @summary DnsContext.debug is public static mutable (findbugs) + * @author Vincent Ryan + */ + +import java.lang.reflect.*; + +/* + * Check that the 'debug' class member is no longer publicly accessible. + */ +public class CheckAccess { + public static final void main(String[] args) throws Exception { + try { + Class clazz = Class.forName("com.sun.jndi.dns.DnsContext"); + Field field = clazz.getField("debug"); + if (Modifier.isPublic(field.getModifiers())) { + throw new Exception( + "class member 'debug' must not be publicly accessible"); + } + } catch (NoSuchFieldException e) { + // 'debug' is not publicly accessible, ignore exception + } + } +} From d12079f670e26bd0c26e80ace4f63b3308622396 Mon Sep 17 00:00:00 2001 From: Vinnie Ryan Date: Fri, 17 Jul 2009 20:43:53 +0100 Subject: [PATCH 23/70] 6657695: AbstractSaslImpl.logger is a static mutable (findbugs) Reviewed-by: alanb --- .../security/sasl/util/AbstractSaslImpl.java | 21 +++------ .../sun/security/sasl/util/CheckAccess.java | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 jdk/test/com/sun/security/sasl/util/CheckAccess.java diff --git a/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java b/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java index 9c24b55ecf6..ac6fa258632 100644 --- a/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java +++ b/jdk/src/share/classes/com/sun/security/sasl/util/AbstractSaslImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2003 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,10 +48,6 @@ import sun.misc.HexDumpEncoder; * @author Rosanna Lee */ public abstract class AbstractSaslImpl { - /** - * Logger for debug messages - */ - protected static Logger logger; // set in initLogger(); lazily loads logger protected boolean completed = false; protected boolean privacy = false; @@ -68,7 +64,6 @@ public abstract class AbstractSaslImpl { protected String myClassName; protected AbstractSaslImpl(Map props, String className) throws SaslException { - initLogger(); myClassName = className; // Parse properties to set desired context options @@ -325,19 +320,15 @@ public abstract class AbstractSaslImpl { } } - /** - * Sets logger field. - */ - private static synchronized void initLogger() { - if (logger == null) { - logger = Logger.getLogger(SASL_LOGGER_NAME); - } - } - // ---------------- Constants ----------------- private static final String SASL_LOGGER_NAME = "javax.security.sasl"; protected static final String MAX_SEND_BUF = "javax.security.sasl.sendmaxbuffer"; + /** + * Logger for debug messages + */ + protected static final Logger logger = Logger.getLogger(SASL_LOGGER_NAME); + // default 0 (no protection); 1 (integrity only) protected static final byte NO_PROTECTION = (byte)1; protected static final byte INTEGRITY_ONLY_PROTECTION = (byte)2; diff --git a/jdk/test/com/sun/security/sasl/util/CheckAccess.java b/jdk/test/com/sun/security/sasl/util/CheckAccess.java new file mode 100644 index 00000000000..9ac0674b15c --- /dev/null +++ b/jdk/test/com/sun/security/sasl/util/CheckAccess.java @@ -0,0 +1,46 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6657695 + * @summary AbstractSaslImpl.logger is a static mutable (findbugs) + * @author Vincent Ryan + */ + +import java.lang.reflect.*; + +/* + * Check that the 'logger' class member is immutable. + */ +public class CheckAccess { + public static final void main(String[] args) throws Exception { + Class clazz = + Class.forName("com.sun.security.sasl.util.AbstractSaslImpl"); + Field field = clazz.getDeclaredField("logger"); + if (! Modifier.isFinal(field.getModifiers())) { + throw new Exception( + "class member 'logger' must be immutable"); + } + } +} From e9b3362acef6ec1e420ccf6b523f15085112b4e3 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Fri, 24 Jul 2009 11:06:57 -0700 Subject: [PATCH 24/70] 5063507: (fmt) missing exception for "%#s" format specifier Throw appropriate exception when necessary Reviewed-by: alanb --- jdk/src/share/classes/java/util/Formatter.java | 11 +++++++---- jdk/test/java/util/Formatter/Basic-X.java | 4 ++++ jdk/test/java/util/Formatter/Basic.java | 2 +- jdk/test/java/util/Formatter/BasicBigDecimal.java | 4 ++++ jdk/test/java/util/Formatter/BasicBigInteger.java | 4 ++++ jdk/test/java/util/Formatter/BasicBoolean.java | 4 ++++ jdk/test/java/util/Formatter/BasicBooleanObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicByte.java | 4 ++++ jdk/test/java/util/Formatter/BasicByteObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicChar.java | 4 ++++ jdk/test/java/util/Formatter/BasicCharObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicDateTime.java | 4 ++++ jdk/test/java/util/Formatter/BasicDouble.java | 4 ++++ jdk/test/java/util/Formatter/BasicDoubleObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicFloat.java | 4 ++++ jdk/test/java/util/Formatter/BasicFloatObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicInt.java | 4 ++++ jdk/test/java/util/Formatter/BasicIntObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicLong.java | 4 ++++ jdk/test/java/util/Formatter/BasicLongObject.java | 4 ++++ jdk/test/java/util/Formatter/BasicShort.java | 4 ++++ jdk/test/java/util/Formatter/BasicShortObject.java | 4 ++++ 22 files changed, 88 insertions(+), 5 deletions(-) diff --git a/jdk/src/share/classes/java/util/Formatter.java b/jdk/src/share/classes/java/util/Formatter.java index eb49ec9c5da..027e36dcc81 100644 --- a/jdk/src/share/classes/java/util/Formatter.java +++ b/jdk/src/share/classes/java/util/Formatter.java @@ -2818,15 +2818,18 @@ public final class Formatter implements Closeable, Flushable { } private void printString(Object arg, Locale l) throws IOException { - if (arg == null) { - print("null"); - } else if (arg instanceof Formattable) { + if (arg instanceof Formattable) { Formatter fmt = formatter; if (formatter.locale() != l) fmt = new Formatter(formatter.out(), l); ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision); } else { - print(arg.toString()); + if (f.contains(Flags.ALTERNATE)) + failMismatch(Flags.ALTERNATE, 's'); + if (arg == null) + print("null"); + else + print(arg.toString()); } } diff --git a/jdk/test/java/util/Formatter/Basic-X.java b/jdk/test/java/util/Formatter/Basic-X.java index 4677062cc14..2469417d256 100644 --- a/jdk/test/java/util/Formatter/Basic-X.java +++ b/jdk/test/java/util/Formatter/Basic-X.java @@ -486,6 +486,10 @@ public class Basic$Type$ extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/Basic.java b/jdk/test/java/util/Formatter/Basic.java index 3a957b2f4fa..e973b186842 100644 --- a/jdk/test/java/util/Formatter/Basic.java +++ b/jdk/test/java/util/Formatter/Basic.java @@ -25,7 +25,7 @@ * @summary Unit test for formatter * @bug 4906370 4962433 4973103 4989961 5005818 5031150 4970931 4989491 5002937 * 5005104 5007745 5061412 5055180 5066788 5088703 6317248 6318369 6320122 - * 6344623 6369500 6534606 6282094 6286592 6476425 + * 6344623 6369500 6534606 6282094 6286592 6476425 5063507 * * @run shell/timeout=240 Basic.sh */ diff --git a/jdk/test/java/util/Formatter/BasicBigDecimal.java b/jdk/test/java/util/Formatter/BasicBigDecimal.java index da96391384c..7f49988ee9d 100644 --- a/jdk/test/java/util/Formatter/BasicBigDecimal.java +++ b/jdk/test/java/util/Formatter/BasicBigDecimal.java @@ -486,6 +486,10 @@ public class BasicBigDecimal extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicBigInteger.java b/jdk/test/java/util/Formatter/BasicBigInteger.java index 4bba5a0fbe4..c7b3bc56002 100644 --- a/jdk/test/java/util/Formatter/BasicBigInteger.java +++ b/jdk/test/java/util/Formatter/BasicBigInteger.java @@ -486,6 +486,10 @@ public class BasicBigInteger extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicBoolean.java b/jdk/test/java/util/Formatter/BasicBoolean.java index ea60e388652..d626fdaba1d 100644 --- a/jdk/test/java/util/Formatter/BasicBoolean.java +++ b/jdk/test/java/util/Formatter/BasicBoolean.java @@ -486,6 +486,10 @@ public class BasicBoolean extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicBooleanObject.java b/jdk/test/java/util/Formatter/BasicBooleanObject.java index b4fbabb76b8..b0a3ab3694d 100644 --- a/jdk/test/java/util/Formatter/BasicBooleanObject.java +++ b/jdk/test/java/util/Formatter/BasicBooleanObject.java @@ -486,6 +486,10 @@ public class BasicBooleanObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicByte.java b/jdk/test/java/util/Formatter/BasicByte.java index deaf37957e5..8c630445459 100644 --- a/jdk/test/java/util/Formatter/BasicByte.java +++ b/jdk/test/java/util/Formatter/BasicByte.java @@ -486,6 +486,10 @@ public class BasicByte extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicByteObject.java b/jdk/test/java/util/Formatter/BasicByteObject.java index 06eb68ebd27..b2563784ee8 100644 --- a/jdk/test/java/util/Formatter/BasicByteObject.java +++ b/jdk/test/java/util/Formatter/BasicByteObject.java @@ -486,6 +486,10 @@ public class BasicByteObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicChar.java b/jdk/test/java/util/Formatter/BasicChar.java index 5ada7b166e7..cec8b76f58d 100644 --- a/jdk/test/java/util/Formatter/BasicChar.java +++ b/jdk/test/java/util/Formatter/BasicChar.java @@ -486,6 +486,10 @@ public class BasicChar extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicCharObject.java b/jdk/test/java/util/Formatter/BasicCharObject.java index 1e7d05d543f..4d1845977e3 100644 --- a/jdk/test/java/util/Formatter/BasicCharObject.java +++ b/jdk/test/java/util/Formatter/BasicCharObject.java @@ -486,6 +486,10 @@ public class BasicCharObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicDateTime.java b/jdk/test/java/util/Formatter/BasicDateTime.java index fd42da06f70..b30709d5465 100644 --- a/jdk/test/java/util/Formatter/BasicDateTime.java +++ b/jdk/test/java/util/Formatter/BasicDateTime.java @@ -486,6 +486,10 @@ public class BasicDateTime extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicDouble.java b/jdk/test/java/util/Formatter/BasicDouble.java index d985b46b1a5..5d5021717ec 100644 --- a/jdk/test/java/util/Formatter/BasicDouble.java +++ b/jdk/test/java/util/Formatter/BasicDouble.java @@ -486,6 +486,10 @@ public class BasicDouble extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicDoubleObject.java b/jdk/test/java/util/Formatter/BasicDoubleObject.java index 70dfd2929e5..1bbd67f18e9 100644 --- a/jdk/test/java/util/Formatter/BasicDoubleObject.java +++ b/jdk/test/java/util/Formatter/BasicDoubleObject.java @@ -486,6 +486,10 @@ public class BasicDoubleObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicFloat.java b/jdk/test/java/util/Formatter/BasicFloat.java index 122b44f1e75..c7592107261 100644 --- a/jdk/test/java/util/Formatter/BasicFloat.java +++ b/jdk/test/java/util/Formatter/BasicFloat.java @@ -486,6 +486,10 @@ public class BasicFloat extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicFloatObject.java b/jdk/test/java/util/Formatter/BasicFloatObject.java index 64c874cf2d5..c64bbb0f9d6 100644 --- a/jdk/test/java/util/Formatter/BasicFloatObject.java +++ b/jdk/test/java/util/Formatter/BasicFloatObject.java @@ -486,6 +486,10 @@ public class BasicFloatObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicInt.java b/jdk/test/java/util/Formatter/BasicInt.java index 4010d2250e0..5e42b45f76d 100644 --- a/jdk/test/java/util/Formatter/BasicInt.java +++ b/jdk/test/java/util/Formatter/BasicInt.java @@ -486,6 +486,10 @@ public class BasicInt extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicIntObject.java b/jdk/test/java/util/Formatter/BasicIntObject.java index fe41ea2964b..a9728b5bbf0 100644 --- a/jdk/test/java/util/Formatter/BasicIntObject.java +++ b/jdk/test/java/util/Formatter/BasicIntObject.java @@ -486,6 +486,10 @@ public class BasicIntObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicLong.java b/jdk/test/java/util/Formatter/BasicLong.java index fe232f1978e..41a74163050 100644 --- a/jdk/test/java/util/Formatter/BasicLong.java +++ b/jdk/test/java/util/Formatter/BasicLong.java @@ -486,6 +486,10 @@ public class BasicLong extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicLongObject.java b/jdk/test/java/util/Formatter/BasicLongObject.java index c99e0ba3c2a..c41c711ec7c 100644 --- a/jdk/test/java/util/Formatter/BasicLongObject.java +++ b/jdk/test/java/util/Formatter/BasicLongObject.java @@ -486,6 +486,10 @@ public class BasicLongObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicShort.java b/jdk/test/java/util/Formatter/BasicShort.java index 39079e4ad1e..e2e4e4c44f8 100644 --- a/jdk/test/java/util/Formatter/BasicShort.java +++ b/jdk/test/java/util/Formatter/BasicShort.java @@ -486,6 +486,10 @@ public class BasicShort extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h diff --git a/jdk/test/java/util/Formatter/BasicShortObject.java b/jdk/test/java/util/Formatter/BasicShortObject.java index e2dcc230174..48b33d18d85 100644 --- a/jdk/test/java/util/Formatter/BasicShortObject.java +++ b/jdk/test/java/util/Formatter/BasicShortObject.java @@ -486,6 +486,10 @@ public class BasicShortObject extends Basic { //--------------------------------------------------------------------- tryCatch("%-s", MissingFormatWidthException.class); tryCatch("%--s", DuplicateFormatFlagsException.class); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, 0.5f); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, "hello"); + tryCatch("%#s", FormatFlagsConversionMismatchException.class, null); //--------------------------------------------------------------------- // %h From df5da31f55e9a647549d7e3a91a01b00f4b42833 Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Tue, 28 Jul 2009 13:24:52 -0700 Subject: [PATCH 25/70] 6785442: ConcurrentLinkedQueue.remove() and poll() can both remove the same element 6493942: ConcurrentLinkedQueue.remove sometimes very slow New algorithm for handling concurrent linked lists Reviewed-by: martin --- .../concurrent/ConcurrentLinkedQueue.java | 448 ++++++++++++------ .../ConcurrentQueueLoops.java | 98 +++- .../ConcurrentQueues/GCRetention.java | 165 +++++++ .../LoopHelpers.java | 0 .../ConcurrentQueues/RemovePollRace.java | 230 +++++++++ .../LinkedBlockingQueue/OfferRemoveLoops.java | 74 +-- 6 files changed, 806 insertions(+), 209 deletions(-) rename jdk/test/java/util/concurrent/{ConcurrentLinkedQueue => ConcurrentQueues}/ConcurrentQueueLoops.java (57%) create mode 100644 jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java rename jdk/test/java/util/concurrent/{ConcurrentLinkedQueue => ConcurrentQueues}/LoopHelpers.java (100%) create mode 100644 jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java diff --git a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index fafbcc01704..fe2bb9d8bca 100644 --- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -34,9 +34,13 @@ */ package java.util.concurrent; -import java.util.*; -import java.util.concurrent.atomic.*; +import java.util.AbstractQueue; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Queue; /** * An unbounded thread-safe {@linkplain Queue queue} based on linked nodes. @@ -47,9 +51,9 @@ import java.util.concurrent.atomic.*; * queue the shortest time. New elements * are inserted at the tail of the queue, and the queue retrieval * operations obtain elements at the head of the queue. - * A ConcurrentLinkedQueue is an appropriate choice when + * A {@code ConcurrentLinkedQueue} is an appropriate choice when * many threads will share access to a common collection. - * This queue does not permit null elements. + * This queue does not permit {@code null} elements. * *

This implementation employs an efficient "wait-free" * algorithm based on one described in by Maged M. Michael and Michael L. Scott. * - *

Beware that, unlike in most collections, the size method + *

Beware that, unlike in most collections, the {@code size} method * is NOT a constant-time operation. Because of the * asynchronous nature of these queues, determining the current number * of elements requires a traversal of the elements. @@ -87,51 +91,102 @@ public class ConcurrentLinkedQueue extends AbstractQueue private static final long serialVersionUID = 196745693267521676L; /* - * This is a straight adaptation of Michael & Scott algorithm. - * For explanation, read the paper. The only (minor) algorithmic - * difference is that this version supports lazy deletion of - * internal nodes (method remove(Object)) -- remove CAS'es item - * fields to null. The normal queue operations unlink but then - * pass over nodes with null item fields. Similarly, iteration - * methods ignore those with nulls. + * This is a modification of the Michael & Scott algorithm, + * adapted for a garbage-collected environment, with support for + * interior node deletion (to support remove(Object)). For + * explanation, read the paper. * - * Also note that like most non-blocking algorithms in this - * package, this implementation relies on the fact that in garbage + * Note that like most non-blocking algorithms in this package, + * this implementation relies on the fact that in garbage * collected systems, there is no possibility of ABA problems due * to recycled nodes, so there is no need to use "counted * pointers" or related techniques seen in versions used in * non-GC'ed settings. + * + * The fundamental invariants are: + * - There is exactly one (last) Node with a null next reference, + * which is CASed when enqueueing. This last Node can be + * reached in O(1) time from tail, but tail is merely an + * optimization - it can always be reached in O(N) time from + * head as well. + * - The elements contained in the queue are the non-null items in + * Nodes that are reachable from head. CASing the item + * reference of a Node to null atomically removes it from the + * queue. Reachability of all elements from head must remain + * true even in the case of concurrent modifications that cause + * head to advance. A dequeued Node may remain in use + * indefinitely due to creation of an Iterator or simply a + * poll() that has lost its time slice. + * + * The above might appear to imply that all Nodes are GC-reachable + * from a predecessor dequeued Node. That would cause two problems: + * - allow a rogue Iterator to cause unbounded memory retention + * - cause cross-generational linking of old Nodes to new Nodes if + * a Node was tenured while live, which generational GCs have a + * hard time dealing with, causing repeated major collections. + * However, only non-deleted Nodes need to be reachable from + * dequeued Nodes, and reachability does not necessarily have to + * be of the kind understood by the GC. We use the trick of + * linking a Node that has just been dequeued to itself. Such a + * self-link implicitly means to advance to head. + * + * Both head and tail are permitted to lag. In fact, failing to + * update them every time one could is a significant optimization + * (fewer CASes). This is controlled by local "hops" variables + * that only trigger helping-CASes after experiencing multiple + * lags. + * + * Since head and tail are updated concurrently and independently, + * it is possible for tail to lag behind head (why not)? + * + * CASing a Node's item reference to null atomically removes the + * element from the queue. Iterators skip over Nodes with null + * items. Prior implementations of this class had a race between + * poll() and remove(Object) where the same element would appear + * to be successfully removed by two concurrent operations. The + * method remove(Object) also lazily unlinks deleted Nodes, but + * this is merely an optimization. + * + * When constructing a Node (before enqueuing it) we avoid paying + * for a volatile write to item by using lazySet instead of a + * normal write. This allows the cost of enqueue to be + * "one-and-a-half" CASes. + * + * Both head and tail may or may not point to a Node with a + * non-null item. If the queue is empty, all items must of course + * be null. Upon creation, both head and tail refer to a dummy + * Node with null item. Both head and tail are only updated using + * CAS, so they never regress, although again this is merely an + * optimization. */ private static class Node { private volatile E item; private volatile Node next; - private static final - AtomicReferenceFieldUpdater - nextUpdater = - AtomicReferenceFieldUpdater.newUpdater - (Node.class, Node.class, "next"); - private static final - AtomicReferenceFieldUpdater - itemUpdater = - AtomicReferenceFieldUpdater.newUpdater - (Node.class, Object.class, "item"); - - Node(E x) { item = x; } - - Node(E x, Node n) { item = x; next = n; } + Node(E item) { + // Piggyback on imminent casNext() + lazySetItem(item); + } E getItem() { return item; } boolean casItem(E cmp, E val) { - return itemUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, itemOffset, cmp, val); } void setItem(E val) { - itemUpdater.set(this, val); + item = val; + } + + void lazySetItem(E val) { + UNSAFE.putOrderedObject(this, itemOffset, val); + } + + void lazySetNext(Node val) { + UNSAFE.putOrderedObject(this, nextOffset, val); } Node getNext() { @@ -139,52 +194,55 @@ public class ConcurrentLinkedQueue extends AbstractQueue } boolean casNext(Node cmp, Node val) { - return nextUpdater.compareAndSet(this, cmp, val); + return UNSAFE.compareAndSwapObject(this, nextOffset, cmp, val); } - void setNext(Node val) { - nextUpdater.set(this, val); - } + // Unsafe mechanics + private static final sun.misc.Unsafe UNSAFE = + sun.misc.Unsafe.getUnsafe(); + private static final long nextOffset = + objectFieldOffset(UNSAFE, "next", Node.class); + private static final long itemOffset = + objectFieldOffset(UNSAFE, "item", Node.class); } - private static final - AtomicReferenceFieldUpdater - tailUpdater = - AtomicReferenceFieldUpdater.newUpdater - (ConcurrentLinkedQueue.class, Node.class, "tail"); - private static final - AtomicReferenceFieldUpdater - headUpdater = - AtomicReferenceFieldUpdater.newUpdater - (ConcurrentLinkedQueue.class, Node.class, "head"); - - private boolean casTail(Node cmp, Node val) { - return tailUpdater.compareAndSet(this, cmp, val); - } - - private boolean casHead(Node cmp, Node val) { - return headUpdater.compareAndSet(this, cmp, val); - } - - /** - * Pointer to header node, initialized to a dummy node. The first - * actual node is at head.getNext(). + * A node from which the first live (non-deleted) node (if any) + * can be reached in O(1) time. + * Invariants: + * - all live nodes are reachable from head via succ() + * - head != null + * - (tmp = head).next != tmp || tmp != head + * Non-invariants: + * - head.item may or may not be null. + * - it is permitted for tail to lag behind head, that is, for tail + * to not be reachable from head! */ - private transient volatile Node head = new Node(null, null); + private transient volatile Node head = new Node(null); - /** Pointer to last node on list **/ + /** + * A node from which the last node on list (that is, the unique + * node with node.next == null) can be reached in O(1) time. + * Invariants: + * - the last node is always reachable from tail via succ() + * - tail != null + * Non-invariants: + * - tail.item may or may not be null. + * - it is permitted for tail to lag behind head, that is, for tail + * to not be reachable from head! + * - tail.next may or may not be self-pointing to tail. + */ private transient volatile Node tail = head; /** - * Creates a ConcurrentLinkedQueue that is initially empty. + * Creates a {@code ConcurrentLinkedQueue} that is initially empty. */ public ConcurrentLinkedQueue() {} /** - * Creates a ConcurrentLinkedQueue + * Creates a {@code ConcurrentLinkedQueue} * initially containing the elements of the given collection, * added in traversal order of the collection's iterator. * @param c the collection of elements to initially contain @@ -201,115 +259,143 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue. * - * @return true (as specified by {@link Collection#add}) + * @return {@code true} (as specified by {@link Collection#add}) * @throws NullPointerException if the specified element is null */ public boolean add(E e) { return offer(e); } + /** + * We don't bother to update head or tail pointers if fewer than + * HOPS links from "true" location. We assume that volatile + * writes are significantly more expensive than volatile reads. + */ + private static final int HOPS = 1; + + /** + * Try to CAS head to p. If successful, repoint old head to itself + * as sentinel for succ(), below. + */ + final void updateHead(Node h, Node p) { + if (h != p && casHead(h, p)) + h.lazySetNext(h); + } + + /** + * Returns the successor of p, or the head node if p.next has been + * linked to self, which will only be true if traversing with a + * stale pointer that is now off the list. + */ + final Node succ(Node p) { + Node next = p.getNext(); + return (p == next) ? head : next; + } + /** * Inserts the specified element at the tail of this queue. * - * @return true (as specified by {@link Queue#offer}) + * @return {@code true} (as specified by {@link Queue#offer}) * @throws NullPointerException if the specified element is null */ public boolean offer(E e) { if (e == null) throw new NullPointerException(); - Node n = new Node(e, null); + Node n = new Node(e); + retry: for (;;) { Node t = tail; - Node s = t.getNext(); - if (t == tail) { - if (s == null) { - if (t.casNext(s, n)) { - casTail(t, n); - return true; - } + Node p = t; + for (int hops = 0; ; hops++) { + Node next = succ(p); + if (next != null) { + if (hops > HOPS && t != tail) + continue retry; + p = next; + } else if (p.casNext(null, n)) { + if (hops >= HOPS) + casTail(t, n); // Failure is OK. + return true; } else { - casTail(t, s); + p = succ(p); } } } } public E poll() { - for (;;) { - Node h = head; - Node t = tail; - Node first = h.getNext(); - if (h == head) { - if (h == t) { - if (first == null) - return null; - else - casTail(t, first); - } else if (casHead(h, first)) { - E item = first.getItem(); - if (item != null) { - first.setItem(null); - return item; - } - // else skip over deleted item, continue loop, + Node h = head; + Node p = h; + for (int hops = 0; ; hops++) { + E item = p.getItem(); + + if (item != null && p.casItem(item, null)) { + if (hops >= HOPS) { + Node q = p.getNext(); + updateHead(h, (q != null) ? q : p); } + return item; } + Node next = succ(p); + if (next == null) { + updateHead(h, p); + break; + } + p = next; } + return null; } - public E peek() { // same as poll except don't remove item + public E peek() { + Node h = head; + Node p = h; + E item; for (;;) { - Node h = head; - Node t = tail; - Node first = h.getNext(); - if (h == head) { - if (h == t) { - if (first == null) - return null; - else - casTail(t, first); - } else { - E item = first.getItem(); - if (item != null) - return item; - else // remove deleted node and continue - casHead(h, first); - } + item = p.getItem(); + if (item != null) + break; + Node next = succ(p); + if (next == null) { + break; } + p = next; } + updateHead(h, p); + return item; } /** - * Returns the first actual (non-header) node on list. This is yet - * another variant of poll/peek; here returning out the first - * node, not element (so we cannot collapse with peek() without - * introducing race.) + * Returns the first live (non-deleted) node on list, or null if none. + * This is yet another variant of poll/peek; here returning the + * first node, not element. We could make peek() a wrapper around + * first(), but that would cost an extra volatile read of item, + * and the need to add a retry loop to deal with the possibility + * of losing a race to a concurrent poll(). */ Node first() { + Node h = head; + Node p = h; + Node result; for (;;) { - Node h = head; - Node t = tail; - Node first = h.getNext(); - if (h == head) { - if (h == t) { - if (first == null) - return null; - else - casTail(t, first); - } else { - if (first.getItem() != null) - return first; - else // remove deleted node and continue - casHead(h, first); - } + E item = p.getItem(); + if (item != null) { + result = p; + break; } + Node next = succ(p); + if (next == null) { + result = null; + break; + } + p = next; } + updateHead(h, p); + return result; } - /** - * Returns true if this queue contains no elements. + * Returns {@code true} if this queue contains no elements. * - * @return true if this queue contains no elements + * @return {@code true} if this queue contains no elements */ public boolean isEmpty() { return first() == null; @@ -317,8 +403,8 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Returns the number of elements in this queue. If this queue - * contains more than Integer.MAX_VALUE elements, returns - * Integer.MAX_VALUE. + * contains more than {@code Integer.MAX_VALUE} elements, returns + * {@code Integer.MAX_VALUE}. * *

Beware that, unlike in most collections, this method is * NOT a constant-time operation. Because of the @@ -329,7 +415,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue */ public int size() { int count = 0; - for (Node p = first(); p != null; p = p.getNext()) { + for (Node p = first(); p != null; p = succ(p)) { if (p.getItem() != null) { // Collections.size() spec says to max out if (++count == Integer.MAX_VALUE) @@ -340,16 +426,16 @@ public class ConcurrentLinkedQueue extends AbstractQueue } /** - * Returns true if this queue contains the specified element. - * More formally, returns true if and only if this queue contains - * at least one element e such that o.equals(e). + * Returns {@code true} if this queue contains the specified element. + * More formally, returns {@code true} if and only if this queue contains + * at least one element {@code e} such that {@code o.equals(e)}. * * @param o object to be checked for containment in this queue - * @return true if this queue contains the specified element + * @return {@code true} if this queue contains the specified element */ public boolean contains(Object o) { if (o == null) return false; - for (Node p = first(); p != null; p = p.getNext()) { + for (Node p = first(); p != null; p = succ(p)) { E item = p.getItem(); if (item != null && o.equals(item)) @@ -360,23 +446,29 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element e such - * that o.equals(e), if this queue contains one or more such + * if it is present. More formally, removes an element {@code e} such + * that {@code o.equals(e)}, if this queue contains one or more such * elements. - * Returns true if this queue contained the specified element + * Returns {@code true} if this queue contained the specified element * (or equivalently, if this queue changed as a result of the call). * * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call + * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { if (o == null) return false; - for (Node p = first(); p != null; p = p.getNext()) { + Node pred = null; + for (Node p = first(); p != null; p = succ(p)) { E item = p.getItem(); if (item != null && o.equals(item) && - p.casItem(item, null)) + p.casItem(item, null)) { + Node next = succ(p); + if (pred != null && next != null) + pred.casNext(p, next); return true; + } + pred = p; } return false; } @@ -397,7 +489,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue public Object[] toArray() { // Use ArrayList to deal with resizing. ArrayList al = new ArrayList(); - for (Node p = first(); p != null; p = p.getNext()) { + for (Node p = first(); p != null; p = succ(p)) { E item = p.getItem(); if (item != null) al.add(item); @@ -415,22 +507,22 @@ public class ConcurrentLinkedQueue extends AbstractQueue *

If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to - * null. + * {@code null}. * *

Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

Suppose x is a queue known to contain only strings. + *

Suppose {@code x} is a queue known to contain only strings. * The following code can be used to dump the queue into a newly - * allocated array of String: + * allocated array of {@code String}: * *

      *     String[] y = x.toArray(new String[0]);
* - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the @@ -441,11 +533,12 @@ public class ConcurrentLinkedQueue extends AbstractQueue * this queue * @throws NullPointerException if the specified array is null */ + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { // try to use sent-in array int k = 0; Node p; - for (p = first(); p != null && k < a.length; p = p.getNext()) { + for (p = first(); p != null && k < a.length; p = succ(p)) { E item = p.getItem(); if (item != null) a[k++] = (T)item; @@ -458,7 +551,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue // If won't fit, use ArrayList version ArrayList al = new ArrayList(); - for (Node q = first(); q != null; q = q.getNext()) { + for (Node q = first(); q != null; q = succ(q)) { E item = q.getItem(); if (item != null) al.add(item); @@ -511,7 +604,15 @@ public class ConcurrentLinkedQueue extends AbstractQueue lastRet = nextNode; E x = nextItem; - Node p = (nextNode == null)? first() : nextNode.getNext(); + Node pred, p; + if (nextNode == null) { + p = first(); + pred = null; + } else { + pred = nextNode; + p = succ(nextNode); + } + for (;;) { if (p == null) { nextNode = null; @@ -523,8 +624,13 @@ public class ConcurrentLinkedQueue extends AbstractQueue nextNode = p; nextItem = item; return x; - } else // skip over nulls - p = p.getNext(); + } else { + // skip over nulls + Node next = succ(p); + if (pred != null && next != null) + pred.casNext(p, next); + p = next; + } } } @@ -549,7 +655,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Save the state to a stream (that is, serialize it). * - * @serialData All of the elements (each an E) in + * @serialData All of the elements (each an {@code E}) in * the proper order, followed by a null * @param s the stream */ @@ -560,7 +666,7 @@ public class ConcurrentLinkedQueue extends AbstractQueue s.defaultWriteObject(); // Write out all elements in the proper order. - for (Node p = first(); p != null; p = p.getNext()) { + for (Node p = first(); p != null; p = succ(p)) { Object item = p.getItem(); if (item != null) s.writeObject(item); @@ -579,10 +685,11 @@ public class ConcurrentLinkedQueue extends AbstractQueue throws java.io.IOException, ClassNotFoundException { // Read in capacity, and any hidden stuff s.defaultReadObject(); - head = new Node(null, null); + head = new Node(null); tail = head; // Read in all elements and place in queue for (;;) { + @SuppressWarnings("unchecked") E item = (E)s.readObject(); if (item == null) break; @@ -591,4 +698,35 @@ public class ConcurrentLinkedQueue extends AbstractQueue } } + // Unsafe mechanics + + private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe(); + private static final long headOffset = + objectFieldOffset(UNSAFE, "head", ConcurrentLinkedQueue.class); + private static final long tailOffset = + objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedQueue.class); + + private boolean casTail(Node cmp, Node val) { + return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val); + } + + private boolean casHead(Node cmp, Node val) { + return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val); + } + + private void lazySetHead(Node val) { + UNSAFE.putOrderedObject(this, headOffset, val); + } + + static long objectFieldOffset(sun.misc.Unsafe UNSAFE, + String field, Class klazz) { + try { + return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field)); + } catch (NoSuchFieldException e) { + // Convert Exception to corresponding Error + NoSuchFieldError error = new NoSuchFieldError(field); + error.initCause(e); + throw error; + } + } } diff --git a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/ConcurrentQueueLoops.java b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java similarity index 57% rename from jdk/test/java/util/concurrent/ConcurrentLinkedQueue/ConcurrentQueueLoops.java rename to jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java index b0c4b68e10e..73dfc65c768 100644 --- a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/ConcurrentQueueLoops.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java @@ -33,9 +33,8 @@ /* * @test - * @bug 4486658 - * @compile -source 1.5 ConcurrentQueueLoops.java - * @run main/timeout=230 ConcurrentQueueLoops + * @bug 4486658 6785442 + * @run main ConcurrentQueueLoops 8 123456 * @summary Checks that a set of threads can repeatedly get and modify items */ @@ -44,34 +43,75 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; public class ConcurrentQueueLoops { - static final ExecutorService pool = Executors.newCachedThreadPool(); - static AtomicInteger totalItems; - static boolean print = false; + ExecutorService pool; + AtomicInteger totalItems; + boolean print; - public static void main(String[] args) throws Exception { - int maxStages = 8; - int items = 100000; + // Suitable for benchmarking. Overriden by args[0] for testing. + int maxStages = 20; + // Suitable for benchmarking. Overriden by args[1] for testing. + int items = 1024 * 1024; + + Collection> concurrentQueues() { + List> queues = new ArrayList>(); + queues.add(new ConcurrentLinkedQueue()); + queues.add(new ArrayBlockingQueue(items, false)); + //queues.add(new ArrayBlockingQueue(count, true)); + queues.add(new LinkedBlockingQueue()); + queues.add(new LinkedBlockingDeque()); + + try { + queues.add((Queue) + Class.forName("java.util.concurrent.LinkedTransferQueue") + .newInstance()); + } catch (IllegalAccessException e) { + } catch (InstantiationException e) { + } catch (ClassNotFoundException e) { + // OK; not yet added to JDK + } + + // Following additional implementations are available from: + // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html + // queues.add(new LinkedTransferQueue()); + // queues.add(new SynchronizedLinkedListQueue()); + + // Avoid "first fast, second slow" benchmark effect. + Collections.shuffle(queues); + return queues; + } + + void test(String[] args) throws Throwable { if (args.length > 0) maxStages = Integer.parseInt(args[0]); + if (args.length > 1) + items = Integer.parseInt(args[1]); + + for (Queue queue : concurrentQueues()) + test(queue); + } + + void test(final Queue q) throws Throwable { + System.out.println(q.getClass().getSimpleName()); + pool = Executors.newCachedThreadPool(); + print = false; print = false; System.out.println("Warmup..."); - oneRun(1, items); - Thread.sleep(100); - oneRun(1, items); + oneRun(1, items, q); + //Thread.sleep(100); + oneRun(3, items, q); Thread.sleep(100); print = true; for (int i = 1; i <= maxStages; i += (i+1) >>> 1) { - oneRun(i, items); + oneRun(i, items, q); } pool.shutdown(); - if (! pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) - throw new Error(); + check(pool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)); } - static class Stage implements Callable { + class Stage implements Callable { final Queue queue; final CyclicBarrier barrier; int items; @@ -110,15 +150,11 @@ public class ConcurrentQueueLoops { } return new Integer(l); } - catch (Exception ie) { - ie.printStackTrace(); - throw new Error("Call loop failed"); - } + catch (Throwable t) { unexpected(t); return null; } } } - static void oneRun(int n, int items) throws Exception { - Queue q = new ConcurrentLinkedQueue(); + void oneRun(int n, int items, final Queue q) throws Exception { LoopHelpers.BarrierTimer timer = new LoopHelpers.BarrierTimer(); CyclicBarrier barrier = new CyclicBarrier(n + 1, timer); totalItems = new AtomicInteger(n * items); @@ -141,6 +177,22 @@ public class ConcurrentQueueLoops { System.out.println(LoopHelpers.rightJustify(time / (items * n)) + " ns per item"); if (total == 0) // avoid overoptimization System.out.println("useless result: " + total); - } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new ConcurrentQueueLoops().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} } diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java new file mode 100644 index 00000000000..68e62734359 --- /dev/null +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java @@ -0,0 +1,165 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ +/* + * @test + * @bug 6785442 + * @summary Benchmark that tries to GC-tenure head, followed by + * many add/remove operations. + * @run main GCRetention 12345 + */ + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.LinkedList; +import java.util.PriorityQueue; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Queue; +import java.util.Map; + +public class GCRetention { + // Suitable for benchmarking. Overriden by args[0] for testing. + int count = 1024 * 1024; + + final Map results = new ConcurrentHashMap(); + + Collection> queues() { + List> queues = new ArrayList>(); + queues.add(new ConcurrentLinkedQueue()); + queues.add(new ArrayBlockingQueue(count, false)); + queues.add(new ArrayBlockingQueue(count, true)); + queues.add(new LinkedBlockingQueue()); + queues.add(new LinkedBlockingDeque()); + queues.add(new PriorityBlockingQueue()); + queues.add(new PriorityQueue()); + queues.add(new LinkedList()); + + try { + queues.add((Queue) + Class.forName("java.util.concurrent.LinkedTransferQueue") + .newInstance()); + } catch (IllegalAccessException e) { + } catch (InstantiationException e) { + } catch (ClassNotFoundException e) { + // OK; not yet added to JDK + } + + // Following additional implementations are available from: + // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html + // queues.add(new LinkedTransferQueue()); + // queues.add(new SynchronizedLinkedListQueue()); + + // Avoid "first fast, second slow" benchmark effect. + Collections.shuffle(queues); + return queues; + } + + void prettyPrintResults() { + List classNames = new ArrayList(results.keySet()); + Collections.sort(classNames); + int maxClassNameLength = 0; + int maxNanosLength = 0; + for (String name : classNames) { + if (maxClassNameLength < name.length()) + maxClassNameLength = name.length(); + if (maxNanosLength < results.get(name).length()) + maxNanosLength = results.get(name).length(); + } + String format = String.format("%%%ds %%%ds nanos/item%%n", + maxClassNameLength, maxNanosLength); + for (String name : classNames) + System.out.printf(format, name, results.get(name)); + } + + void test(String[] args) { + if (args.length > 0) + count = Integer.valueOf(args[0]); + // Warmup + for (Queue queue : queues()) + test(queue); + results.clear(); + for (Queue queue : queues()) + test(queue); + + prettyPrintResults(); + } + + void test(Queue q) { + long t0 = System.nanoTime(); + for (int i = 0; i < count; i++) + check(q.add(Boolean.TRUE)); + System.gc(); + System.gc(); + Boolean x; + while ((x = q.poll()) != null) + equal(x, Boolean.TRUE); + check(q.isEmpty()); + + for (int i = 0; i < 10 * count; i++) { + for (int k = 0; k < 3; k++) + check(q.add(Boolean.TRUE)); + for (int k = 0; k < 3; k++) + if (q.poll() != Boolean.TRUE) + fail(); + } + check(q.isEmpty()); + + String className = q.getClass().getSimpleName(); + long elapsed = System.nanoTime() - t0; + int nanos = (int) ((double) elapsed / (10 * 3 * count)); + results.put(className, String.valueOf(nanos)); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new GCRetention().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/concurrent/ConcurrentLinkedQueue/LoopHelpers.java b/jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java similarity index 100% rename from jdk/test/java/util/concurrent/ConcurrentLinkedQueue/LoopHelpers.java rename to jdk/test/java/util/concurrent/ConcurrentQueues/LoopHelpers.java diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java new file mode 100644 index 00000000000..f3e4ee9feb8 --- /dev/null +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/RemovePollRace.java @@ -0,0 +1,230 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @bug 6785442 + * @summary Checks race between poll and remove(Object), while + * occasionally moonlighting as a microbenchmark. + * @run main RemovePollRace 12345 + */ + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.atomic.AtomicLong; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Queue; +import java.util.Map; + +public class RemovePollRace { + // Suitable for benchmarking. Overriden by args[0] for testing. + int count = 1024 * 1024; + + final Map results = new ConcurrentHashMap(); + + Collection> concurrentQueues() { + List> queues = new ArrayList>(); + queues.add(new ConcurrentLinkedQueue()); + queues.add(new ArrayBlockingQueue(count, false)); + queues.add(new ArrayBlockingQueue(count, true)); + queues.add(new LinkedBlockingQueue()); + queues.add(new LinkedBlockingDeque()); + + try { + queues.add((Queue) + Class.forName("java.util.concurrent.LinkedTransferQueue") + .newInstance()); + } catch (IllegalAccessException e) { + } catch (InstantiationException e) { + } catch (ClassNotFoundException e) { + // OK; not yet added to JDK + } + + // Following additional implementations are available from: + // http://gee.cs.oswego.edu/dl/concurrency-interest/index.html + // queues.add(new LinkedTransferQueue()); + // queues.add(new SynchronizedLinkedListQueue()); + + // Avoid "first fast, second slow" benchmark effect. + Collections.shuffle(queues); + return queues; + } + + void prettyPrintResults() { + List classNames = new ArrayList(results.keySet()); + Collections.sort(classNames); + int maxClassNameLength = 0; + int maxNanosLength = 0; + for (String name : classNames) { + if (maxClassNameLength < name.length()) + maxClassNameLength = name.length(); + if (maxNanosLength < results.get(name).length()) + maxNanosLength = results.get(name).length(); + } + String format = String.format("%%%ds %%%ds nanos/item%%n", + maxClassNameLength, maxNanosLength); + for (String name : classNames) + System.out.printf(format, name, results.get(name)); + } + + void test(String[] args) throws Throwable { + if (args.length > 0) + count = Integer.valueOf(args[0]); + // Warmup + for (Queue queue : concurrentQueues()) + test(queue); + results.clear(); + for (Queue queue : concurrentQueues()) + test(queue); + + prettyPrintResults(); + } + + void await(CountDownLatch latch) { + try { latch.await(); } + catch (InterruptedException e) { unexpected(e); } + } + + void test(final Queue q) throws Throwable { + long t0 = System.nanoTime(); + final int SPINS = 5; + final AtomicLong removes = new AtomicLong(0); + final AtomicLong polls = new AtomicLong(0); + final int adderCount = + Math.max(1, Runtime.getRuntime().availableProcessors() / 4); + final int removerCount = + Math.max(1, Runtime.getRuntime().availableProcessors() / 4); + final int pollerCount = removerCount; + final int threadCount = adderCount + removerCount + pollerCount; + final CountDownLatch startingGate = new CountDownLatch(1); + final CountDownLatch addersDone = new CountDownLatch(adderCount); + final Runnable remover = new Runnable() { + public void run() { + await(startingGate); + int spins = 0; + for (;;) { + boolean quittingTime = (addersDone.getCount() == 0); + if (q.remove(Boolean.TRUE)) + removes.getAndIncrement(); + else if (quittingTime) + break; + else if (++spins > SPINS) { + Thread.yield(); + spins = 0; + }}}}; + final Runnable poller = new Runnable() { + public void run() { + await(startingGate); + int spins = 0; + for (;;) { + boolean quittingTime = (addersDone.getCount() == 0); + if (q.poll() == Boolean.TRUE) + polls.getAndIncrement(); + else if (quittingTime) + break; + else if (++spins > SPINS) { + Thread.yield(); + spins = 0; + }}}}; + final Runnable adder = new Runnable() { + public void run() { + await(startingGate); + for (int i = 0; i < count; i++) { + for (;;) { + try { q.add(Boolean.TRUE); break; } + catch (IllegalStateException e) { Thread.yield(); } + } + } + addersDone.countDown(); + }}; + + final List adders = new ArrayList(); + final List removers = new ArrayList(); + final List pollers = new ArrayList(); + for (int i = 0; i < adderCount; i++) + adders.add(checkedThread(adder)); + for (int i = 0; i < removerCount; i++) + removers.add(checkedThread(remover)); + for (int i = 0; i < pollerCount; i++) + pollers.add(checkedThread(poller)); + + final List allThreads = new ArrayList(); + allThreads.addAll(removers); + allThreads.addAll(pollers); + allThreads.addAll(adders); + + for (Thread t : allThreads) + t.start(); + startingGate.countDown(); + for (Thread t : allThreads) + t.join(); + + String className = q.getClass().getSimpleName(); + long elapsed = System.nanoTime() - t0; + int nanos = (int) ((double) elapsed / (adderCount * count)); + results.put(className, String.valueOf(nanos)); + if (removes.get() + polls.get() != adderCount * count) { + String msg = String.format + ("class=%s removes=%s polls=%d count=%d", + className, removes.get(), polls.get(), count); + fail(msg); + } + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new RemovePollRace().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} + Thread checkedThread(final Runnable r) { + return new Thread() {public void run() { + try {r.run();} catch (Throwable t) {unexpected(t);}}};} +} diff --git a/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java b/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java index e66dfb7042d..fbd0070a7a7 100644 --- a/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java +++ b/jdk/test/java/util/concurrent/LinkedBlockingQueue/OfferRemoveLoops.java @@ -28,62 +28,74 @@ * @author Martin Buchholz */ +import java.util.*; import java.util.concurrent.*; public class OfferRemoveLoops { - private static void realMain(String[] args) throws Throwable { + void test(String[] args) throws Throwable { testQueue(new LinkedBlockingQueue(10)); testQueue(new LinkedBlockingQueue()); testQueue(new LinkedBlockingDeque(10)); testQueue(new LinkedBlockingDeque()); testQueue(new ArrayBlockingQueue(10)); testQueue(new PriorityBlockingQueue(10)); + testQueue(new ConcurrentLinkedQueue()); } - private abstract static class ControlledThread extends Thread { + abstract class CheckedThread extends Thread { abstract protected void realRun(); public void run() { try { realRun(); } catch (Throwable t) { unexpected(t); } } } - private static void testQueue(final BlockingQueue q) throws Throwable { - System.out.println(q.getClass()); - final int count = 10000; - final long quittingTime = System.nanoTime() + 1L * 1000L * 1000L * 1000L; - Thread t1 = new ControlledThread() { - protected void realRun() { - for (int i = 0, j = 0; i < count; i++) - while (! q.remove(String.valueOf(i)) - && System.nanoTime() - quittingTime < 0) - Thread.yield();}}; - Thread t2 = new ControlledThread() { - protected void realRun() { - for (int i = 0, j = 0; i < count; i++) - while (! q.offer(String.valueOf(i)) - && System.nanoTime() - quittingTime < 0) - Thread.yield();}}; + void testQueue(final Queue q) throws Throwable { + System.out.println(q.getClass().getSimpleName()); + final int count = 1000 * 1000; + final long testDurationSeconds = 1L; + final long testDurationMillis = testDurationSeconds * 1000L; + final long quittingTimeNanos + = System.nanoTime() + testDurationSeconds * 1000L * 1000L * 1000L; + Thread t1 = new CheckedThread() { + protected void realRun() { + for (int i = 0; i < count; i++) { + if ((i % 1024) == 0 && + System.nanoTime() - quittingTimeNanos > 0) + return; + while (! q.remove(String.valueOf(i))) + Thread.yield(); + }}}; + Thread t2 = new CheckedThread() { + protected void realRun() { + for (int i = 0; i < count; i++) { + if ((i % 1024) == 0 && + System.nanoTime() - quittingTimeNanos > 0) + return; + while (! q.offer(String.valueOf(i))) + Thread.yield(); + }}}; t1.setDaemon(true); t2.setDaemon(true); t1.start(); t2.start(); - t1.join(10000); t2.join(10000); + t1.join(10 * testDurationMillis); + t2.join(10 * testDurationMillis); check(! t1.isAlive()); check(! t2.isAlive()); } //--------------------- Infrastructure --------------------------- - static volatile int passed = 0, failed = 0; - static void pass() { passed++; } - static void fail() { failed++; Thread.dumpStack(); } - static void unexpected(Throwable t) { failed++; t.printStackTrace(); } - static void check(boolean cond) { if (cond) pass(); else fail(); } - static void equal(Object x, Object y) { + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { if (x == null ? y == null : x.equals(y)) pass(); - else {System.out.println(x + " not equal to " + y); fail(); }} - + else fail(x + " not equal to " + y);} public static void main(String[] args) throws Throwable { - try { realMain(args); } catch (Throwable t) { unexpected(t); } - + new OfferRemoveLoops().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); - if (failed > 0) throw new Exception("Some tests failed"); - } + if (failed > 0) throw new AssertionError("Some tests failed");} } From d43e798981fa1c1d3119555e087776f09fb3015b Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Tue, 28 Jul 2009 17:17:55 -0700 Subject: [PATCH 26/70] 6805775: LinkedBlockingQueue Nodes should unlink themselves before becoming garbage 6815766: LinkedBlockingQueue's iterator can return null if drainTo(c) executes concurrently Faster, more correct. Use self-linking trick to avoid gc retention Reviewed-by: martin, dholmes --- .../util/concurrent/LinkedBlockingDeque.java | 394 +++++++++++------ .../util/concurrent/LinkedBlockingQueue.java | 403 ++++++++++-------- jdk/test/java/util/Collection/MOAT.java | 35 ++ .../BlockingQueue/OfferDrainToLoops.java | 130 ++++++ .../IteratorWeakConsistency.java | 93 ++++ 5 files changed, 730 insertions(+), 325 deletions(-) create mode 100644 jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java create mode 100644 jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 48fc8717a42..7db94a6efba 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -34,8 +34,13 @@ */ package java.util.concurrent; -import java.util.*; -import java.util.concurrent.locks.*; + +import java.util.AbstractQueue; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; /** * An optionally-bounded {@linkplain BlockingDeque blocking deque} based on @@ -73,6 +78,20 @@ public class LinkedBlockingDeque /* * Implemented as a simple doubly-linked list protected by a * single lock and using conditions to manage blocking. + * + * To implement weakly consistent iterators, it appears we need to + * keep all Nodes GC-reachable from a predecessor dequeued Node. + * That would cause two problems: + * - allow a rogue Iterator to cause unbounded memory retention + * - cause cross-generational linking of old Nodes to new Nodes if + * a Node was tenured while live, which generational GCs have a + * hard time dealing with, causing repeated major collections. + * However, only non-deleted Nodes need to be reachable from + * dequeued Nodes, and reachability does not necessarily have to + * be of the kind understood by the GC. We use the trick of + * linking a Node that has just been dequeued to itself. Such a + * self-link implicitly means to jump to "first" (for next links) + * or "last" (for prev links). */ /* @@ -86,9 +105,27 @@ public class LinkedBlockingDeque /** Doubly-linked list node class */ static final class Node { + /** + * The item, or null if this node has been removed. + */ E item; + + /** + * One of: + * - the real predecessor Node + * - this Node, meaning the predecessor is tail + * - null, meaning there is no predecessor + */ Node prev; + + /** + * One of: + * - the real successor Node + * - this Node, meaning the successor is head + * - null, meaning there is no successor + */ Node next; + Node(E x, Node p, Node n) { item = x; prev = p; @@ -96,23 +133,37 @@ public class LinkedBlockingDeque } } - /** Pointer to first node */ - private transient Node first; - /** Pointer to last node */ - private transient Node last; + /** + * Pointer to first node. + * Invariant: (first == null && last == null) || + * (first.prev == null && first.item != null) + */ + transient Node first; + + /** + * Pointer to last node. + * Invariant: (first == null && last == null) || + * (last.next == null && last.item != null) + */ + transient Node last; + /** Number of items in the deque */ private transient int count; + /** Maximum number of items in the deque */ private final int capacity; + /** Main lock guarding all access */ - private final ReentrantLock lock = new ReentrantLock(); + final ReentrantLock lock = new ReentrantLock(); + /** Condition for waiting takes */ private final Condition notEmpty = lock.newCondition(); + /** Condition for waiting puts */ private final Condition notFull = lock.newCondition(); /** - * Creates a LinkedBlockingDeque with a capacity of + * Creates a {@code LinkedBlockingDeque} with a capacity of * {@link Integer#MAX_VALUE}. */ public LinkedBlockingDeque() { @@ -120,10 +171,10 @@ public class LinkedBlockingDeque } /** - * Creates a LinkedBlockingDeque with the given (fixed) capacity. + * Creates a {@code LinkedBlockingDeque} with the given (fixed) capacity. * * @param capacity the capacity of this deque - * @throws IllegalArgumentException if capacity is less than 1 + * @throws IllegalArgumentException if {@code capacity} is less than 1 */ public LinkedBlockingDeque(int capacity) { if (capacity <= 0) throw new IllegalArgumentException(); @@ -131,7 +182,7 @@ public class LinkedBlockingDeque } /** - * Creates a LinkedBlockingDeque with a capacity of + * Creates a {@code LinkedBlockingDeque} with a capacity of * {@link Integer#MAX_VALUE}, initially containing the elements of * the given collection, added in traversal order of the * collection's iterator. @@ -142,8 +193,18 @@ public class LinkedBlockingDeque */ public LinkedBlockingDeque(Collection c) { this(Integer.MAX_VALUE); - for (E e : c) - add(e); + final ReentrantLock lock = this.lock; + lock.lock(); // Never contended, but necessary for visibility + try { + for (E e : c) { + if (e == null) + throw new NullPointerException(); + if (!linkLast(e)) + throw new IllegalStateException("Deque full"); + } + } finally { + lock.unlock(); + } } @@ -153,9 +214,9 @@ public class LinkedBlockingDeque * Links e as first element, or returns false if full. */ private boolean linkFirst(E e) { + // assert lock.isHeldByCurrentThread(); if (count >= capacity) return false; - ++count; Node f = first; Node x = new Node(e, null, f); first = x; @@ -163,6 +224,7 @@ public class LinkedBlockingDeque last = x; else f.prev = x; + ++count; notEmpty.signal(); return true; } @@ -171,9 +233,9 @@ public class LinkedBlockingDeque * Links e as last element, or returns false if full. */ private boolean linkLast(E e) { + // assert lock.isHeldByCurrentThread(); if (count >= capacity) return false; - ++count; Node l = last; Node x = new Node(e, l, null); last = x; @@ -181,6 +243,7 @@ public class LinkedBlockingDeque first = x; else l.next = x; + ++count; notEmpty.signal(); return true; } @@ -189,10 +252,14 @@ public class LinkedBlockingDeque * Removes and returns first element, or null if empty. */ private E unlinkFirst() { + // assert lock.isHeldByCurrentThread(); Node f = first; if (f == null) return null; Node n = f.next; + E item = f.item; + f.item = null; + f.next = f; // help GC first = n; if (n == null) last = null; @@ -200,17 +267,21 @@ public class LinkedBlockingDeque n.prev = null; --count; notFull.signal(); - return f.item; + return item; } /** * Removes and returns last element, or null if empty. */ private E unlinkLast() { + // assert lock.isHeldByCurrentThread(); Node l = last; if (l == null) return null; Node p = l.prev; + E item = l.item; + l.item = null; + l.prev = l; // help GC last = p; if (p == null) first = null; @@ -218,31 +289,29 @@ public class LinkedBlockingDeque p.next = null; --count; notFull.signal(); - return l.item; + return item; } /** - * Unlink e + * Unlinks x. */ - private void unlink(Node x) { + void unlink(Node x) { + // assert lock.isHeldByCurrentThread(); Node p = x.prev; Node n = x.next; if (p == null) { - if (n == null) - first = last = null; - else { - n.prev = null; - first = n; - } + unlinkFirst(); } else if (n == null) { - p.next = null; - last = p; + unlinkLast(); } else { p.next = n; n.prev = p; + x.item = null; + // Don't mess with x's links. They may still be in use by + // an iterator. + --count; + notFull.signal(); } - --count; - notFull.signalAll(); } // BlockingDeque methods @@ -270,6 +339,7 @@ public class LinkedBlockingDeque */ public boolean offerFirst(E e) { if (e == null) throw new NullPointerException(); + final ReentrantLock lock = this.lock; lock.lock(); try { return linkFirst(e); @@ -283,6 +353,7 @@ public class LinkedBlockingDeque */ public boolean offerLast(E e) { if (e == null) throw new NullPointerException(); + final ReentrantLock lock = this.lock; lock.lock(); try { return linkLast(e); @@ -297,6 +368,7 @@ public class LinkedBlockingDeque */ public void putFirst(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); + final ReentrantLock lock = this.lock; lock.lock(); try { while (!linkFirst(e)) @@ -312,6 +384,7 @@ public class LinkedBlockingDeque */ public void putLast(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); + final ReentrantLock lock = this.lock; lock.lock(); try { while (!linkLast(e)) @@ -329,15 +402,15 @@ public class LinkedBlockingDeque throws InterruptedException { if (e == null) throw new NullPointerException(); long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - if (linkFirst(e)) - return true; + while (!linkFirst(e)) { if (nanos <= 0) return false; nanos = notFull.awaitNanos(nanos); } + return true; } finally { lock.unlock(); } @@ -351,15 +424,15 @@ public class LinkedBlockingDeque throws InterruptedException { if (e == null) throw new NullPointerException(); long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - if (linkLast(e)) - return true; + while (!linkLast(e)) { if (nanos <= 0) return false; nanos = notFull.awaitNanos(nanos); } + return true; } finally { lock.unlock(); } @@ -384,6 +457,7 @@ public class LinkedBlockingDeque } public E pollFirst() { + final ReentrantLock lock = this.lock; lock.lock(); try { return unlinkFirst(); @@ -393,6 +467,7 @@ public class LinkedBlockingDeque } public E pollLast() { + final ReentrantLock lock = this.lock; lock.lock(); try { return unlinkLast(); @@ -402,6 +477,7 @@ public class LinkedBlockingDeque } public E takeFirst() throws InterruptedException { + final ReentrantLock lock = this.lock; lock.lock(); try { E x; @@ -414,6 +490,7 @@ public class LinkedBlockingDeque } public E takeLast() throws InterruptedException { + final ReentrantLock lock = this.lock; lock.lock(); try { E x; @@ -428,16 +505,16 @@ public class LinkedBlockingDeque public E pollFirst(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - E x = unlinkFirst(); - if (x != null) - return x; + E x; + while ( (x = unlinkFirst()) == null) { if (nanos <= 0) return null; nanos = notEmpty.awaitNanos(nanos); } + return x; } finally { lock.unlock(); } @@ -446,16 +523,16 @@ public class LinkedBlockingDeque public E pollLast(long timeout, TimeUnit unit) throws InterruptedException { long nanos = unit.toNanos(timeout); + final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { - for (;;) { - E x = unlinkLast(); - if (x != null) - return x; + E x; + while ( (x = unlinkLast()) == null) { if (nanos <= 0) return null; nanos = notEmpty.awaitNanos(nanos); } + return x; } finally { lock.unlock(); } @@ -480,6 +557,7 @@ public class LinkedBlockingDeque } public E peekFirst() { + final ReentrantLock lock = this.lock; lock.lock(); try { return (first == null) ? null : first.item; @@ -489,6 +567,7 @@ public class LinkedBlockingDeque } public E peekLast() { + final ReentrantLock lock = this.lock; lock.lock(); try { return (last == null) ? null : last.item; @@ -499,6 +578,7 @@ public class LinkedBlockingDeque public boolean removeFirstOccurrence(Object o) { if (o == null) return false; + final ReentrantLock lock = this.lock; lock.lock(); try { for (Node p = first; p != null; p = p.next) { @@ -515,6 +595,7 @@ public class LinkedBlockingDeque public boolean removeLastOccurrence(Object o) { if (o == null) return false; + final ReentrantLock lock = this.lock; lock.lock(); try { for (Node p = last; p != null; p = p.prev) { @@ -619,14 +700,15 @@ public class LinkedBlockingDeque * Returns the number of additional elements that this deque can ideally * (in the absence of memory or resource constraints) accept without * blocking. This is always equal to the initial capacity of this deque - * less the current size of this deque. + * less the current {@code size} of this deque. * *

Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting remainingCapacity + * an element will succeed by inspecting {@code remainingCapacity} * because it may be the case that another thread is about to * insert or remove an element. */ public int remainingCapacity() { + final ReentrantLock lock = this.lock; lock.lock(); try { return capacity - count; @@ -642,22 +724,7 @@ public class LinkedBlockingDeque * @throws IllegalArgumentException {@inheritDoc} */ public int drainTo(Collection c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - lock.lock(); - try { - for (Node p = first; p != null; p = p.next) - c.add(p.item); - int n = count; - count = 0; - first = last = null; - notFull.signalAll(); - return n; - } finally { - lock.unlock(); - } + return drainTo(c, Integer.MAX_VALUE); } /** @@ -671,19 +738,14 @@ public class LinkedBlockingDeque throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); + final ReentrantLock lock = this.lock; lock.lock(); try { - int n = 0; - while (n < maxElements && first != null) { - c.add(first.item); - first.prev = null; - first = first.next; - --count; - ++n; + int n = Math.min(maxElements, count); + for (int i = 0; i < n; i++) { + c.add(first.item); // In this order, in case add() throws. + unlinkFirst(); } - if (first == null) - last = null; - notFull.signalAll(); return n; } finally { lock.unlock(); @@ -712,16 +774,16 @@ public class LinkedBlockingDeque /** * Removes the first occurrence of the specified element from this deque. * If the deque does not contain the element, it is unchanged. - * More formally, removes the first element e such that - * o.equals(e) (if such an element exists). - * Returns true if this deque contained the specified element + * More formally, removes the first element {@code e} such that + * {@code o.equals(e)} (if such an element exists). + * Returns {@code true} if this deque contained the specified element * (or equivalently, if this deque changed as a result of the call). * *

This method is equivalent to * {@link #removeFirstOccurrence(Object) removeFirstOccurrence}. * * @param o element to be removed from this deque, if present - * @return true if this deque changed as a result of the call + * @return {@code true} if this deque changed as a result of the call */ public boolean remove(Object o) { return removeFirstOccurrence(o); @@ -733,6 +795,7 @@ public class LinkedBlockingDeque * @return the number of elements in this deque */ public int size() { + final ReentrantLock lock = this.lock; lock.lock(); try { return count; @@ -742,15 +805,16 @@ public class LinkedBlockingDeque } /** - * Returns true if this deque contains the specified element. - * More formally, returns true if and only if this deque contains - * at least one element e such that o.equals(e). + * Returns {@code true} if this deque contains the specified element. + * More formally, returns {@code true} if and only if this deque contains + * at least one element {@code e} such that {@code o.equals(e)}. * * @param o object to be checked for containment in this deque - * @return true if this deque contains the specified element + * @return {@code true} if this deque contains the specified element */ public boolean contains(Object o) { if (o == null) return false; + final ReentrantLock lock = this.lock; lock.lock(); try { for (Node p = first; p != null; p = p.next) @@ -762,24 +826,46 @@ public class LinkedBlockingDeque } } - /** - * Variant of removeFirstOccurrence needed by iterator.remove. - * Searches for the node, not its contents. + /* + * TODO: Add support for more efficient bulk operations. + * + * We don't want to acquire the lock for every iteration, but we + * also want other threads a chance to interact with the + * collection, especially when count is close to capacity. */ - boolean removeNode(Node e) { - lock.lock(); - try { - for (Node p = first; p != null; p = p.next) { - if (p == e) { - unlink(p); - return true; - } - } - return false; - } finally { - lock.unlock(); - } - } + +// /** +// * Adds all of the elements in the specified collection to this +// * queue. Attempts to addAll of a queue to itself result in +// * {@code IllegalArgumentException}. Further, the behavior of +// * this operation is undefined if the specified collection is +// * modified while the operation is in progress. +// * +// * @param c collection containing elements to be added to this queue +// * @return {@code true} if this queue changed as a result of the call +// * @throws ClassCastException {@inheritDoc} +// * @throws NullPointerException {@inheritDoc} +// * @throws IllegalArgumentException {@inheritDoc} +// * @throws IllegalStateException {@inheritDoc} +// * @see #add(Object) +// */ +// public boolean addAll(Collection c) { +// if (c == null) +// throw new NullPointerException(); +// if (c == this) +// throw new IllegalArgumentException(); +// final ReentrantLock lock = this.lock; +// lock.lock(); +// try { +// boolean modified = false; +// for (E e : c) +// if (linkLast(e)) +// modified = true; +// return modified; +// } finally { +// lock.unlock(); +// } +// } /** * Returns an array containing all of the elements in this deque, in @@ -794,7 +880,9 @@ public class LinkedBlockingDeque * * @return an array containing all of the elements in this deque */ + @SuppressWarnings("unchecked") public Object[] toArray() { + final ReentrantLock lock = this.lock; lock.lock(); try { Object[] a = new Object[count]; @@ -817,22 +905,22 @@ public class LinkedBlockingDeque *

If this deque fits in the specified array with room to spare * (i.e., the array has more elements than this deque), the element in * the array immediately following the end of the deque is set to - * null. + * {@code null}. * *

Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

Suppose x is a deque known to contain only strings. + *

Suppose {@code x} is a deque known to contain only strings. * The following code can be used to dump the deque into a newly - * allocated array of String: + * allocated array of {@code String}: * *

      *     String[] y = x.toArray(new String[0]);
* - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the deque are to * be stored, if it is big enough; otherwise, a new array of the @@ -843,14 +931,14 @@ public class LinkedBlockingDeque * this deque * @throws NullPointerException if the specified array is null */ + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { + final ReentrantLock lock = this.lock; lock.lock(); try { if (a.length < count) - a = (T[])java.lang.reflect.Array.newInstance( - a.getClass().getComponentType(), - count - ); + a = (T[])java.lang.reflect.Array.newInstance + (a.getClass().getComponentType(), count); int k = 0; for (Node p = first; p != null; p = p.next) @@ -864,6 +952,7 @@ public class LinkedBlockingDeque } public String toString() { + final ReentrantLock lock = this.lock; lock.lock(); try { return super.toString(); @@ -877,8 +966,16 @@ public class LinkedBlockingDeque * The deque will be empty after this call returns. */ public void clear() { + final ReentrantLock lock = this.lock; lock.lock(); try { + for (Node f = first; f != null; ) { + f.item = null; + Node n = f.next; + f.prev = null; + f.next = null; + f = n; + } first = last = null; count = 0; notFull.signalAll(); @@ -890,7 +987,7 @@ public class LinkedBlockingDeque /** * Returns an iterator over the elements in this deque in proper sequence. * The elements will be returned in order from first (head) to last (tail). - * The returned Iterator is a "weakly consistent" iterator that + * The returned {@code Iterator} is a "weakly consistent" iterator that * will never throw {@link ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) @@ -906,7 +1003,7 @@ public class LinkedBlockingDeque * Returns an iterator over the elements in this deque in reverse * sequential order. The elements will be returned in order from * last (tail) to first (head). - * The returned Iterator is a "weakly consistent" iterator that + * The returned {@code Iterator} is a "weakly consistent" iterator that * will never throw {@link ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) @@ -921,7 +1018,7 @@ public class LinkedBlockingDeque */ private abstract class AbstractItr implements Iterator { /** - * The next node to return in next + * The next node to return in next() */ Node next; @@ -939,15 +1036,44 @@ public class LinkedBlockingDeque */ private Node lastRet; + abstract Node firstNode(); + abstract Node nextNode(Node n); + AbstractItr() { - advance(); // set to initial position + // set to initial position + final ReentrantLock lock = LinkedBlockingDeque.this.lock; + lock.lock(); + try { + next = firstNode(); + nextItem = (next == null) ? null : next.item; + } finally { + lock.unlock(); + } } /** - * Advances next, or if not yet initialized, sets to first node. - * Implemented to move forward vs backward in the two subclasses. + * Advances next. */ - abstract void advance(); + void advance() { + final ReentrantLock lock = LinkedBlockingDeque.this.lock; + lock.lock(); + try { + // assert next != null; + Node s = nextNode(next); + if (s == next) { + next = firstNode(); + } else { + // Skip over removed nodes. + // May be necessary if multiple interior Nodes are removed. + while (s != null && s.item == null) + s = nextNode(s); + next = s; + } + nextItem = (next == null) ? null : next.item; + } finally { + lock.unlock(); + } + } public boolean hasNext() { return next != null; @@ -967,52 +1093,39 @@ public class LinkedBlockingDeque if (n == null) throw new IllegalStateException(); lastRet = null; - // Note: removeNode rescans looking for this node to make - // sure it was not already removed. Otherwise, trying to - // re-remove could corrupt list. - removeNode(n); + final ReentrantLock lock = LinkedBlockingDeque.this.lock; + lock.lock(); + try { + if (n.item != null) + unlink(n); + } finally { + lock.unlock(); + } } } /** Forward iterator */ private class Itr extends AbstractItr { - void advance() { - final ReentrantLock lock = LinkedBlockingDeque.this.lock; - lock.lock(); - try { - next = (next == null)? first : next.next; - nextItem = (next == null)? null : next.item; - } finally { - lock.unlock(); - } - } + Node firstNode() { return first; } + Node nextNode(Node n) { return n.next; } } - /** - * Descending iterator for LinkedBlockingDeque - */ + /** Descending iterator */ private class DescendingItr extends AbstractItr { - void advance() { - final ReentrantLock lock = LinkedBlockingDeque.this.lock; - lock.lock(); - try { - next = (next == null)? last : next.prev; - nextItem = (next == null)? null : next.item; - } finally { - lock.unlock(); - } - } + Node firstNode() { return last; } + Node nextNode(Node n) { return n.prev; } } /** * Save the state of this deque to a stream (that is, serialize it). * * @serialData The capacity (int), followed by elements (each an - * Object) in the proper order, followed by a null + * {@code Object}) in the proper order, followed by a null * @param s the stream */ private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { + final ReentrantLock lock = this.lock; lock.lock(); try { // Write out capacity and any hidden stuff @@ -1040,6 +1153,7 @@ public class LinkedBlockingDeque last = null; // Read in all elements and place in queue for (;;) { + @SuppressWarnings("unchecked") E item = (E)s.readObject(); if (item == null) break; diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java index dc56a034665..9c1c6cc7b1f 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -34,9 +34,14 @@ */ package java.util.concurrent; -import java.util.concurrent.atomic.*; -import java.util.concurrent.locks.*; -import java.util.*; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; +import java.util.AbstractQueue; +import java.util.Collection; +import java.util.Iterator; +import java.util.NoSuchElementException; /** * An optionally-bounded {@linkplain BlockingQueue blocking queue} based on @@ -86,15 +91,43 @@ public class LinkedBlockingQueue extends AbstractQueue * items have been entered since the signal. And symmetrically for * takes signalling puts. Operations such as remove(Object) and * iterators acquire both locks. + * + * Visibility between writers and readers is provided as follows: + * + * Whenever an element is enqueued, the putLock is acquired and + * count updated. A subsequent reader guarantees visibility to the + * enqueued Node by either acquiring the putLock (via fullyLock) + * or by acquiring the takeLock, and then reading n = count.get(); + * this gives visibility to the first n items. + * + * To implement weakly consistent iterators, it appears we need to + * keep all Nodes GC-reachable from a predecessor dequeued Node. + * That would cause two problems: + * - allow a rogue Iterator to cause unbounded memory retention + * - cause cross-generational linking of old Nodes to new Nodes if + * a Node was tenured while live, which generational GCs have a + * hard time dealing with, causing repeated major collections. + * However, only non-deleted Nodes need to be reachable from + * dequeued Nodes, and reachability does not necessarily have to + * be of the kind understood by the GC. We use the trick of + * linking a Node that has just been dequeued to itself. Such a + * self-link implicitly means to advance to head.next. */ /** * Linked list node class */ static class Node { - /** The item, volatile to ensure barrier separating write and read */ - volatile E item; + E item; + + /** + * One of: + * - the real successor Node + * - this Node, meaning the successor is head.next + * - null, meaning there is no successor (this is the last node) + */ Node next; + Node(E x) { item = x; } } @@ -104,10 +137,16 @@ public class LinkedBlockingQueue extends AbstractQueue /** Current number of elements */ private final AtomicInteger count = new AtomicInteger(0); - /** Head of linked list */ + /** + * Head of linked list. + * Invariant: head.item == null + */ private transient Node head; - /** Tail of linked list */ + /** + * Tail of linked list. + * Invariant: last.next == null + */ private transient Node last; /** Lock held by take, poll, etc */ @@ -151,18 +190,26 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Creates a node and links it at end of queue. + * * @param x the item */ - private void insert(E x) { + private void enqueue(E x) { + // assert putLock.isHeldByCurrentThread(); + // assert last.next == null; last = last.next = new Node(x); } /** - * Removes a node from head of queue, + * Removes a node from head of queue. + * * @return the node */ - private E extract() { - Node first = head.next; + private E dequeue() { + // assert takeLock.isHeldByCurrentThread(); + // assert head.item == null; + Node h = head; + Node first = h.next; + h.next = h; // help GC head = first; E x = first.item; first.item = null; @@ -172,7 +219,7 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Lock to prevent both puts and takes. */ - private void fullyLock() { + void fullyLock() { putLock.lock(); takeLock.lock(); } @@ -180,14 +227,21 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Unlock to allow both puts and takes. */ - private void fullyUnlock() { + void fullyUnlock() { takeLock.unlock(); putLock.unlock(); } +// /** +// * Tells whether both locks are held by current thread. +// */ +// boolean isFullyLocked() { +// return (putLock.isHeldByCurrentThread() && +// takeLock.isHeldByCurrentThread()); +// } /** - * Creates a LinkedBlockingQueue with a capacity of + * Creates a {@code LinkedBlockingQueue} with a capacity of * {@link Integer#MAX_VALUE}. */ public LinkedBlockingQueue() { @@ -195,10 +249,10 @@ public class LinkedBlockingQueue extends AbstractQueue } /** - * Creates a LinkedBlockingQueue with the given (fixed) capacity. + * Creates a {@code LinkedBlockingQueue} with the given (fixed) capacity. * * @param capacity the capacity of this queue - * @throws IllegalArgumentException if capacity is not greater + * @throws IllegalArgumentException if {@code capacity} is not greater * than zero */ public LinkedBlockingQueue(int capacity) { @@ -208,7 +262,7 @@ public class LinkedBlockingQueue extends AbstractQueue } /** - * Creates a LinkedBlockingQueue with a capacity of + * Creates a {@code LinkedBlockingQueue} with a capacity of * {@link Integer#MAX_VALUE}, initially containing the elements of the * given collection, * added in traversal order of the collection's iterator. @@ -219,8 +273,22 @@ public class LinkedBlockingQueue extends AbstractQueue */ public LinkedBlockingQueue(Collection c) { this(Integer.MAX_VALUE); - for (E e : c) - add(e); + final ReentrantLock putLock = this.putLock; + putLock.lock(); // Never contended, but necessary for visibility + try { + int n = 0; + for (E e : c) { + if (e == null) + throw new NullPointerException(); + if (n == capacity) + throw new IllegalStateException("Queue full"); + enqueue(e); + ++n; + } + count.set(n); + } finally { + putLock.unlock(); + } } @@ -241,10 +309,10 @@ public class LinkedBlockingQueue extends AbstractQueue * Returns the number of additional elements that this queue can ideally * (in the absence of memory or resource constraints) accept without * blocking. This is always equal to the initial capacity of this queue - * less the current size of this queue. + * less the current {@code size} of this queue. * *

Note that you cannot always tell if an attempt to insert - * an element will succeed by inspecting remainingCapacity + * an element will succeed by inspecting {@code remainingCapacity} * because it may be the case that another thread is about to * insert or remove an element. */ @@ -261,8 +329,8 @@ public class LinkedBlockingQueue extends AbstractQueue */ public void put(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); - // Note: convention in all put/take/etc is to preset - // local var holding count negative to indicate failure unless set. + // Note: convention in all put/take/etc is to preset local var + // holding count negative to indicate failure unless set. int c = -1; final ReentrantLock putLock = this.putLock; final AtomicInteger count = this.count; @@ -273,18 +341,13 @@ public class LinkedBlockingQueue extends AbstractQueue * not protected by lock. This works because count can * only decrease at this point (all other puts are shut * out by lock), and we (or some other waiting put) are - * signalled if it ever changes from - * capacity. Similarly for all other uses of count in - * other wait guards. + * signalled if it ever changes from capacity. Similarly + * for all other uses of count in other wait guards. */ - try { - while (count.get() == capacity) - notFull.await(); - } catch (InterruptedException ie) { - notFull.signal(); // propagate to a non-interrupted thread - throw ie; + while (count.get() == capacity) { + notFull.await(); } - insert(e); + enqueue(e); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -299,7 +362,7 @@ public class LinkedBlockingQueue extends AbstractQueue * Inserts the specified element at the tail of this queue, waiting if * necessary up to the specified wait time for space to become available. * - * @return true if successful, or false if + * @return {@code true} if successful, or {@code false} if * the specified waiting time elapses before space is available. * @throws InterruptedException {@inheritDoc} * @throws NullPointerException {@inheritDoc} @@ -314,23 +377,15 @@ public class LinkedBlockingQueue extends AbstractQueue final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { - for (;;) { - if (count.get() < capacity) { - insert(e); - c = count.getAndIncrement(); - if (c + 1 < capacity) - notFull.signal(); - break; - } + while (count.get() == capacity) { if (nanos <= 0) return false; - try { - nanos = notFull.awaitNanos(nanos); - } catch (InterruptedException ie) { - notFull.signal(); // propagate to a non-interrupted thread - throw ie; - } + nanos = notFull.awaitNanos(nanos); } + enqueue(e); + c = count.getAndIncrement(); + if (c + 1 < capacity) + notFull.signal(); } finally { putLock.unlock(); } @@ -342,7 +397,7 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Inserts the specified element at the tail of this queue if it is * possible to do so immediately without exceeding the queue's capacity, - * returning true upon success and false if this queue + * returning {@code true} upon success and {@code false} if this queue * is full. * When using a capacity-restricted queue, this method is generally * preferable to method {@link BlockingQueue#add add}, which can fail to @@ -360,7 +415,7 @@ public class LinkedBlockingQueue extends AbstractQueue putLock.lock(); try { if (count.get() < capacity) { - insert(e); + enqueue(e); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); @@ -381,15 +436,10 @@ public class LinkedBlockingQueue extends AbstractQueue final ReentrantLock takeLock = this.takeLock; takeLock.lockInterruptibly(); try { - try { - while (count.get() == 0) - notEmpty.await(); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to a non-interrupted thread - throw ie; + while (count.get() == 0) { + notEmpty.await(); } - - x = extract(); + x = dequeue(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); @@ -409,23 +459,15 @@ public class LinkedBlockingQueue extends AbstractQueue final ReentrantLock takeLock = this.takeLock; takeLock.lockInterruptibly(); try { - for (;;) { - if (count.get() > 0) { - x = extract(); - c = count.getAndDecrement(); - if (c > 1) - notEmpty.signal(); - break; - } + while (count.get() == 0) { if (nanos <= 0) return null; - try { - nanos = notEmpty.awaitNanos(nanos); - } catch (InterruptedException ie) { - notEmpty.signal(); // propagate to a non-interrupted thread - throw ie; - } + nanos = notEmpty.awaitNanos(nanos); } + x = dequeue(); + c = count.getAndDecrement(); + if (c > 1) + notEmpty.signal(); } finally { takeLock.unlock(); } @@ -444,7 +486,7 @@ public class LinkedBlockingQueue extends AbstractQueue takeLock.lock(); try { if (count.get() > 0) { - x = extract(); + x = dequeue(); c = count.getAndDecrement(); if (c > 1) notEmpty.signal(); @@ -457,7 +499,6 @@ public class LinkedBlockingQueue extends AbstractQueue return x; } - public E peek() { if (count.get() == 0) return null; @@ -474,44 +515,48 @@ public class LinkedBlockingQueue extends AbstractQueue } } + /** + * Unlinks interior Node p with predecessor trail. + */ + void unlink(Node p, Node trail) { + // assert isFullyLocked(); + // p.next is not changed, to allow iterators that are + // traversing p to maintain their weak-consistency guarantee. + p.item = null; + trail.next = p.next; + if (last == p) + last = trail; + if (count.getAndDecrement() == capacity) + notFull.signal(); + } + /** * Removes a single instance of the specified element from this queue, - * if it is present. More formally, removes an element e such - * that o.equals(e), if this queue contains one or more such + * if it is present. More formally, removes an element {@code e} such + * that {@code o.equals(e)}, if this queue contains one or more such * elements. - * Returns true if this queue contained the specified element + * Returns {@code true} if this queue contained the specified element * (or equivalently, if this queue changed as a result of the call). * * @param o element to be removed from this queue, if present - * @return true if this queue changed as a result of the call + * @return {@code true} if this queue changed as a result of the call */ public boolean remove(Object o) { if (o == null) return false; - boolean removed = false; fullyLock(); try { - Node trail = head; - Node p = head.next; - while (p != null) { + for (Node trail = head, p = trail.next; + p != null; + trail = p, p = p.next) { if (o.equals(p.item)) { - removed = true; - break; + unlink(p, trail); + return true; } - trail = p; - p = p.next; - } - if (removed) { - p.item = null; - trail.next = p.next; - if (last == p) - last = trail; - if (count.getAndDecrement() == capacity) - notFull.signalAll(); } + return false; } finally { fullyUnlock(); } - return removed; } /** @@ -551,22 +596,22 @@ public class LinkedBlockingQueue extends AbstractQueue *

If this queue fits in the specified array with room to spare * (i.e., the array has more elements than this queue), the element in * the array immediately following the end of the queue is set to - * null. + * {@code null}. * *

Like the {@link #toArray()} method, this method acts as bridge between * array-based and collection-based APIs. Further, this method allows * precise control over the runtime type of the output array, and may, * under certain circumstances, be used to save allocation costs. * - *

Suppose x is a queue known to contain only strings. + *

Suppose {@code x} is a queue known to contain only strings. * The following code can be used to dump the queue into a newly - * allocated array of String: + * allocated array of {@code String}: * *

      *     String[] y = x.toArray(new String[0]);
* - * Note that toArray(new Object[0]) is identical in function to - * toArray(). + * Note that {@code toArray(new Object[0])} is identical in function to + * {@code toArray()}. * * @param a the array into which the elements of the queue are to * be stored, if it is big enough; otherwise, a new array of the @@ -577,6 +622,7 @@ public class LinkedBlockingQueue extends AbstractQueue * this queue * @throws NullPointerException if the specified array is null */ + @SuppressWarnings("unchecked") public T[] toArray(T[] a) { fullyLock(); try { @@ -586,7 +632,7 @@ public class LinkedBlockingQueue extends AbstractQueue (a.getClass().getComponentType(), size); int k = 0; - for (Node p = head.next; p != null; p = p.next) + for (Node p = head.next; p != null; p = p.next) a[k++] = (T)p.item; if (a.length > k) a[k] = null; @@ -612,11 +658,14 @@ public class LinkedBlockingQueue extends AbstractQueue public void clear() { fullyLock(); try { - head.next = null; - assert head.item == null; - last = head; + for (Node p, h = head; (p = h.next) != null; h = p) { + h.next = h; + p.item = null; + } + head = last; + // assert head.item == null && head.next == null; if (count.getAndSet(0) == capacity) - notFull.signalAll(); + notFull.signal(); } finally { fullyUnlock(); } @@ -629,30 +678,7 @@ public class LinkedBlockingQueue extends AbstractQueue * @throws IllegalArgumentException {@inheritDoc} */ public int drainTo(Collection c) { - if (c == null) - throw new NullPointerException(); - if (c == this) - throw new IllegalArgumentException(); - Node first; - fullyLock(); - try { - first = head.next; - head.next = null; - assert head.item == null; - last = head; - if (count.getAndSet(0) == capacity) - notFull.signalAll(); - } finally { - fullyUnlock(); - } - // Transfer the elements outside of locks - int n = 0; - for (Node p = first; p != null; p = p.next) { - c.add(p.item); - p.item = null; - ++n; - } - return n; + return drainTo(c, Integer.MAX_VALUE); } /** @@ -666,33 +692,42 @@ public class LinkedBlockingQueue extends AbstractQueue throw new NullPointerException(); if (c == this) throw new IllegalArgumentException(); - fullyLock(); + boolean signalNotFull = false; + final ReentrantLock takeLock = this.takeLock; + takeLock.lock(); try { - int n = 0; - Node p = head.next; - while (p != null && n < maxElements) { - c.add(p.item); - p.item = null; - p = p.next; - ++n; + int n = Math.min(maxElements, count.get()); + // count.get provides visibility to first n Nodes + Node h = head; + int i = 0; + try { + while (i < n) { + Node p = h.next; + c.add(p.item); + p.item = null; + h.next = h; + h = p; + ++i; + } + return n; + } finally { + // Restore invariants even if c.add() threw + if (i > 0) { + // assert h.item == null; + head = h; + signalNotFull = (count.getAndAdd(-i) == capacity); + } } - if (n != 0) { - head.next = p; - assert head.item == null; - if (p == null) - last = head; - if (count.getAndAdd(-n) == capacity) - notFull.signalAll(); - } - return n; } finally { - fullyUnlock(); + takeLock.unlock(); + if (signalNotFull) + signalNotFull(); } } /** * Returns an iterator over the elements in this queue in proper sequence. - * The returned Iterator is a "weakly consistent" iterator that + * The returned {@code Iterator} is a "weakly consistent" iterator that * will never throw {@link ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) @@ -706,7 +741,7 @@ public class LinkedBlockingQueue extends AbstractQueue private class Itr implements Iterator { /* - * Basic weak-consistent iterator. At all times hold the next + * Basic weakly-consistent iterator. At all times hold the next * item to hand out so that if hasNext() reports true, we will * still have it to return even if lost race with a take etc. */ @@ -715,17 +750,13 @@ public class LinkedBlockingQueue extends AbstractQueue private E currentElement; Itr() { - final ReentrantLock putLock = LinkedBlockingQueue.this.putLock; - final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock; - putLock.lock(); - takeLock.lock(); + fullyLock(); try { current = head.next; if (current != null) currentElement = current.item; } finally { - takeLock.unlock(); - putLock.unlock(); + fullyUnlock(); } } @@ -733,54 +764,54 @@ public class LinkedBlockingQueue extends AbstractQueue return current != null; } + /** + * Unlike other traversal methods, iterators need to handle: + * - dequeued nodes (p.next == p) + * - interior removed nodes (p.item == null) + */ + private Node nextNode(Node p) { + Node s = p.next; + if (p == s) + return head.next; + // Skip over removed nodes. + // May be necessary if multiple interior Nodes are removed. + while (s != null && s.item == null) + s = s.next; + return s; + } + public E next() { - final ReentrantLock putLock = LinkedBlockingQueue.this.putLock; - final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock; - putLock.lock(); - takeLock.lock(); + fullyLock(); try { if (current == null) throw new NoSuchElementException(); E x = currentElement; lastRet = current; - current = current.next; - if (current != null) - currentElement = current.item; + current = nextNode(current); + currentElement = (current == null) ? null : current.item; return x; } finally { - takeLock.unlock(); - putLock.unlock(); + fullyUnlock(); } } public void remove() { if (lastRet == null) throw new IllegalStateException(); - final ReentrantLock putLock = LinkedBlockingQueue.this.putLock; - final ReentrantLock takeLock = LinkedBlockingQueue.this.takeLock; - putLock.lock(); - takeLock.lock(); + fullyLock(); try { Node node = lastRet; lastRet = null; - Node trail = head; - Node p = head.next; - while (p != null && p != node) { - trail = p; - p = p.next; - } - if (p == node) { - p.item = null; - trail.next = p.next; - if (last == p) - last = trail; - int c = count.getAndDecrement(); - if (c == capacity) - notFull.signalAll(); + for (Node trail = head, p = trail.next; + p != null; + trail = p, p = p.next) { + if (p == node) { + unlink(p, trail); + break; + } } } finally { - takeLock.unlock(); - putLock.unlock(); + fullyUnlock(); } } } @@ -789,7 +820,7 @@ public class LinkedBlockingQueue extends AbstractQueue * Save the state to a stream (that is, serialize it). * * @serialData The capacity is emitted (int), followed by all of - * its elements (each an Object) in the proper order, + * its elements (each an {@code Object}) in the proper order, * followed by a null * @param s the stream */ @@ -815,6 +846,7 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Reconstitute this queue instance from a stream (that is, * deserialize it). + * * @param s the stream */ private void readObject(java.io.ObjectInputStream s) @@ -827,6 +859,7 @@ public class LinkedBlockingQueue extends AbstractQueue // Read in all elements and place in queue for (;;) { + @SuppressWarnings("unchecked") E item = (E)s.readObject(); if (item == null) break; diff --git a/jdk/test/java/util/Collection/MOAT.java b/jdk/test/java/util/Collection/MOAT.java index f9d30f56217..d2b6b686903 100644 --- a/jdk/test/java/util/Collection/MOAT.java +++ b/jdk/test/java/util/Collection/MOAT.java @@ -426,6 +426,36 @@ public class MOAT { q.poll(); equal(q.size(), 4); checkFunctionalInvariants(q); + if ((q instanceof LinkedBlockingQueue) || + (q instanceof LinkedBlockingDeque) || + (q instanceof ConcurrentLinkedQueue)) { + testQueueIteratorRemove(q); + } + } + + private static void testQueueIteratorRemove(Queue q) { + System.err.printf("testQueueIteratorRemove %s%n", + q.getClass().getSimpleName()); + q.clear(); + for (int i = 0; i < 5; i++) + q.add(i); + Iterator it = q.iterator(); + check(it.hasNext()); + for (int i = 3; i >= 0; i--) + q.remove(i); + equal(it.next(), 0); + equal(it.next(), 4); + + q.clear(); + for (int i = 0; i < 5; i++) + q.add(i); + it = q.iterator(); + equal(it.next(), 0); + check(it.hasNext()); + for (int i = 1; i < 4; i++) + q.remove(i); + equal(it.next(), 1); + equal(it.next(), 4); } private static void testList(final List l) { @@ -451,6 +481,11 @@ public class MOAT { } private static void testCollection(Collection c) { + try { testCollection1(c); } + catch (Throwable t) { unexpected(t); } + } + + private static void testCollection1(Collection c) { System.out.println("\n==> " + c.getClass().getName()); diff --git a/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java new file mode 100644 index 00000000000..eb85f7bb3ab --- /dev/null +++ b/jdk/test/java/util/concurrent/BlockingQueue/OfferDrainToLoops.java @@ -0,0 +1,130 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +/* + * @test + * @bug 6805775 6815766 + * @summary Test concurrent offer vs. drainTo + */ + +import java.util.*; +import java.util.concurrent.*; + +@SuppressWarnings({"unchecked", "rawtypes"}) +public class OfferDrainToLoops { + void checkNotContainsNull(Iterable it) { + for (Object x : it) + check(x != null); + } + + abstract class CheckedThread extends Thread { + abstract protected void realRun(); + public void run() { + try { realRun(); } catch (Throwable t) { unexpected(t); } + } + { + setDaemon(true); + start(); + } + } + + void test(String[] args) throws Throwable { + test(new LinkedBlockingQueue()); + test(new LinkedBlockingQueue(2000)); + test(new LinkedBlockingDeque()); + test(new LinkedBlockingDeque(2000)); + test(new ArrayBlockingQueue(2000)); + } + + void test(final BlockingQueue q) throws Throwable { + System.out.println(q.getClass().getSimpleName()); + final long testDurationSeconds = 1L; + final long testDurationMillis = testDurationSeconds * 1000L; + final long quittingTimeNanos + = System.nanoTime() + testDurationSeconds * 1000L * 1000L * 1000L; + + Thread offerer = new CheckedThread() { + protected void realRun() { + for (long i = 0; ; i++) { + if ((i % 1024) == 0 && + System.nanoTime() - quittingTimeNanos > 0) + break; + while (! q.offer(i)) + Thread.yield(); + }}}; + + Thread drainer = new CheckedThread() { + protected void realRun() { + for (long i = 0; ; i++) { + if (System.nanoTime() - quittingTimeNanos > 0) + break; + List list = new ArrayList(); + int n = q.drainTo(list); + equal(list.size(), n); + for (int j = 0; j < n - 1; j++) + equal((Long) list.get(j) + 1L, list.get(j + 1)); + Thread.yield(); + }}}; + + Thread scanner = new CheckedThread() { + protected void realRun() { + for (long i = 0; ; i++) { + if (System.nanoTime() - quittingTimeNanos > 0) + break; + checkNotContainsNull(q); + Thread.yield(); + }}}; + + offerer.join(10 * testDurationMillis); + drainer.join(10 * testDurationMillis); + check(! offerer.isAlive()); + check(! drainer.isAlive()); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + public static void main(String[] args) throws Throwable { + new OfferDrainToLoops().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java new file mode 100644 index 00000000000..727f6495651 --- /dev/null +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/IteratorWeakConsistency.java @@ -0,0 +1,93 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/licenses/publicdomain + */ + +import java.util.*; +import java.util.concurrent.*; + +/* + * @test + * @bug 6805775 6815766 + * @summary Check weak consistency of concurrent queue iterators + */ + +@SuppressWarnings({"unchecked", "rawtypes"}) +public class IteratorWeakConsistency { + + void test(String[] args) throws Throwable { + test(new LinkedBlockingQueue()); + test(new LinkedBlockingQueue(20)); + test(new LinkedBlockingDeque()); + test(new LinkedBlockingDeque(20)); + test(new ConcurrentLinkedQueue()); + // Other concurrent queues (e.g. ArrayBlockingQueue) do not + // currently have weakly consistent iterators. + // test(new ArrayBlockingQueue(20)); + } + + void test(Queue q) throws Throwable { + // TODO: make this more general + for (int i = 0; i < 10; i++) + q.add(i); + Iterator it = q.iterator(); + q.poll(); + q.poll(); + q.poll(); + q.remove(7); + List list = new ArrayList(); + while (it.hasNext()) + list.add(it.next()); + equal(list, Arrays.asList(0, 3, 4, 5, 6, 8, 9)); + check(! list.contains(null)); + System.out.printf("%s: %s%n", + q.getClass().getSimpleName(), + list); + } + + //--------------------- Infrastructure --------------------------- + volatile int passed = 0, failed = 0; + void pass() {passed++;} + void fail() {failed++; Thread.dumpStack();} + void fail(String msg) {System.err.println(msg); fail();} + void unexpected(Throwable t) {failed++; t.printStackTrace();} + void check(boolean cond) {if (cond) pass(); else fail();} + void equal(Object x, Object y) { + if (x == null ? y == null : x.equals(y)) pass(); + else fail(x + " not equal to " + y);} + static Class thisClass = new Object(){}.getClass().getEnclosingClass(); + public static void main(String[] args) throws Throwable { + new IteratorWeakConsistency().instanceMain(args);} + public void instanceMain(String[] args) throws Throwable { + try {test(args);} catch (Throwable t) {unexpected(t);} + System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); + if (failed > 0) throw new AssertionError("Some tests failed");} +} From 36736be8baa432ebfe0d7bfa0042496402d06459 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Wed, 29 Jul 2009 13:56:15 -0700 Subject: [PATCH 27/70] 6866554: Misc. javadoc warnings Reviewed-by: alanb --- .../share/classes/java/nio/channels/DatagramChannel.java | 2 +- jdk/src/share/classes/java/nio/channels/package-info.java | 4 ++-- jdk/src/share/classes/java/nio/file/DirectoryStream.java | 2 +- jdk/src/share/classes/java/nio/file/Path.java | 2 +- .../share/classes/java/nio/file/attribute/package-info.java | 4 ++-- .../classes/java/util/concurrent/ConcurrentLinkedQueue.java | 3 ++- .../classes/java/util/concurrent/LinkedBlockingDeque.java | 6 ++++-- .../classes/java/util/concurrent/LinkedBlockingQueue.java | 3 ++- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/jdk/src/share/classes/java/nio/channels/DatagramChannel.java b/jdk/src/share/classes/java/nio/channels/DatagramChannel.java index cbf402f5933..1dde1d7a399 100644 --- a/jdk/src/share/classes/java/nio/channels/DatagramChannel.java +++ b/jdk/src/share/classes/java/nio/channels/DatagramChannel.java @@ -421,7 +421,7 @@ public abstract class DatagramChannel * invocation of this method will block until the first operation is * complete. If this channel's socket is not bound then this method will * first cause the socket to be bound to an address that is assigned - * automatically, as if by invoking the {@link #bind bind) method with a + * automatically, as if by invoking the {@link #bind bind} method with a * parameter of {@code null}.

* * @param src diff --git a/jdk/src/share/classes/java/nio/channels/package-info.java b/jdk/src/share/classes/java/nio/channels/package-info.java index 47a1cb5f979..36a40840260 100644 --- a/jdk/src/share/classes/java/nio/channels/package-info.java +++ b/jdk/src/share/classes/java/nio/channels/package-info.java @@ -115,8 +115,8 @@ * Reads, writes, maps, and manipulates files * {@link java.nio.channels.FileLock} * A lock on a (region of a) file - * {@link java.nio.MappedByteBuffer}/{@link java.nio.MappedBigByteBuffer}   - * A direct byte buffer or big byte buffer mapped to a region of a file + * {@link java.nio.MappedByteBuffer}   + * A direct byte buffer mapped to a region of a file * * *

The {@link java.nio.channels.FileChannel} class supports the usual diff --git a/jdk/src/share/classes/java/nio/file/DirectoryStream.java b/jdk/src/share/classes/java/nio/file/DirectoryStream.java index 001f22b0723..f0be02172d6 100644 --- a/jdk/src/share/classes/java/nio/file/DirectoryStream.java +++ b/jdk/src/share/classes/java/nio/file/DirectoryStream.java @@ -53,7 +53,7 @@ import java.io.IOException; * invoking the {@link #close close} method. Closing the directory stream * releases any resources associated with the stream. Once a directory stream * is closed, all further method invocations on the iterator throw {@link - * java.util.concurrent.ConcurrentModificationException} with cause {@link + * java.util.ConcurrentModificationException} with cause {@link * ClosedDirectoryStreamException}. * *

A directory stream is not required to be asynchronously closeable. diff --git a/jdk/src/share/classes/java/nio/file/Path.java b/jdk/src/share/classes/java/nio/file/Path.java index 113a7c58067..d9ba6de7835 100644 --- a/jdk/src/share/classes/java/nio/file/Path.java +++ b/jdk/src/share/classes/java/nio/file/Path.java @@ -987,7 +987,7 @@ public abstract class Path * exception then it is propogated to the iterator's {@link Iterator#hasNext() * hasNext} or {@link Iterator#next() next} method. Where an {@code * IOException} is thrown, it is propogated as a {@link - * java.util.concurrent.ConcurrentModificationException} with the {@code + * java.util.ConcurrentModificationException} with the {@code * IOException} as the cause. * *

When an implementation supports operations on entries in the diff --git a/jdk/src/share/classes/java/nio/file/attribute/package-info.java b/jdk/src/share/classes/java/nio/file/attribute/package-info.java index c5301b1f840..b2192b89237 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/package-info.java +++ b/jdk/src/share/classes/java/nio/file/attribute/package-info.java @@ -102,9 +102,9 @@ *

  • The {@link java.nio.file.attribute.UserPrincipalLookupService} * interface defines methods to lookup user or group principals.
  • * - *

  • The {@link java.nio.file.attribute.Attribute} interface + *

  • The {@link java.nio.file.attribute.FileAttribute} interface * represents the value of an attribute for cases where the attribute value is - * require to be set atomically when creating an object in the file system.
  • + * required to be set atomically when creating an object in the file system. * * * diff --git a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java index fe2bb9d8bca..5e31adea247 100644 --- a/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java @@ -562,7 +562,8 @@ public class ConcurrentLinkedQueue extends AbstractQueue /** * Returns an iterator over the elements in this queue in proper sequence. * The returned iterator is a "weakly consistent" iterator that - * will never throw {@link ConcurrentModificationException}, + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 7db94a6efba..dd34d0dc6b7 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -988,7 +988,8 @@ public class LinkedBlockingDeque * Returns an iterator over the elements in this deque in proper sequence. * The elements will be returned in order from first (head) to last (tail). * The returned {@code Iterator} is a "weakly consistent" iterator that - * will never throw {@link ConcurrentModificationException}, + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. @@ -1004,7 +1005,8 @@ public class LinkedBlockingDeque * sequential order. The elements will be returned in order from * last (tail) to first (head). * The returned {@code Iterator} is a "weakly consistent" iterator that - * will never throw {@link ConcurrentModificationException}, + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. diff --git a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java index 9c1c6cc7b1f..10f2b6540cd 100644 --- a/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java +++ b/jdk/src/share/classes/java/util/concurrent/LinkedBlockingQueue.java @@ -728,7 +728,8 @@ public class LinkedBlockingQueue extends AbstractQueue /** * Returns an iterator over the elements in this queue in proper sequence. * The returned {@code Iterator} is a "weakly consistent" iterator that - * will never throw {@link ConcurrentModificationException}, + * will never throw {@link java.util.ConcurrentModificationException + * ConcurrentModificationException}, * and guarantees to traverse elements as they existed upon * construction of the iterator, and may (but is not guaranteed to) * reflect any modifications subsequent to construction. From 827200b265d5837bda0abb4c450e8267414588a8 Mon Sep 17 00:00:00 2001 From: Josh Bloch Date: Wed, 29 Jul 2009 14:24:19 -0700 Subject: [PATCH 28/70] 6804124: Replace "modified mergesort" in java.util.Arrays.sort with timsort Easy port of timsort from android Reviewed-by: martin --- jdk/make/java/java/FILES_java.gmk | 2 + jdk/src/share/classes/java/util/Arrays.java | 277 ++++-- .../share/classes/java/util/Collections.java | 97 +- .../classes/java/util/ComparableTimSort.java | 895 +++++++++++++++++ jdk/src/share/classes/java/util/TimSort.java | 928 ++++++++++++++++++ jdk/test/java/util/TimSort/ArrayBuilder.java | 142 +++ jdk/test/java/util/TimSort/README | 4 + jdk/test/java/util/TimSort/SortPerf.java | 66 ++ jdk/test/java/util/TimSort/Sorter.java | 55 ++ 9 files changed, 2381 insertions(+), 85 deletions(-) create mode 100644 jdk/src/share/classes/java/util/ComparableTimSort.java create mode 100644 jdk/src/share/classes/java/util/TimSort.java create mode 100644 jdk/test/java/util/TimSort/ArrayBuilder.java create mode 100644 jdk/test/java/util/TimSort/README create mode 100644 jdk/test/java/util/TimSort/SortPerf.java create mode 100644 jdk/test/java/util/TimSort/Sorter.java diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index 58c7b13608c..f9dd26383ce 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -250,6 +250,8 @@ JAVA_JAVA_java = \ java/util/IdentityHashMap.java \ java/util/EnumMap.java \ java/util/Arrays.java \ + java/util/TimSort.java \ + java/util/ComparableTimSort.java \ java/util/ConcurrentModificationException.java \ java/util/ServiceLoader.java \ java/util/ServiceConfigurationError.java \ diff --git a/jdk/src/share/classes/java/util/Arrays.java b/jdk/src/share/classes/java/util/Arrays.java index 313c686eb36..eac5521cd86 100644 --- a/jdk/src/share/classes/java/util/Arrays.java +++ b/jdk/src/share/classes/java/util/Arrays.java @@ -1065,29 +1065,103 @@ public class Arrays { (x[b] > x[c] ? b : x[a] > x[c] ? c : a)); } + /** + * Old merge sort implementation can be selected (for + * compatibility with broken comparators) using a system property. + * Cannot be a static boolean in the enclosing class due to + * circular dependencies. To be removed in a future release. + */ + static final class LegacyMergeSort { + private static final boolean userRequested = + java.security.AccessController.doPrivileged( + new sun.security.action.GetBooleanAction( + "java.util.Arrays.useLegacyMergeSort")).booleanValue(); + } + + /* + * If this platform has an optimizing VM, check whether ComparableTimSort + * offers any performance benefit over TimSort in conjunction with a + * comparator that returns: + * {@code ((Comparable)first).compareTo(Second)}. + * If not, you are better off deleting ComparableTimSort to + * eliminate the code duplication. In other words, the commented + * out code below is the preferable implementation for sorting + * arrays of Comparables if it offers sufficient performance. + */ + +// /** +// * A comparator that implements the natural ordering of a group of +// * mutually comparable elements. Using this comparator saves us +// * from duplicating most of the code in this file (one version for +// * Comparables, one for explicit Comparators). +// */ +// private static final Comparator NATURAL_ORDER = +// new Comparator() { +// @SuppressWarnings("unchecked") +// public int compare(Object first, Object second) { +// return ((Comparable)first).compareTo(second); +// } +// }; +// +// public static void sort(Object[] a) { +// sort(a, 0, a.length, NATURAL_ORDER); +// } +// +// public static void sort(Object[] a, int fromIndex, int toIndex) { +// sort(a, fromIndex, toIndex, NATURAL_ORDER); +// } /** - * Sorts the specified array of objects into ascending order, according to - * the {@linkplain Comparable natural ordering} - * of its elements. All elements in the array - * must implement the {@link Comparable} interface. Furthermore, all - * elements in the array must be mutually comparable (that is, - * e1.compareTo(e2) must not throw a ClassCastException - * for any elements e1 and e2 in the array).

    + * Sorts the specified array of objects into ascending order, according + * to the {@linkplain Comparable natural ordering} of its elements. + * All elements in the array must implement the {@link Comparable} + * interface. Furthermore, all elements in the array must be + * mutually comparable (that is, {@code e1.compareTo(e2)} must + * not throw a {@code ClassCastException} for any elements {@code e1} + * and {@code e2} in the array). * - * This sort is guaranteed to be stable: equal elements will - * not be reordered as a result of the sort.

    + *

    This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. * - * The sorting algorithm is a modified mergesort (in which the merge is - * omitted if the highest element in the low sublist is less than the - * lowest element in the high sublist). This algorithm offers guaranteed - * n*log(n) performance. + *

    Implementation note: This implementation is a stable, adaptive, + * iterative mergesort that requires far fewer than n lg(n) comparisons + * when the input array is partially sorted, while offering the + * performance of a traditional mergesort when the input array is + * randomly ordered. If the input array is nearly sorted, the + * implementation requires approximately n comparisons. Temporary + * storage requirements vary from a small constant for nearly sorted + * input arrays to n/2 object references for randomly ordered input + * arrays. + * + *

    The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

    The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. * * @param a the array to be sorted - * @throws ClassCastException if the array contains elements that are not - * mutually comparable (for example, strings and integers). + * @throws ClassCastException if the array contains elements that are not + * mutually comparable (for example, strings and integers) + * @throws IllegalArgumentException (optional) if the natural + * ordering of the array elements is found to violate the + * {@link Comparable} contract */ public static void sort(Object[] a) { + if (LegacyMergeSort.userRequested) + legacyMergeSort(a); + else + ComparableTimSort.sort(a); + } + + /** To be removed in a future release. */ + private static void legacyMergeSort(Object[] a) { Object[] aux = a.clone(); mergeSort(aux, a, 0, a.length, 0); } @@ -1097,34 +1171,63 @@ public class Arrays { * ascending order, according to the * {@linkplain Comparable natural ordering} of its * elements. The range to be sorted extends from index - * fromIndex, inclusive, to index toIndex, exclusive. - * (If fromIndex==toIndex, the range to be sorted is empty.) All + * {@code fromIndex}, inclusive, to index {@code toIndex}, exclusive. + * (If {@code fromIndex==toIndex}, the range to be sorted is empty.) All * elements in this range must implement the {@link Comparable} * interface. Furthermore, all elements in this range must be mutually - * comparable (that is, e1.compareTo(e2) must not throw a - * ClassCastException for any elements e1 and - * e2 in the array).

    + * comparable (that is, {@code e1.compareTo(e2)} must not throw a + * {@code ClassCastException} for any elements {@code e1} and + * {@code e2} in the array). * - * This sort is guaranteed to be stable: equal elements will - * not be reordered as a result of the sort.

    + *

    This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. * - * The sorting algorithm is a modified mergesort (in which the merge is - * omitted if the highest element in the low sublist is less than the - * lowest element in the high sublist). This algorithm offers guaranteed - * n*log(n) performance. + *

    Implementation note: This implementation is a stable, adaptive, + * iterative mergesort that requires far fewer than n lg(n) comparisons + * when the input array is partially sorted, while offering the + * performance of a traditional mergesort when the input array is + * randomly ordered. If the input array is nearly sorted, the + * implementation requires approximately n comparisons. Temporary + * storage requirements vary from a small constant for nearly sorted + * input arrays to n/2 object references for randomly ordered input + * arrays. + * + *

    The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

    The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. * * @param a the array to be sorted * @param fromIndex the index of the first element (inclusive) to be * sorted * @param toIndex the index of the last element (exclusive) to be sorted - * @throws IllegalArgumentException if fromIndex > toIndex - * @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or - * toIndex > a.length - * @throws ClassCastException if the array contains elements that are - * not mutually comparable (for example, strings and - * integers). + * @throws IllegalArgumentException if {@code fromIndex > toIndex} or + * (optional) if the natural ordering of the array elements is + * found to violate the {@link Comparable} contract + * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or + * {@code toIndex > a.length} + * @throws ClassCastException if the array contains elements that are + * not mutually comparable (for example, strings and + * integers). */ public static void sort(Object[] a, int fromIndex, int toIndex) { + if (LegacyMergeSort.userRequested) + legacyMergeSort(a, fromIndex, toIndex); + else + ComparableTimSort.sort(a, fromIndex, toIndex); + } + + /** To be removed in a future release. */ + private static void legacyMergeSort(Object[] a, + int fromIndex, int toIndex) { rangeCheck(a.length, fromIndex, toIndex); Object[] aux = copyOfRange(a, fromIndex, toIndex); mergeSort(aux, a, fromIndex, toIndex, -fromIndex); @@ -1133,6 +1236,7 @@ public class Arrays { /** * Tuning parameter: list size at or below which insertion sort will be * used in preference to mergesort or quicksort. + * To be removed in a future release. */ private static final int INSERTIONSORT_THRESHOLD = 7; @@ -1142,6 +1246,7 @@ public class Arrays { * low is the index in dest to start sorting * high is the end index in dest to end sorting * off is the offset to generate corresponding low, high in src + * To be removed in a future release. */ private static void mergeSort(Object[] src, Object[] dest, @@ -1197,25 +1302,53 @@ public class Arrays { * Sorts the specified array of objects according to the order induced by * the specified comparator. All elements in the array must be * mutually comparable by the specified comparator (that is, - * c.compare(e1, e2) must not throw a ClassCastException - * for any elements e1 and e2 in the array).

    + * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException} + * for any elements {@code e1} and {@code e2} in the array). * - * This sort is guaranteed to be stable: equal elements will - * not be reordered as a result of the sort.

    + *

    This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. * - * The sorting algorithm is a modified mergesort (in which the merge is - * omitted if the highest element in the low sublist is less than the - * lowest element in the high sublist). This algorithm offers guaranteed - * n*log(n) performance. + *

    Implementation note: This implementation is a stable, adaptive, + * iterative mergesort that requires far fewer than n lg(n) comparisons + * when the input array is partially sorted, while offering the + * performance of a traditional mergesort when the input array is + * randomly ordered. If the input array is nearly sorted, the + * implementation requires approximately n comparisons. Temporary + * storage requirements vary from a small constant for nearly sorted + * input arrays to n/2 object references for randomly ordered input + * arrays. + * + *

    The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

    The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. * * @param a the array to be sorted * @param c the comparator to determine the order of the array. A - * null value indicates that the elements' + * {@code null} value indicates that the elements' * {@linkplain Comparable natural ordering} should be used. - * @throws ClassCastException if the array contains elements that are - * not mutually comparable using the specified comparator. + * @throws ClassCastException if the array contains elements that are + * not mutually comparable using the specified comparator + * @throws IllegalArgumentException (optional) if the comparator is + * found to violate the {@link Comparator} contract */ public static void sort(T[] a, Comparator c) { + if (LegacyMergeSort.userRequested) + legacyMergeSort(a, c); + else + TimSort.sort(a, c); + } + + /** To be removed in a future release. */ + private static void legacyMergeSort(T[] a, Comparator c) { T[] aux = a.clone(); if (c==null) mergeSort(aux, a, 0, a.length, 0); @@ -1226,36 +1359,65 @@ public class Arrays { /** * Sorts the specified range of the specified array of objects according * to the order induced by the specified comparator. The range to be - * sorted extends from index fromIndex, inclusive, to index - * toIndex, exclusive. (If fromIndex==toIndex, the + * sorted extends from index {@code fromIndex}, inclusive, to index + * {@code toIndex}, exclusive. (If {@code fromIndex==toIndex}, the * range to be sorted is empty.) All elements in the range must be * mutually comparable by the specified comparator (that is, - * c.compare(e1, e2) must not throw a ClassCastException - * for any elements e1 and e2 in the range).

    + * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException} + * for any elements {@code e1} and {@code e2} in the range). * - * This sort is guaranteed to be stable: equal elements will - * not be reordered as a result of the sort.

    + *

    This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. * - * The sorting algorithm is a modified mergesort (in which the merge is - * omitted if the highest element in the low sublist is less than the - * lowest element in the high sublist). This algorithm offers guaranteed - * n*log(n) performance. + *

    Implementation note: This implementation is a stable, adaptive, + * iterative mergesort that requires far fewer than n lg(n) comparisons + * when the input array is partially sorted, while offering the + * performance of a traditional mergesort when the input array is + * randomly ordered. If the input array is nearly sorted, the + * implementation requires approximately n comparisons. Temporary + * storage requirements vary from a small constant for nearly sorted + * input arrays to n/2 object references for randomly ordered input + * arrays. + * + *

    The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

    The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. * * @param a the array to be sorted * @param fromIndex the index of the first element (inclusive) to be * sorted * @param toIndex the index of the last element (exclusive) to be sorted * @param c the comparator to determine the order of the array. A - * null value indicates that the elements' + * {@code null} value indicates that the elements' * {@linkplain Comparable natural ordering} should be used. * @throws ClassCastException if the array contains elements that are not * mutually comparable using the specified comparator. - * @throws IllegalArgumentException if fromIndex > toIndex - * @throws ArrayIndexOutOfBoundsException if fromIndex < 0 or - * toIndex > a.length + * @throws IllegalArgumentException if {@code fromIndex > toIndex} or + * (optional) if the comparator is found to violate the + * {@link Comparator} contract + * @throws ArrayIndexOutOfBoundsException if {@code fromIndex < 0} or + * {@code toIndex > a.length} */ public static void sort(T[] a, int fromIndex, int toIndex, Comparator c) { + if (LegacyMergeSort.userRequested) + legacyMergeSort(a, fromIndex, toIndex, c); + else + TimSort.sort(a, fromIndex, toIndex, c); + } + + /** To be removed in a future release. */ + private static void legacyMergeSort(T[] a, int fromIndex, int toIndex, + Comparator c) { rangeCheck(a.length, fromIndex, toIndex); T[] aux = copyOfRange(a, fromIndex, toIndex); if (c==null) @@ -1270,6 +1432,7 @@ public class Arrays { * low is the index in dest to start sorting * high is the end index in dest to end sorting * off is the offset into src corresponding to low in dest + * To be removed in a future release. */ private static void mergeSort(Object[] src, Object[] dest, diff --git a/jdk/src/share/classes/java/util/Collections.java b/jdk/src/share/classes/java/util/Collections.java index caec3ffd11c..8597888dfa5 100644 --- a/jdk/src/share/classes/java/util/Collections.java +++ b/jdk/src/share/classes/java/util/Collections.java @@ -100,23 +100,42 @@ public class Collections { /** * Sorts the specified list into ascending order, according to the - * natural ordering of its elements. All elements in the list must - * implement the Comparable interface. Furthermore, all elements - * in the list must be mutually comparable (that is, - * e1.compareTo(e2) must not throw a ClassCastException - * for any elements e1 and e2 in the list).

    + * {@linkplain Comparable natural ordering} of its elements. + * All elements in the list must implement the {@link Comparable} + * interface. Furthermore, all elements in the list must be + * mutually comparable (that is, {@code e1.compareTo(e2)} + * must not throw a {@code ClassCastException} for any elements + * {@code e1} and {@code e2} in the list). * - * This sort is guaranteed to be stable: equal elements will - * not be reordered as a result of the sort.

    + *

    This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. * - * The specified list must be modifiable, but need not be resizable.

    + *

    The specified list must be modifiable, but need not be resizable. * - * The sorting algorithm is a modified mergesort (in which the merge is - * omitted if the highest element in the low sublist is less than the - * lowest element in the high sublist). This algorithm offers guaranteed - * n log(n) performance. + *

    Implementation note: This implementation is a stable, adaptive, + * iterative mergesort that requires far fewer than n lg(n) comparisons + * when the input array is partially sorted, while offering the + * performance of a traditional mergesort when the input array is + * randomly ordered. If the input array is nearly sorted, the + * implementation requires approximately n comparisons. Temporary + * storage requirements vary from a small constant for nearly sorted + * input arrays to n/2 object references for randomly ordered input + * arrays. * - * This implementation dumps the specified list into an array, sorts + *

    The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

    The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. + * + *

    This implementation dumps the specified list into an array, sorts * the array, and iterates over the list resetting each element * from the corresponding position in the array. This avoids the * n2 log(n) performance that would result from attempting @@ -126,8 +145,10 @@ public class Collections { * @throws ClassCastException if the list contains elements that are not * mutually comparable (for example, strings and integers). * @throws UnsupportedOperationException if the specified list's - * list-iterator does not support the set operation. - * @see Comparable + * list-iterator does not support the {@code set} operation. + * @throws IllegalArgumentException (optional) if the implementation + * detects that the natural ordering of the list elements is + * found to violate the {@link Comparable} contract */ public static > void sort(List list) { Object[] a = list.toArray(); @@ -143,19 +164,38 @@ public class Collections { * Sorts the specified list according to the order induced by the * specified comparator. All elements in the list must be mutually * comparable using the specified comparator (that is, - * c.compare(e1, e2) must not throw a ClassCastException - * for any elements e1 and e2 in the list).

    + * {@code c.compare(e1, e2)} must not throw a {@code ClassCastException} + * for any elements {@code e1} and {@code e2} in the list). * - * This sort is guaranteed to be stable: equal elements will - * not be reordered as a result of the sort.

    + *

    This sort is guaranteed to be stable: equal elements will + * not be reordered as a result of the sort. * - * The sorting algorithm is a modified mergesort (in which the merge is - * omitted if the highest element in the low sublist is less than the - * lowest element in the high sublist). This algorithm offers guaranteed - * n log(n) performance. + *

    The specified list must be modifiable, but need not be resizable. * - * The specified list must be modifiable, but need not be resizable. - * This implementation dumps the specified list into an array, sorts + *

    Implementation note: This implementation is a stable, adaptive, + * iterative mergesort that requires far fewer than n lg(n) comparisons + * when the input array is partially sorted, while offering the + * performance of a traditional mergesort when the input array is + * randomly ordered. If the input array is nearly sorted, the + * implementation requires approximately n comparisons. Temporary + * storage requirements vary from a small constant for nearly sorted + * input arrays to n/2 object references for randomly ordered input + * arrays. + * + *

    The implementation takes equal advantage of ascending and + * descending order in its input array, and can take advantage of + * ascending and descending order in different parts of the the same + * input array. It is well-suited to merging two or more sorted arrays: + * simply concatenate the arrays and sort the resulting array. + * + *

    The implementation was adapted from Tim Peters's list sort for Python + * ( + * TimSort). It uses techiques from Peter McIlroy's "Optimistic + * Sorting and Information Theoretic Complexity", in Proceedings of the + * Fourth Annual ACM-SIAM Symposium on Discrete Algorithms, pp 467-474, + * January 1993. + * + *

    This implementation dumps the specified list into an array, sorts * the array, and iterates over the list resetting each element * from the corresponding position in the array. This avoids the * n2 log(n) performance that would result from attempting @@ -163,13 +203,14 @@ public class Collections { * * @param list the list to be sorted. * @param c the comparator to determine the order of the list. A - * null value indicates that the elements' natural + * {@code null} value indicates that the elements' natural * ordering should be used. * @throws ClassCastException if the list contains elements that are not * mutually comparable using the specified comparator. * @throws UnsupportedOperationException if the specified list's - * list-iterator does not support the set operation. - * @see Comparator + * list-iterator does not support the {@code set} operation. + * @throws IllegalArgumentException (optional) if the comparator is + * found to violate the {@link Comparator} contract */ public static void sort(List list, Comparator c) { Object[] a = list.toArray(); diff --git a/jdk/src/share/classes/java/util/ComparableTimSort.java b/jdk/src/share/classes/java/util/ComparableTimSort.java new file mode 100644 index 00000000000..750a89bebaa --- /dev/null +++ b/jdk/src/share/classes/java/util/ComparableTimSort.java @@ -0,0 +1,895 @@ +/* + * Copyright 2009 Google Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.util; + +/** + * This is a near duplicate of {@link TimSort}, modified for use with + * arrays of objects that implement {@link Comparable}, instead of using + * explicit comparators. + * + *

    If you are using an optimizing VM, you may find that ComparableTimSort + * offers no performance benefit over TimSort in conjunction with a + * comparator that simply returns {@code ((Comparable)first).compareTo(Second)}. + * If this is the case, you are better off deleting ComparableTimSort to + * eliminate the code duplication. (See Arrays.java for details.) + * + * @author Josh Bloch + */ +class ComparableTimSort { + /** + * This is the minimum sized sequence that will be merged. Shorter + * sequences will be lengthened by calling binarySort. If the entire + * array is less than this length, no merges will be performed. + * + * This constant should be a power of two. It was 64 in Tim Peter's C + * implementation, but 32 was empirically determined to work better in + * this implementation. In the unlikely event that you set this constant + * to be a number that's not a power of two, you'll need to change the + * {@link #minRunLength} computation. + * + * If you decrease this constant, you must change the stackLen + * computation in the TimSort constructor, or you risk an + * ArrayOutOfBounds exception. See listsort.txt for a discussion + * of the minimum stack length required as a function of the length + * of the array being sorted and the minimum merge sequence length. + */ + private static final int MIN_MERGE = 32; + + /** + * The array being sorted. + */ + private final Object[] a; + + /** + * When we get into galloping mode, we stay there until both runs win less + * often than MIN_GALLOP consecutive times. + */ + private static final int MIN_GALLOP = 7; + + /** + * This controls when we get *into* galloping mode. It is initialized + * to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for + * random data, and lower for highly structured data. + */ + private int minGallop = MIN_GALLOP; + + /** + * Maximum initial size of tmp array, which is used for merging. The array + * can grow to accommodate demand. + * + * Unlike Tim's original C version, we do not allocate this much storage + * when sorting smaller arrays. This change was required for performance. + */ + private static final int INITIAL_TMP_STORAGE_LENGTH = 256; + + /** + * Temp storage for merges. + */ + private Object[] tmp; + + /** + * A stack of pending runs yet to be merged. Run i starts at + * address base[i] and extends for len[i] elements. It's always + * true (so long as the indices are in bounds) that: + * + * runBase[i] + runLen[i] == runBase[i + 1] + * + * so we could cut the storage for this, but it's a minor amount, + * and keeping all the info explicit simplifies the code. + */ + private int stackSize = 0; // Number of pending runs on stack + private final int[] runBase; + private final int[] runLen; + + /** + * Creates a TimSort instance to maintain the state of an ongoing sort. + * + * @param a the array to be sorted + */ + private ComparableTimSort(Object[] a) { + this.a = a; + + // Allocate temp storage (which may be increased later if necessary) + int len = a.length; + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + Object[] newArray = new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ? + len >>> 1 : INITIAL_TMP_STORAGE_LENGTH]; + tmp = newArray; + + /* + * Allocate runs-to-be-merged stack (which cannot be expanded). The + * stack length requirements are described in listsort.txt. The C + * version always uses the same stack length (85), but this was + * measured to be too expensive when sorting "mid-sized" arrays (e.g., + * 100 elements) in Java. Therefore, we use smaller (but sufficiently + * large) stack lengths for smaller arrays. The "magic numbers" in the + * computation below must be changed if MIN_MERGE is decreased. See + * the MIN_MERGE declaration above for more information. + */ + int stackLen = (len < 120 ? 5 : + len < 1542 ? 10 : + len < 119151 ? 19 : 40); + runBase = new int[stackLen]; + runLen = new int[stackLen]; + } + + /* + * The next two methods (which are package private and static) constitute + * the entire API of this class. Each of these methods obeys the contract + * of the public method with the same signature in java.util.Arrays. + */ + + static void sort(Object[] a) { + sort(a, 0, a.length); + } + + static void sort(Object[] a, int lo, int hi) { + rangeCheck(a.length, lo, hi); + int nRemaining = hi - lo; + if (nRemaining < 2) + return; // Arrays of size 0 and 1 are always sorted + + // If array is small, do a "mini-TimSort" with no merges + if (nRemaining < MIN_MERGE) { + int initRunLen = countRunAndMakeAscending(a, lo, hi); + binarySort(a, lo, hi, lo + initRunLen); + return; + } + + /** + * March over the array once, left to right, finding natural runs, + * extending short natural runs to minRun elements, and merging runs + * to maintain stack invariant. + */ + ComparableTimSort ts = new ComparableTimSort(a); + int minRun = minRunLength(nRemaining); + do { + // Identify next run + int runLen = countRunAndMakeAscending(a, lo, hi); + + // If run is short, extend to min(minRun, nRemaining) + if (runLen < minRun) { + int force = nRemaining <= minRun ? nRemaining : minRun; + binarySort(a, lo, lo + force, lo + runLen); + runLen = force; + } + + // Push run onto pending-run stack, and maybe merge + ts.pushRun(lo, runLen); + ts.mergeCollapse(); + + // Advance to find next run + lo += runLen; + nRemaining -= runLen; + } while (nRemaining != 0); + + // Merge all remaining runs to complete sort + assert lo == hi; + ts.mergeForceCollapse(); + assert ts.stackSize == 1; + } + + /** + * Sorts the specified portion of the specified array using a binary + * insertion sort. This is the best method for sorting small numbers + * of elements. It requires O(n log n) compares, but O(n^2) data + * movement (worst case). + * + * If the initial part of the specified range is already sorted, + * this method can take advantage of it: the method assumes that the + * elements from index {@code lo}, inclusive, to {@code start}, + * exclusive are already sorted. + * + * @param a the array in which a range is to be sorted + * @param lo the index of the first element in the range to be sorted + * @param hi the index after the last element in the range to be sorted + * @param start the index of the first element in the range that is + * not already known to be sorted (@code lo <= start <= hi} + */ + @SuppressWarnings("fallthrough") + private static void binarySort(Object[] a, int lo, int hi, int start) { + assert lo <= start && start <= hi; + if (start == lo) + start++; + for ( ; start < hi; start++) { + @SuppressWarnings("unchecked") + Comparable pivot = (Comparable) a[start]; + + // Set left (and right) to the index where a[start] (pivot) belongs + int left = lo; + int right = start; + assert left <= right; + /* + * Invariants: + * pivot >= all in [lo, left). + * pivot < all in [right, start). + */ + while (left < right) { + int mid = (left + right) >>> 1; + if (pivot.compareTo(a[mid]) < 0) + right = mid; + else + left = mid + 1; + } + assert left == right; + + /* + * The invariants still hold: pivot >= all in [lo, left) and + * pivot < all in [left, start), so pivot belongs at left. Note + * that if there are elements equal to pivot, left points to the + * first slot after them -- that's why this sort is stable. + * Slide elements over to make room to make room for pivot. + */ + int n = start - left; // The number of elements to move + // Switch is just an optimization for arraycopy in default case + switch(n) { + case 2: a[left + 2] = a[left + 1]; + case 1: a[left + 1] = a[left]; + break; + default: System.arraycopy(a, left, a, left + 1, n); + } + a[left] = pivot; + } + } + + /** + * Returns the length of the run beginning at the specified position in + * the specified array and reverses the run if it is descending (ensuring + * that the run will always be ascending when the method returns). + * + * A run is the longest ascending sequence with: + * + * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... + * + * or the longest descending sequence with: + * + * a[lo] > a[lo + 1] > a[lo + 2] > ... + * + * For its intended use in a stable mergesort, the strictness of the + * definition of "descending" is needed so that the call can safely + * reverse a descending sequence without violating stability. + * + * @param a the array in which a run is to be counted and possibly reversed + * @param lo index of the first element in the run + * @param hi index after the last element that may be contained in the run. + It is required that @code{lo < hi}. + * @return the length of the run beginning at the specified position in + * the specified array + */ + @SuppressWarnings("unchecked") + private static int countRunAndMakeAscending(Object[] a, int lo, int hi) { + assert lo < hi; + int runHi = lo + 1; + if (runHi == hi) + return 1; + + // Find end of run, and reverse range if descending + if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending + while(runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0) + runHi++; + reverseRange(a, lo, runHi); + } else { // Ascending + while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0) + runHi++; + } + + return runHi - lo; + } + + /** + * Reverse the specified range of the specified array. + * + * @param a the array in which a range is to be reversed + * @param lo the index of the first element in the range to be reversed + * @param hi the index after the last element in the range to be reversed + */ + private static void reverseRange(Object[] a, int lo, int hi) { + hi--; + while (lo < hi) { + Object t = a[lo]; + a[lo++] = a[hi]; + a[hi--] = t; + } + } + + /** + * Returns the minimum acceptable run length for an array of the specified + * length. Natural runs shorter than this will be extended with + * {@link #binarySort}. + * + * Roughly speaking, the computation is: + * + * If n < MIN_MERGE, return n (it's too small to bother with fancy stuff). + * Else if n is an exact power of 2, return MIN_MERGE/2. + * Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k + * is close to, but strictly less than, an exact power of 2. + * + * For the rationale, see listsort.txt. + * + * @param n the length of the array to be sorted + * @return the length of the minimum run to be merged + */ + private static int minRunLength(int n) { + assert n >= 0; + int r = 0; // Becomes 1 if any 1 bits are shifted off + while (n >= MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + return n + r; + } + + /** + * Pushes the specified run onto the pending-run stack. + * + * @param runBase index of the first element in the run + * @param runLen the number of elements in the run + */ + private void pushRun(int runBase, int runLen) { + this.runBase[stackSize] = runBase; + this.runLen[stackSize] = runLen; + stackSize++; + } + + /** + * Examines the stack of runs waiting to be merged and merges adjacent runs + * until the stack invariants are reestablished: + * + * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] + * 2. runLen[i - 2] > runLen[i - 1] + * + * This method is called each time a new run is pushed onto the stack, + * so the invariants are guaranteed to hold for i < stackSize upon + * entry to the method. + */ + private void mergeCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) { + if (runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } else if (runLen[n] <= runLen[n + 1]) { + mergeAt(n); + } else { + break; // Invariant is established + } + } + } + + /** + * Merges all runs on the stack until only one remains. This method is + * called once, to complete the sort. + */ + private void mergeForceCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } + } + + /** + * Merges the two runs at stack indices i and i+1. Run i must be + * the penultimate or antepenultimate run on the stack. In other words, + * i must be equal to stackSize-2 or stackSize-3. + * + * @param i stack index of the first of the two runs to merge + */ + @SuppressWarnings("unchecked") + private void mergeAt(int i) { + assert stackSize >= 2; + assert i >= 0; + assert i == stackSize - 2 || i == stackSize - 3; + + int base1 = runBase[i]; + int len1 = runLen[i]; + int base2 = runBase[i + 1]; + int len2 = runLen[i + 1]; + assert len1 > 0 && len2 > 0; + assert base1 + len1 == base2; + + /* + * Record the length of the combined runs; if i is the 3rd-last + * run now, also slide over the last run (which isn't involved + * in this merge). The current run (i+1) goes away in any case. + */ + runLen[i] = len1 + len2; + if (i == stackSize - 3) { + runBase[i + 1] = runBase[i + 2]; + runLen[i + 1] = runLen[i + 2]; + } + stackSize--; + + /* + * Find where the first element of run2 goes in run1. Prior elements + * in run1 can be ignored (because they're already in place). + */ + int k = gallopRight((Comparable) a[base2], a, base1, len1, 0); + assert k >= 0; + base1 += k; + len1 -= k; + if (len1 == 0) + return; + + /* + * Find where the last element of run1 goes in run2. Subsequent elements + * in run2 can be ignored (because they're already in place). + */ + len2 = gallopLeft((Comparable) a[base1 + len1 - 1], a, + base2, len2, len2 - 1); + assert len2 >= 0; + if (len2 == 0) + return; + + // Merge remaining runs, using tmp array with min(len1, len2) elements + if (len1 <= len2) + mergeLo(base1, len1, base2, len2); + else + mergeHi(base1, len1, base2, len2); + } + + /** + * Locates the position at which to insert the specified key into the + * specified sorted range; if the range contains an element equal to key, + * returns the index of the leftmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], + * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. + * In other words, key belongs at index b + k; or in other words, + * the first k elements of a should precede key, and the last n - k + * should follow it. + */ + private static int gallopLeft(Comparable key, Object[] a, + int base, int len, int hint) { + assert len > 0 && hint >= 0 && hint < len; + + int lastOfs = 0; + int ofs = 1; + if (key.compareTo(a[base + hint]) > 0) { + // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) > 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + lastOfs += hint; + ofs += hint; + } else { // key <= a[base + hint] + // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] + final int maxOfs = hint + 1; + while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) <= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere + * to the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (key.compareTo(a[base + m]) > 0) + lastOfs = m + 1; // a[base + m] < key + else + ofs = m; // key <= a[base + m] + } + assert lastOfs == ofs; // so a[base + ofs - 1] < key <= a[base + ofs] + return ofs; + } + + /** + * Like gallopLeft, except that if the range contains an element equal to + * key, gallopRight returns the index after the rightmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] + */ + private static int gallopRight(Comparable key, Object[] a, + int base, int len, int hint) { + assert len > 0 && hint >= 0 && hint < len; + + int ofs = 1; + int lastOfs = 0; + if (key.compareTo(a[base + hint]) < 0) { + // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] + int maxOfs = hint + 1; + while (ofs < maxOfs && key.compareTo(a[base + hint - ofs]) < 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } else { // a[b + hint] <= key + // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && key.compareTo(a[base + hint + ofs]) >= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + lastOfs += hint; + ofs += hint; + } + assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to + * the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (key.compareTo(a[base + m]) < 0) + ofs = m; // key < a[b + m] + else + lastOfs = m + 1; // a[b + m] <= key + } + assert lastOfs == ofs; // so a[b + ofs - 1] <= key < a[b + ofs] + return ofs; + } + + /** + * Merges two adjacent runs in place, in a stable fashion. The first + * element of the first run must be greater than the first element of the + * second run (a[base1] > a[base2]), and the last element of the first run + * (a[base1 + len1-1]) must be greater than all elements of the second run. + * + * For performance, this method should be called only when len1 <= len2; + * its twin, mergeHi should be called if len1 >= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + @SuppressWarnings("unchecked") + private void mergeLo(int base1, int len1, int base2, int len2) { + assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy first run into temp array + Object[] a = this.a; // For performance + Object[] tmp = ensureCapacity(len1); + System.arraycopy(a, base1, tmp, 0, len1); + + int cursor1 = 0; // Indexes into tmp array + int cursor2 = base2; // Indexes int a + int dest = base1; // Indexes int a + + // Move first element of second run and deal with degenerate cases + a[dest++] = a[cursor2++]; + if (--len2 == 0) { + System.arraycopy(tmp, cursor1, a, dest, len1); + return; + } + if (len1 == 1) { + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + return; + } + + int minGallop = this.minGallop; // Use local variable for performance + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run starts + * winning consistently. + */ + do { + assert len1 > 1 && len2 > 0; + if (((Comparable) a[cursor2]).compareTo(tmp[cursor1]) < 0) { + a[dest++] = a[cursor2++]; + count2++; + count1 = 0; + if (--len2 == 0) + break outer; + } else { + a[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--len1 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + assert len1 > 1 && len2 > 0; + count1 = gallopRight((Comparable) a[cursor2], tmp, cursor1, len1, 0); + if (count1 != 0) { + System.arraycopy(tmp, cursor1, a, dest, count1); + dest += count1; + cursor1 += count1; + len1 -= count1; + if (len1 <= 1) // len1 == 1 || len1 == 0 + break outer; + } + a[dest++] = a[cursor2++]; + if (--len2 == 0) + break outer; + + count2 = gallopLeft((Comparable) tmp[cursor1], a, cursor2, len2, 0); + if (count2 != 0) { + System.arraycopy(a, cursor2, a, dest, count2); + dest += count2; + cursor2 += count2; + len2 -= count2; + if (len2 == 0) + break outer; + } + a[dest++] = tmp[cursor1++]; + if (--len1 == 1) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len1 == 1) { + assert len2 > 0; + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + } else if (len1 == 0) { + throw new IllegalArgumentException( + "Comparison method violates its general contract!"); + } else { + assert len2 == 0; + assert len1 > 1; + System.arraycopy(tmp, cursor1, a, dest, len1); + } + } + + /** + * Like mergeLo, except that this method should be called only if + * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + @SuppressWarnings("unchecked") + private void mergeHi(int base1, int len1, int base2, int len2) { + assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy second run into temp array + Object[] a = this.a; // For performance + Object[] tmp = ensureCapacity(len2); + System.arraycopy(a, base2, tmp, 0, len2); + + int cursor1 = base1 + len1 - 1; // Indexes into a + int cursor2 = len2 - 1; // Indexes into tmp array + int dest = base2 + len2 - 1; // Indexes into a + + // Move last element of first run and deal with degenerate cases + a[dest--] = a[cursor1--]; + if (--len1 == 0) { + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + return; + } + if (len2 == 1) { + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; + return; + } + + int minGallop = this.minGallop; // Use local variable for performance + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run + * appears to win consistently. + */ + do { + assert len1 > 0 && len2 > 1; + if (((Comparable) tmp[cursor2]).compareTo(a[cursor1]) < 0) { + a[dest--] = a[cursor1--]; + count1++; + count2 = 0; + if (--len1 == 0) + break outer; + } else { + a[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--len2 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + assert len1 > 0 && len2 > 1; + count1 = len1 - gallopRight((Comparable) tmp[cursor2], a, base1, len1, len1 - 1); + if (count1 != 0) { + dest -= count1; + cursor1 -= count1; + len1 -= count1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, count1); + if (len1 == 0) + break outer; + } + a[dest--] = tmp[cursor2--]; + if (--len2 == 1) + break outer; + + count2 = len2 - gallopLeft((Comparable) a[cursor1], tmp, 0, len2, len2 - 1); + if (count2 != 0) { + dest -= count2; + cursor2 -= count2; + len2 -= count2; + System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2); + if (len2 <= 1) + break outer; // len2 == 1 || len2 == 0 + } + a[dest--] = a[cursor1--]; + if (--len1 == 0) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len2 == 1) { + assert len1 > 0; + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; // Move first elt of run2 to front of merge + } else if (len2 == 0) { + throw new IllegalArgumentException( + "Comparison method violates its general contract!"); + } else { + assert len1 == 0; + assert len2 > 0; + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + } + } + + /** + * Ensures that the external array tmp has at least the specified + * number of elements, increasing its size if necessary. The size + * increases exponentially to ensure amortized linear time complexity. + * + * @param minCapacity the minimum required capacity of the tmp array + * @return tmp, whether or not it grew + */ + private Object[] ensureCapacity(int minCapacity) { + if (tmp.length < minCapacity) { + // Compute smallest power of 2 > minCapacity + int newSize = minCapacity; + newSize |= newSize >> 1; + newSize |= newSize >> 2; + newSize |= newSize >> 4; + newSize |= newSize >> 8; + newSize |= newSize >> 16; + newSize++; + + if (newSize < 0) // Not bloody likely! + newSize = minCapacity; + else + newSize = Math.min(newSize, a.length >>> 1); + + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + Object[] newArray = new Object[newSize]; + tmp = newArray; + } + return tmp; + } + + /** + * Checks that fromIndex and toIndex are in range, and throws an + * appropriate exception if they aren't. + * + * @param arrayLen the length of the array + * @param fromIndex the index of the first element of the range + * @param toIndex the index after the last element of the range + * @throws IllegalArgumentException if fromIndex > toIndex + * @throws ArrayIndexOutOfBoundsException if fromIndex < 0 + * or toIndex > arrayLen + */ + private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) { + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex+")"); + if (fromIndex < 0) + throw new ArrayIndexOutOfBoundsException(fromIndex); + if (toIndex > arrayLen) + throw new ArrayIndexOutOfBoundsException(toIndex); + } +} diff --git a/jdk/src/share/classes/java/util/TimSort.java b/jdk/src/share/classes/java/util/TimSort.java new file mode 100644 index 00000000000..1d4e710a499 --- /dev/null +++ b/jdk/src/share/classes/java/util/TimSort.java @@ -0,0 +1,928 @@ +/* + * Copyright 2009 Google Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.util; + +/** + * A stable, adaptive, iterative mergesort that requires far fewer than + * n lg(n) comparisons when running on partially sorted arrays, while + * offering performance comparable to a traditional mergesort when run + * on random arrays. Like all proper mergesorts, this sort is stable and + * runs O(n log n) time (worst case). In the worst case, this sort requires + * temporary storage space for n/2 object references; in the best case, + * it requires only a small constant amount of space. + * + * This implementation was adapted from Tim Peters's list sort for + * Python, which is described in detail here: + * + * http://svn.python.org/projects/python/trunk/Objects/listsort.txt + * + * Tim's C code may be found here: + * + * http://svn.python.org/projects/python/trunk/Objects/listobject.c + * + * The underlying techniques are described in this paper (and may have + * even earlier origins): + * + * "Optimistic Sorting and Information Theoretic Complexity" + * Peter McIlroy + * SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), + * pp 467-474, Austin, Texas, 25-27 January 1993. + * + * While the API to this class consists solely of static methods, it is + * (privately) instantiable; a TimSort instance holds the state of an ongoing + * sort, assuming the input array is large enough to warrant the full-blown + * TimSort. Small arrays are sorted in place, using a binary insertion sort. + * + * @author Josh Bloch + */ +class TimSort { + /** + * This is the minimum sized sequence that will be merged. Shorter + * sequences will be lengthened by calling binarySort. If the entire + * array is less than this length, no merges will be performed. + * + * This constant should be a power of two. It was 64 in Tim Peter's C + * implementation, but 32 was empirically determined to work better in + * this implementation. In the unlikely event that you set this constant + * to be a number that's not a power of two, you'll need to change the + * {@link #minRunLength} computation. + * + * If you decrease this constant, you must change the stackLen + * computation in the TimSort constructor, or you risk an + * ArrayOutOfBounds exception. See listsort.txt for a discussion + * of the minimum stack length required as a function of the length + * of the array being sorted and the minimum merge sequence length. + */ + private static final int MIN_MERGE = 32; + + /** + * The array being sorted. + */ + private final T[] a; + + /** + * The comparator for this sort. + */ + private final Comparator c; + + /** + * When we get into galloping mode, we stay there until both runs win less + * often than MIN_GALLOP consecutive times. + */ + private static final int MIN_GALLOP = 7; + + /** + * This controls when we get *into* galloping mode. It is initialized + * to MIN_GALLOP. The mergeLo and mergeHi methods nudge it higher for + * random data, and lower for highly structured data. + */ + private int minGallop = MIN_GALLOP; + + /** + * Maximum initial size of tmp array, which is used for merging. The array + * can grow to accommodate demand. + * + * Unlike Tim's original C version, we do not allocate this much storage + * when sorting smaller arrays. This change was required for performance. + */ + private static final int INITIAL_TMP_STORAGE_LENGTH = 256; + + /** + * Temp storage for merges. + */ + private T[] tmp; // Actual runtime type will be Object[], regardless of T + + /** + * A stack of pending runs yet to be merged. Run i starts at + * address base[i] and extends for len[i] elements. It's always + * true (so long as the indices are in bounds) that: + * + * runBase[i] + runLen[i] == runBase[i + 1] + * + * so we could cut the storage for this, but it's a minor amount, + * and keeping all the info explicit simplifies the code. + */ + private int stackSize = 0; // Number of pending runs on stack + private final int[] runBase; + private final int[] runLen; + + /** + * Creates a TimSort instance to maintain the state of an ongoing sort. + * + * @param a the array to be sorted + * @param c the comparator to determine the order of the sort + */ + private TimSort(T[] a, Comparator c) { + this.a = a; + this.c = c; + + // Allocate temp storage (which may be increased later if necessary) + int len = a.length; + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + T[] newArray = (T[]) new Object[len < 2 * INITIAL_TMP_STORAGE_LENGTH ? + len >>> 1 : INITIAL_TMP_STORAGE_LENGTH]; + tmp = newArray; + + /* + * Allocate runs-to-be-merged stack (which cannot be expanded). The + * stack length requirements are described in listsort.txt. The C + * version always uses the same stack length (85), but this was + * measured to be too expensive when sorting "mid-sized" arrays (e.g., + * 100 elements) in Java. Therefore, we use smaller (but sufficiently + * large) stack lengths for smaller arrays. The "magic numbers" in the + * computation below must be changed if MIN_MERGE is decreased. See + * the MIN_MERGE declaration above for more information. + */ + int stackLen = (len < 120 ? 5 : + len < 1542 ? 10 : + len < 119151 ? 19 : 40); + runBase = new int[stackLen]; + runLen = new int[stackLen]; + } + + /* + * The next two methods (which are package private and static) constitute + * the entire API of this class. Each of these methods obeys the contract + * of the public method with the same signature in java.util.Arrays. + */ + + static void sort(T[] a, Comparator c) { + sort(a, 0, a.length, c); + } + + static void sort(T[] a, int lo, int hi, Comparator c) { + if (c == null) { + Arrays.sort(a, lo, hi); + return; + } + + rangeCheck(a.length, lo, hi); + int nRemaining = hi - lo; + if (nRemaining < 2) + return; // Arrays of size 0 and 1 are always sorted + + // If array is small, do a "mini-TimSort" with no merges + if (nRemaining < MIN_MERGE) { + int initRunLen = countRunAndMakeAscending(a, lo, hi, c); + binarySort(a, lo, hi, lo + initRunLen, c); + return; + } + + /** + * March over the array once, left to right, finding natural runs, + * extending short natural runs to minRun elements, and merging runs + * to maintain stack invariant. + */ + TimSort ts = new TimSort(a, c); + int minRun = minRunLength(nRemaining); + do { + // Identify next run + int runLen = countRunAndMakeAscending(a, lo, hi, c); + + // If run is short, extend to min(minRun, nRemaining) + if (runLen < minRun) { + int force = nRemaining <= minRun ? nRemaining : minRun; + binarySort(a, lo, lo + force, lo + runLen, c); + runLen = force; + } + + // Push run onto pending-run stack, and maybe merge + ts.pushRun(lo, runLen); + ts.mergeCollapse(); + + // Advance to find next run + lo += runLen; + nRemaining -= runLen; + } while (nRemaining != 0); + + // Merge all remaining runs to complete sort + assert lo == hi; + ts.mergeForceCollapse(); + assert ts.stackSize == 1; + } + + /** + * Sorts the specified portion of the specified array using a binary + * insertion sort. This is the best method for sorting small numbers + * of elements. It requires O(n log n) compares, but O(n^2) data + * movement (worst case). + * + * If the initial part of the specified range is already sorted, + * this method can take advantage of it: the method assumes that the + * elements from index {@code lo}, inclusive, to {@code start}, + * exclusive are already sorted. + * + * @param a the array in which a range is to be sorted + * @param lo the index of the first element in the range to be sorted + * @param hi the index after the last element in the range to be sorted + * @param start the index of the first element in the range that is + * not already known to be sorted (@code lo <= start <= hi} + * @param c comparator to used for the sort + */ + @SuppressWarnings("fallthrough") + private static void binarySort(T[] a, int lo, int hi, int start, + Comparator c) { + assert lo <= start && start <= hi; + if (start == lo) + start++; + for ( ; start < hi; start++) { + T pivot = a[start]; + + // Set left (and right) to the index where a[start] (pivot) belongs + int left = lo; + int right = start; + assert left <= right; + /* + * Invariants: + * pivot >= all in [lo, left). + * pivot < all in [right, start). + */ + while (left < right) { + int mid = (left + right) >>> 1; + if (c.compare(pivot, a[mid]) < 0) + right = mid; + else + left = mid + 1; + } + assert left == right; + + /* + * The invariants still hold: pivot >= all in [lo, left) and + * pivot < all in [left, start), so pivot belongs at left. Note + * that if there are elements equal to pivot, left points to the + * first slot after them -- that's why this sort is stable. + * Slide elements over to make room to make room for pivot. + */ + int n = start - left; // The number of elements to move + // Switch is just an optimization for arraycopy in default case + switch(n) { + case 2: a[left + 2] = a[left + 1]; + case 1: a[left + 1] = a[left]; + break; + default: System.arraycopy(a, left, a, left + 1, n); + } + a[left] = pivot; + } + } + + /** + * Returns the length of the run beginning at the specified position in + * the specified array and reverses the run if it is descending (ensuring + * that the run will always be ascending when the method returns). + * + * A run is the longest ascending sequence with: + * + * a[lo] <= a[lo + 1] <= a[lo + 2] <= ... + * + * or the longest descending sequence with: + * + * a[lo] > a[lo + 1] > a[lo + 2] > ... + * + * For its intended use in a stable mergesort, the strictness of the + * definition of "descending" is needed so that the call can safely + * reverse a descending sequence without violating stability. + * + * @param a the array in which a run is to be counted and possibly reversed + * @param lo index of the first element in the run + * @param hi index after the last element that may be contained in the run. + It is required that @code{lo < hi}. + * @param c the comparator to used for the sort + * @return the length of the run beginning at the specified position in + * the specified array + */ + private static int countRunAndMakeAscending(T[] a, int lo, int hi, + Comparator c) { + assert lo < hi; + int runHi = lo + 1; + if (runHi == hi) + return 1; + + // Find end of run, and reverse range if descending + if (c.compare(a[runHi++], a[lo]) < 0) { // Descending + while(runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0) + runHi++; + reverseRange(a, lo, runHi); + } else { // Ascending + while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) >= 0) + runHi++; + } + + return runHi - lo; + } + + /** + * Reverse the specified range of the specified array. + * + * @param a the array in which a range is to be reversed + * @param lo the index of the first element in the range to be reversed + * @param hi the index after the last element in the range to be reversed + */ + private static void reverseRange(Object[] a, int lo, int hi) { + hi--; + while (lo < hi) { + Object t = a[lo]; + a[lo++] = a[hi]; + a[hi--] = t; + } + } + + /** + * Returns the minimum acceptable run length for an array of the specified + * length. Natural runs shorter than this will be extended with + * {@link #binarySort}. + * + * Roughly speaking, the computation is: + * + * If n < MIN_MERGE, return n (it's too small to bother with fancy stuff). + * Else if n is an exact power of 2, return MIN_MERGE/2. + * Else return an int k, MIN_MERGE/2 <= k <= MIN_MERGE, such that n/k + * is close to, but strictly less than, an exact power of 2. + * + * For the rationale, see listsort.txt. + * + * @param n the length of the array to be sorted + * @return the length of the minimum run to be merged + */ + private static int minRunLength(int n) { + assert n >= 0; + int r = 0; // Becomes 1 if any 1 bits are shifted off + while (n >= MIN_MERGE) { + r |= (n & 1); + n >>= 1; + } + return n + r; + } + + /** + * Pushes the specified run onto the pending-run stack. + * + * @param runBase index of the first element in the run + * @param runLen the number of elements in the run + */ + private void pushRun(int runBase, int runLen) { + this.runBase[stackSize] = runBase; + this.runLen[stackSize] = runLen; + stackSize++; + } + + /** + * Examines the stack of runs waiting to be merged and merges adjacent runs + * until the stack invariants are reestablished: + * + * 1. runLen[i - 3] > runLen[i - 2] + runLen[i - 1] + * 2. runLen[i - 2] > runLen[i - 1] + * + * This method is called each time a new run is pushed onto the stack, + * so the invariants are guaranteed to hold for i < stackSize upon + * entry to the method. + */ + private void mergeCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n-1] <= runLen[n] + runLen[n+1]) { + if (runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } else if (runLen[n] <= runLen[n + 1]) { + mergeAt(n); + } else { + break; // Invariant is established + } + } + } + + /** + * Merges all runs on the stack until only one remains. This method is + * called once, to complete the sort. + */ + private void mergeForceCollapse() { + while (stackSize > 1) { + int n = stackSize - 2; + if (n > 0 && runLen[n - 1] < runLen[n + 1]) + n--; + mergeAt(n); + } + } + + /** + * Merges the two runs at stack indices i and i+1. Run i must be + * the penultimate or antepenultimate run on the stack. In other words, + * i must be equal to stackSize-2 or stackSize-3. + * + * @param i stack index of the first of the two runs to merge + */ + private void mergeAt(int i) { + assert stackSize >= 2; + assert i >= 0; + assert i == stackSize - 2 || i == stackSize - 3; + + int base1 = runBase[i]; + int len1 = runLen[i]; + int base2 = runBase[i + 1]; + int len2 = runLen[i + 1]; + assert len1 > 0 && len2 > 0; + assert base1 + len1 == base2; + + /* + * Record the length of the combined runs; if i is the 3rd-last + * run now, also slide over the last run (which isn't involved + * in this merge). The current run (i+1) goes away in any case. + */ + runLen[i] = len1 + len2; + if (i == stackSize - 3) { + runBase[i + 1] = runBase[i + 2]; + runLen[i + 1] = runLen[i + 2]; + } + stackSize--; + + /* + * Find where the first element of run2 goes in run1. Prior elements + * in run1 can be ignored (because they're already in place). + */ + int k = gallopRight(a[base2], a, base1, len1, 0, c); + assert k >= 0; + base1 += k; + len1 -= k; + if (len1 == 0) + return; + + /* + * Find where the last element of run1 goes in run2. Subsequent elements + * in run2 can be ignored (because they're already in place). + */ + len2 = gallopLeft(a[base1 + len1 - 1], a, base2, len2, len2 - 1, c); + assert len2 >= 0; + if (len2 == 0) + return; + + // Merge remaining runs, using tmp array with min(len1, len2) elements + if (len1 <= len2) + mergeLo(base1, len1, base2, len2); + else + mergeHi(base1, len1, base2, len2); + } + + /** + * Locates the position at which to insert the specified key into the + * specified sorted range; if the range contains an element equal to key, + * returns the index of the leftmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @param c the comparator used to order the range, and to search + * @return the int k, 0 <= k <= n such that a[b + k - 1] < key <= a[b + k], + * pretending that a[b - 1] is minus infinity and a[b + n] is infinity. + * In other words, key belongs at index b + k; or in other words, + * the first k elements of a should precede key, and the last n - k + * should follow it. + */ + private static int gallopLeft(T key, T[] a, int base, int len, int hint, + Comparator c) { + assert len > 0 && hint >= 0 && hint < len; + int lastOfs = 0; + int ofs = 1; + if (c.compare(key, a[base + hint]) > 0) { + // Gallop right until a[base+hint+lastOfs] < key <= a[base+hint+ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) > 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + lastOfs += hint; + ofs += hint; + } else { // key <= a[base + hint] + // Gallop left until a[base+hint-ofs] < key <= a[base+hint-lastOfs] + final int maxOfs = hint + 1; + while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) <= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to base + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[base+lastOfs] < key <= a[base+ofs], so key belongs somewhere + * to the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[base + lastOfs - 1] < key <= a[base + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (c.compare(key, a[base + m]) > 0) + lastOfs = m + 1; // a[base + m] < key + else + ofs = m; // key <= a[base + m] + } + assert lastOfs == ofs; // so a[base + ofs - 1] < key <= a[base + ofs] + return ofs; + } + + /** + * Like gallopLeft, except that if the range contains an element equal to + * key, gallopRight returns the index after the rightmost equal element. + * + * @param key the key whose insertion point to search for + * @param a the array in which to search + * @param base the index of the first element in the range + * @param len the length of the range; must be > 0 + * @param hint the index at which to begin the search, 0 <= hint < n. + * The closer hint is to the result, the faster this method will run. + * @param c the comparator used to order the range, and to search + * @return the int k, 0 <= k <= n such that a[b + k - 1] <= key < a[b + k] + */ + private static int gallopRight(T key, T[] a, int base, int len, + int hint, Comparator c) { + assert len > 0 && hint >= 0 && hint < len; + + int ofs = 1; + int lastOfs = 0; + if (c.compare(key, a[base + hint]) < 0) { + // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] + int maxOfs = hint + 1; + while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) < 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + int tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } else { // a[b + hint] <= key + // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] + int maxOfs = len - hint; + while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) >= 0) { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if (ofs <= 0) // int overflow + ofs = maxOfs; + } + if (ofs > maxOfs) + ofs = maxOfs; + + // Make offsets relative to b + lastOfs += hint; + ofs += hint; + } + assert -1 <= lastOfs && lastOfs < ofs && ofs <= len; + + /* + * Now a[b + lastOfs] <= key < a[b + ofs], so key belongs somewhere to + * the right of lastOfs but no farther right than ofs. Do a binary + * search, with invariant a[b + lastOfs - 1] <= key < a[b + ofs]. + */ + lastOfs++; + while (lastOfs < ofs) { + int m = lastOfs + ((ofs - lastOfs) >>> 1); + + if (c.compare(key, a[base + m]) < 0) + ofs = m; // key < a[b + m] + else + lastOfs = m + 1; // a[b + m] <= key + } + assert lastOfs == ofs; // so a[b + ofs - 1] <= key < a[b + ofs] + return ofs; + } + + /** + * Merges two adjacent runs in place, in a stable fashion. The first + * element of the first run must be greater than the first element of the + * second run (a[base1] > a[base2]), and the last element of the first run + * (a[base1 + len1-1]) must be greater than all elements of the second run. + * + * For performance, this method should be called only when len1 <= len2; + * its twin, mergeHi should be called if len1 >= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + private void mergeLo(int base1, int len1, int base2, int len2) { + assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy first run into temp array + T[] a = this.a; // For performance + T[] tmp = ensureCapacity(len1); + System.arraycopy(a, base1, tmp, 0, len1); + + int cursor1 = 0; // Indexes into tmp array + int cursor2 = base2; // Indexes int a + int dest = base1; // Indexes int a + + // Move first element of second run and deal with degenerate cases + a[dest++] = a[cursor2++]; + if (--len2 == 0) { + System.arraycopy(tmp, cursor1, a, dest, len1); + return; + } + if (len1 == 1) { + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + return; + } + + Comparator c = this.c; // Use local variable for performance + int minGallop = this.minGallop; // " " " " " + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run starts + * winning consistently. + */ + do { + assert len1 > 1 && len2 > 0; + if (c.compare(a[cursor2], tmp[cursor1]) < 0) { + a[dest++] = a[cursor2++]; + count2++; + count1 = 0; + if (--len2 == 0) + break outer; + } else { + a[dest++] = tmp[cursor1++]; + count1++; + count2 = 0; + if (--len1 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + assert len1 > 1 && len2 > 0; + count1 = gallopRight(a[cursor2], tmp, cursor1, len1, 0, c); + if (count1 != 0) { + System.arraycopy(tmp, cursor1, a, dest, count1); + dest += count1; + cursor1 += count1; + len1 -= count1; + if (len1 <= 1) // len1 == 1 || len1 == 0 + break outer; + } + a[dest++] = a[cursor2++]; + if (--len2 == 0) + break outer; + + count2 = gallopLeft(tmp[cursor1], a, cursor2, len2, 0, c); + if (count2 != 0) { + System.arraycopy(a, cursor2, a, dest, count2); + dest += count2; + cursor2 += count2; + len2 -= count2; + if (len2 == 0) + break outer; + } + a[dest++] = tmp[cursor1++]; + if (--len1 == 1) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len1 == 1) { + assert len2 > 0; + System.arraycopy(a, cursor2, a, dest, len2); + a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge + } else if (len1 == 0) { + throw new IllegalArgumentException( + "Comparison method violates its general contract!"); + } else { + assert len2 == 0; + assert len1 > 1; + System.arraycopy(tmp, cursor1, a, dest, len1); + } + } + + /** + * Like mergeLo, except that this method should be called only if + * len1 >= len2; mergeLo should be called if len1 <= len2. (Either method + * may be called if len1 == len2.) + * + * @param base1 index of first element in first run to be merged + * @param len1 length of first run to be merged (must be > 0) + * @param base2 index of first element in second run to be merged + * (must be aBase + aLen) + * @param len2 length of second run to be merged (must be > 0) + */ + private void mergeHi(int base1, int len1, int base2, int len2) { + assert len1 > 0 && len2 > 0 && base1 + len1 == base2; + + // Copy second run into temp array + T[] a = this.a; // For performance + T[] tmp = ensureCapacity(len2); + System.arraycopy(a, base2, tmp, 0, len2); + + int cursor1 = base1 + len1 - 1; // Indexes into a + int cursor2 = len2 - 1; // Indexes into tmp array + int dest = base2 + len2 - 1; // Indexes into a + + // Move last element of first run and deal with degenerate cases + a[dest--] = a[cursor1--]; + if (--len1 == 0) { + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + return; + } + if (len2 == 1) { + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; + return; + } + + Comparator c = this.c; // Use local variable for performance + int minGallop = this.minGallop; // " " " " " + outer: + while (true) { + int count1 = 0; // Number of times in a row that first run won + int count2 = 0; // Number of times in a row that second run won + + /* + * Do the straightforward thing until (if ever) one run + * appears to win consistently. + */ + do { + assert len1 > 0 && len2 > 1; + if (c.compare(tmp[cursor2], a[cursor1]) < 0) { + a[dest--] = a[cursor1--]; + count1++; + count2 = 0; + if (--len1 == 0) + break outer; + } else { + a[dest--] = tmp[cursor2--]; + count2++; + count1 = 0; + if (--len2 == 1) + break outer; + } + } while ((count1 | count2) < minGallop); + + /* + * One run is winning so consistently that galloping may be a + * huge win. So try that, and continue galloping until (if ever) + * neither run appears to be winning consistently anymore. + */ + do { + assert len1 > 0 && len2 > 1; + count1 = len1 - gallopRight(tmp[cursor2], a, base1, len1, len1 - 1, c); + if (count1 != 0) { + dest -= count1; + cursor1 -= count1; + len1 -= count1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, count1); + if (len1 == 0) + break outer; + } + a[dest--] = tmp[cursor2--]; + if (--len2 == 1) + break outer; + + count2 = len2 - gallopLeft(a[cursor1], tmp, 0, len2, len2 - 1, c); + if (count2 != 0) { + dest -= count2; + cursor2 -= count2; + len2 -= count2; + System.arraycopy(tmp, cursor2 + 1, a, dest + 1, count2); + if (len2 <= 1) // len2 == 1 || len2 == 0 + break outer; + } + a[dest--] = a[cursor1--]; + if (--len1 == 0) + break outer; + minGallop--; + } while (count1 >= MIN_GALLOP | count2 >= MIN_GALLOP); + if (minGallop < 0) + minGallop = 0; + minGallop += 2; // Penalize for leaving gallop mode + } // End of "outer" loop + this.minGallop = minGallop < 1 ? 1 : minGallop; // Write back to field + + if (len2 == 1) { + assert len1 > 0; + dest -= len1; + cursor1 -= len1; + System.arraycopy(a, cursor1 + 1, a, dest + 1, len1); + a[dest] = tmp[cursor2]; // Move first elt of run2 to front of merge + } else if (len2 == 0) { + throw new IllegalArgumentException( + "Comparison method violates its general contract!"); + } else { + assert len1 == 0; + assert len2 > 0; + System.arraycopy(tmp, 0, a, dest - (len2 - 1), len2); + } + } + + /** + * Ensures that the external array tmp has at least the specified + * number of elements, increasing its size if necessary. The size + * increases exponentially to ensure amortized linear time complexity. + * + * @param minCapacity the minimum required capacity of the tmp array + * @return tmp, whether or not it grew + */ + private T[] ensureCapacity(int minCapacity) { + if (tmp.length < minCapacity) { + // Compute smallest power of 2 > minCapacity + int newSize = minCapacity; + newSize |= newSize >> 1; + newSize |= newSize >> 2; + newSize |= newSize >> 4; + newSize |= newSize >> 8; + newSize |= newSize >> 16; + newSize++; + + if (newSize < 0) // Not bloody likely! + newSize = minCapacity; + else + newSize = Math.min(newSize, a.length >>> 1); + + @SuppressWarnings({"unchecked", "UnnecessaryLocalVariable"}) + T[] newArray = (T[]) new Object[newSize]; + tmp = newArray; + } + return tmp; + } + + /** + * Checks that fromIndex and toIndex are in range, and throws an + * appropriate exception if they aren't. + * + * @param arrayLen the length of the array + * @param fromIndex the index of the first element of the range + * @param toIndex the index after the last element of the range + * @throws IllegalArgumentException if fromIndex > toIndex + * @throws ArrayIndexOutOfBoundsException if fromIndex < 0 + * or toIndex > arrayLen + */ + private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) { + if (fromIndex > toIndex) + throw new IllegalArgumentException("fromIndex(" + fromIndex + + ") > toIndex(" + toIndex+")"); + if (fromIndex < 0) + throw new ArrayIndexOutOfBoundsException(fromIndex); + if (toIndex > arrayLen) + throw new ArrayIndexOutOfBoundsException(toIndex); + } +} diff --git a/jdk/test/java/util/TimSort/ArrayBuilder.java b/jdk/test/java/util/TimSort/ArrayBuilder.java new file mode 100644 index 00000000000..25194f6ca57 --- /dev/null +++ b/jdk/test/java/util/TimSort/ArrayBuilder.java @@ -0,0 +1,142 @@ +/* + * Copyright 2009 Google Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.Random; +import java.math.BigInteger; + +public enum ArrayBuilder { + + // These seven are from Tim's paper (listsort.txt) + + RANDOM_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = rnd.nextInt(); + return result; + } + }, + + DESCENDING_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = len - i; + return result; + } + }, + + ASCENDING_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = i; + return result; + } + }, + + ASCENDING_3_RND_EXCH_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = i; + for (int i = 0; i < 3; i++) + swap(result, rnd.nextInt(result.length), + rnd.nextInt(result.length)); + return result; + } + }, + + ASCENDING_10_RND_AT_END_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + int endStart = len - 10; + for (int i = 0; i < endStart; i++) + result[i] = i; + for (int i = endStart; i < len; i++) + result[i] = rnd.nextInt(endStart + 10); + return result; + } + }, + + ALL_EQUAL_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = 666; + return result; + } + }, + + DUPS_GALORE_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = rnd.nextInt(4); + return result; + } + }, + + RANDOM_WITH_DUPS_INT { + public Object[] build(int len) { + Integer[] result = new Integer[len]; + for (int i = 0; i < len; i++) + result[i] = rnd.nextInt(len); + return result; + } + }, + + PSEUDO_ASCENDING_STRING { + public String[] build(int len) { + String[] result = new String[len]; + for (int i = 0; i < len; i++) + result[i] = Integer.toString(i); + return result; + } + }, + + RANDOM_BIGINT { + public BigInteger[] build(int len) { + BigInteger[] result = new BigInteger[len]; + for (int i = 0; i < len; i++) + result[i] = HUGE.add(BigInteger.valueOf(rnd.nextInt(len))); + return result; + } + }; + + public abstract Object[] build(int len); + + public void resetRandom() { + rnd = new Random(666); + } + + private static Random rnd = new Random(666); + + private static void swap(Object[] a, int i, int j) { + Object t = a[i]; + a[i] = a[j]; + a[j] = t; + } + + private static BigInteger HUGE = BigInteger.ONE.shiftLeft(100); +} diff --git a/jdk/test/java/util/TimSort/README b/jdk/test/java/util/TimSort/README new file mode 100644 index 00000000000..7add0be0a50 --- /dev/null +++ b/jdk/test/java/util/TimSort/README @@ -0,0 +1,4 @@ +This directory contains benchmark programs used to compare the +performance of the TimSort algorithm against the historic 1997 +implementation of Arrays.sort. Any future benchmarking will require +minor modifications. diff --git a/jdk/test/java/util/TimSort/SortPerf.java b/jdk/test/java/util/TimSort/SortPerf.java new file mode 100644 index 00000000000..89b41bb7527 --- /dev/null +++ b/jdk/test/java/util/TimSort/SortPerf.java @@ -0,0 +1,66 @@ +/* + * Copyright 2009 Google Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.Arrays; + +public class SortPerf { + private static final int NUM_SETS = 5; + private static final int[] lengths = { 10, 100, 1000, 10000, 1000000 }; + + // Returns the number of repetitions as a function of the list length + private static int reps(int n) { + return (int) (12000000 / (n * Math.log10(n))); + } + + public static void main(String[] args) { + Sorter.warmup(); + + System.out.print("Strategy,Length"); + for (Sorter sorter : Sorter.values()) + System.out.print("," + sorter); + System.out.println(); + + for (ArrayBuilder ab : ArrayBuilder.values()) { + for (int n : lengths) { + System.out.printf("%s,%d", ab, n); + int reps = reps(n); + Object[] proto = ab.build(n); + for (Sorter sorter : Sorter.values()) { + double minTime = Double.POSITIVE_INFINITY; + for (int set = 0; set < NUM_SETS; set++) { + long startTime = System.nanoTime(); + for (int k = 0; k < reps; k++) { + Object[] a = proto.clone(); + sorter.sort(a); + } + long endTime = System.nanoTime(); + double time = (endTime - startTime) / (1000000. * reps); + minTime = Math.min(minTime, time); + } + System.out.printf(",%5f", minTime); + } + System.out.println(); + } + } + } +} diff --git a/jdk/test/java/util/TimSort/Sorter.java b/jdk/test/java/util/TimSort/Sorter.java new file mode 100644 index 00000000000..4867996490f --- /dev/null +++ b/jdk/test/java/util/TimSort/Sorter.java @@ -0,0 +1,55 @@ +/* + * Copyright 2009 Google Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +import java.util.*; + +public enum Sorter { + TIMSORT { + public void sort(Object[] array) { + ComparableTimSort.sort(array); + } + }, + MERGESORT { + public void sort(Object[] array) { + Arrays.sort(array); + } + }; + + public abstract void sort(Object[] array); + + public static void warmup() { + System.out.println("start warm up"); + Integer[] gold = new Integer[10000]; + Random random = new java.util.Random(); + for (int i=0; i < gold.length; i++) + gold[i] = random.nextInt(); + + for (int i=0; i < 10000; i++) { + for (Sorter s : values()) { + Integer[] test= gold.clone(); + s.sort(test); + } + } + System.out.println(" end warm up"); + } +} From 2d83195be50ebb1b92c534d119ed1ead93d128aa Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Wed, 29 Jul 2009 21:45:52 -0700 Subject: [PATCH 29/70] 6866719: Rename execvpe to avoid symbol clash with glibc 2.10 Reviewed-by: darcy --- jdk/src/solaris/native/java/lang/UNIXProcess_md.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c index 041413574d4..d0226d07735 100644 --- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c +++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c @@ -447,14 +447,16 @@ execve_with_shell_fallback(const char *file, } /** - * execvpe should have been included in the Unix standards. - * execvpe is identical to execvp, except that the child environment is + * 'execvpe' should have been included in the Unix standards, + * and is a GNU extension in glibc 2.10. + * + * JDK_execvpe is identical to execvp, except that the child environment is * specified via the 3rd argument instead of being inherited from environ. */ static void -execvpe(const char *file, - const char *argv[], - const char *const envp[]) +JDK_execvpe(const char *file, + const char *argv[], + const char *const envp[]) { /* This is one of the rare times it's more portable to declare an * external symbol explicitly, rather than via a system header. @@ -644,7 +646,7 @@ childProcess(void *arg) if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) goto WhyCantJohnnyExec; - execvpe(p->argv[0], p->argv, p->envv); + JDK_execvpe(p->argv[0], p->argv, p->envv); WhyCantJohnnyExec: /* We used to go to an awful lot of trouble to predict whether the From a74a7d0f30ff32e71b97981aa5997e728f4f775a Mon Sep 17 00:00:00 2001 From: Yuka Kamiya Date: Thu, 30 Jul 2009 14:45:04 +0900 Subject: [PATCH 30/70] 6866243: Javadoc for java.lang.Character still refers to Unicode 4 instead of 5 Reviewed-by: okutsu --- jdk/src/share/classes/java/lang/Character.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/java/lang/Character.java b/jdk/src/share/classes/java/lang/Character.java index 9b9c938fa1e..19790de3ae8 100644 --- a/jdk/src/share/classes/java/lang/Character.java +++ b/jdk/src/share/classes/java/lang/Character.java @@ -38,7 +38,7 @@ import java.util.Locale; * a character's category (lowercase letter, digit, etc.) and for converting * characters from uppercase to lowercase and vice versa. *

    - * Character information is based on the Unicode Standard, version 4.0. + * Character information is based on the Unicode Standard, version 5.1.0. *

    * The methods and data of class Character are defined by * the information in the UnicodeData file that is part of the From 08f07d0f8ae988eef70c57404f2f6202ad20a7e6 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 31 Jul 2009 08:44:28 +0100 Subject: [PATCH 31/70] 6867101: Path.checkAccess fails with sharing violation on special files such as pagefile.sys Reviewed-by: sherman --- .../classes/sun/nio/fs/WindowsConstants.java | 1 + .../sun/nio/fs/WindowsFileAttributes.java | 33 +++++++++++++++++++ jdk/test/java/nio/file/Path/Misc.java | 24 +++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java index 077a4893b2f..a99f3fd448f 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsConstants.java @@ -92,6 +92,7 @@ class WindowsConstants { public static final int ERROR_INVALID_DATA = 13; public static final int ERROR_NOT_SAME_DEVICE = 17; public static final int ERROR_NOT_READY = 21; + public static final int ERROR_SHARING_VIOLATION = 32; public static final int ERROR_FILE_EXISTS = 80; public static final int ERROR_INVALID_PARAMATER = 87; public static final int ERROR_DISK_FULL = 112; diff --git a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java index f930eab98d3..9a1e0bd1a15 100644 --- a/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java +++ b/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributes.java @@ -299,6 +299,9 @@ class WindowsFileAttributes throws WindowsException { if (!ensureAccurateMetadata) { + WindowsException firstException = null; + + // GetFileAttributesEx is the fastest way to read the attributes NativeBuffer buffer = NativeBuffers.getNativeBuffer(SIZEOF_FILE_ATTRIBUTE_DATA); try { @@ -310,9 +313,39 @@ class WindowsFileAttributes .getInt(address + OFFSETOF_FILE_ATTRIBUTE_DATA_ATTRIBUTES); if ((fileAttrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0) return fromFileAttributeData(address, 0); + } catch (WindowsException x) { + if (x.lastError() != ERROR_SHARING_VIOLATION) + throw x; + firstException = x; } finally { buffer.release(); } + + // For sharing violations, fallback to FindFirstFile if the file + // is not a root directory. + if (firstException != null) { + String search = path.getPathForWin32Calls(); + char last = search.charAt(search.length() -1); + if (last == ':' || last == '\\') + throw firstException; + buffer = getBufferForFindData(); + try { + long handle = FindFirstFile(search, buffer.address()); + FindClose(handle); + WindowsFileAttributes attrs = fromFindData(buffer.address()); + // FindFirstFile does not follow sym links. Even if + // followLinks is false, there isn't sufficient information + // in the WIN32_FIND_DATA structure to know if the reparse + // point is a sym link. + if (attrs.isReparsePoint()) + throw firstException; + return attrs; + } catch (WindowsException ignore) { + throw firstException; + } finally { + buffer.release(); + } + } } // file is reparse point so need to open file to get attributes diff --git a/jdk/test/java/nio/file/Path/Misc.java b/jdk/test/java/nio/file/Path/Misc.java index 066cf6bedf9..07418844fd8 100644 --- a/jdk/test/java/nio/file/Path/Misc.java +++ b/jdk/test/java/nio/file/Path/Misc.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 6838333 + * @bug 4313887 6838333 6866804 * @summary Unit test for java.nio.file.Path for miscellenous methods not * covered by other tests * @library .. @@ -106,6 +106,28 @@ public class Misc { dir.checkAccess(AccessMode.WRITE); dir.checkAccess(AccessMode.READ, AccessMode.WRITE); + /** + * Test: Check access to all files in all root directories. + * (A useful test on Windows for special files such as pagefile.sys) + */ + for (Path root: FileSystems.getDefault().getRootDirectories()) { + DirectoryStream stream; + try { + stream = root.newDirectoryStream(); + } catch (IOException x) { + continue; // skip root directories that aren't accessible + } + try { + for (Path entry: stream) { + try { + entry.checkAccess(); + } catch (AccessDeniedException ignore) { } + } + } finally { + stream.close(); + } + } + /** * Test: File does not exist */ From 6538a1bcf911c4dff0eb75958208b748dba8d474 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 31 Jul 2009 08:45:30 +0100 Subject: [PATCH 32/70] 6867244: Tests missing @run tag Reviewed-by: sherman --- .../java/nio/channels/DatagramChannel/BasicMulticastTests.java | 1 + .../nio/channels/DatagramChannel/MulticastSendReceiveTests.java | 1 + jdk/test/java/nio/file/Files/ContentType.java | 1 + 3 files changed, 3 insertions(+) diff --git a/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java b/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java index 6928bcded3e..86b9752ba0c 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/BasicMulticastTests.java @@ -25,6 +25,7 @@ * @bug 4527345 * @summary Unit test for DatagramChannel's multicast support * @build BasicMulticastTests NetworkConfiguration + * @run main BasicMulticastTests */ import java.nio.ByteBuffer; diff --git a/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java b/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java index 11e3b0be068..bb1b7037571 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java @@ -25,6 +25,7 @@ * @bug 4527345 * @summary Unit test for DatagramChannel's multicast support * @build MulticastSendReceiveTests NetworkConfiguration + * @run main MulticastSendReceiveTests */ import java.nio.ByteBuffer; diff --git a/jdk/test/java/nio/file/Files/ContentType.java b/jdk/test/java/nio/file/Files/ContentType.java index 8a2267ebd4e..fdbb9014ef6 100644 --- a/jdk/test/java/nio/file/Files/ContentType.java +++ b/jdk/test/java/nio/file/Files/ContentType.java @@ -26,6 +26,7 @@ * @summary Unit test for probeContentType method * @library .. * @build ContentType SimpleFileTypeDetector + * @run main ContentType */ import java.nio.file.*; From bdafe7ca74c373ff15b650ecfa4e114f55bdf8af Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Fri, 31 Jul 2009 16:21:30 +0800 Subject: [PATCH 33/70] 6867231: Regression: jdk/test/sun/security/krb5/ConfPlusProp.java error against jdk7/pit/b68 Reviewed-by: xuelei --- jdk/test/sun/security/krb5/ConfPlusProp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/sun/security/krb5/ConfPlusProp.java b/jdk/test/sun/security/krb5/ConfPlusProp.java index e2c49a237a9..ac9ec81c277 100644 --- a/jdk/test/sun/security/krb5/ConfPlusProp.java +++ b/jdk/test/sun/security/krb5/ConfPlusProp.java @@ -23,7 +23,7 @@ /* * @test * @bug 6857795 - * @buf 6858589 + * @bug 6858589 * @summary krb5.conf ignored if system properties on realm and kdc are provided */ From 099a44dbf827aa02d0260fae016f84b82da91c66 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 31 Jul 2009 16:27:35 +0400 Subject: [PATCH 34/70] 6865565: Test failed: /test/closed/javax/swing/JInternalFrame/6325652/bug6325652.java Reviewed-by: peterz --- .../swing/JInternalFrame/Test6325652.java | 105 +++++++++++++ .../swing/JInternalFrame/Test6505027.java | 113 ++++++-------- .../swing/JInternalFrame/Test6802868.java | 114 +++++++------- .../javax/swing/JScrollPane/Test6526631.java | 21 ++- jdk/test/javax/swing/SwingTest.java | 142 ++++++++---------- 5 files changed, 274 insertions(+), 221 deletions(-) create mode 100644 jdk/test/javax/swing/JInternalFrame/Test6325652.java diff --git a/jdk/test/javax/swing/JInternalFrame/Test6325652.java b/jdk/test/javax/swing/JInternalFrame/Test6325652.java new file mode 100644 index 00000000000..d9fea4487cb --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/Test6325652.java @@ -0,0 +1,105 @@ +/* + * 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 6325652 + * @summary Tests keyboard shortcuts + * @author Sergey Malenkov + * @library .. + */ + +import java.awt.AWTException; +import java.awt.Robot; +import java.awt.event.KeyEvent; +import java.beans.PropertyVetoException; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.JTextArea; + +public class Test6325652 { + + private static final int WIDTH = 300; + private static final int HEIGHT = 300; + + public static void main(String[] args) throws Throwable { + SwingTest.start(Test6325652.class); + } + + private static Robot robot; + private JInternalFrame internal; + + public Test6325652(JFrame frame) { + JDesktopPane desktop = new JDesktopPane(); + desktop.add(create(0)); + desktop.add(this.internal = create(1)); + frame.add(desktop); + } + + public void select() throws PropertyVetoException { + this.internal.setSelected(true); + } + + public static void stepFirst() throws AWTException { + robot = new Robot(); // initialize shared static field first time + click(KeyEvent.VK_CONTROL, KeyEvent.VK_F9); // iconify internal frame + } + + public void stepFirstValidate() { + if (!this.internal.isIcon()) { + throw new Error("frame should be an icon"); + } + } + + public static void stepSecond() { + click(KeyEvent.VK_CONTROL, KeyEvent.VK_F6); // navigate to the icon + click(KeyEvent.VK_CONTROL, KeyEvent.VK_F5); // restore the icon + } + + public void stepSecondValidate() { + if (this.internal.isIcon()) { + throw new Error("frame should not be an icon"); + } + } + + private static void click(int... keys) { + for (int key : keys) { + robot.keyPress(key); + } + for (int key : keys) { + robot.keyRelease(key); + } + } + + private static JInternalFrame create(int index) { + String text = "test" + index; // NON-NLS: frame identification + index = index * 3 + 1; + + JInternalFrame internal = new JInternalFrame(text, true, true, true, true); + internal.getContentPane().add(new JTextArea(text)); + internal.setBounds(10 * index, 10 * index, WIDTH, HEIGHT); + internal.setVisible(true); + return internal; + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/Test6505027.java b/jdk/test/javax/swing/JInternalFrame/Test6505027.java index 218769003cb..42923ec5e0c 100644 --- a/jdk/test/javax/swing/JInternalFrame/Test6505027.java +++ b/jdk/test/javax/swing/JInternalFrame/Test6505027.java @@ -26,6 +26,7 @@ * @bug 6505027 * @summary Tests focus problem inside internal frame * @author Sergey Malenkov + * @library .. */ import java.awt.AWTException; @@ -45,11 +46,10 @@ import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.JTextField; import javax.swing.SwingUtilities; -import javax.swing.WindowConstants; import javax.swing.table.DefaultTableModel; import javax.swing.table.TableColumn; -public class Test6505027 implements Runnable { +public class Test6505027 { private static final boolean INTERNAL = true; private static final boolean TERMINATE = true; @@ -57,80 +57,53 @@ public class Test6505027 implements Runnable { private static final int WIDTH = 450; private static final int HEIGHT = 200; private static final int OFFSET = 10; - private static final long PAUSE = 2048L; - private static final String[] COLUMNS = { "Size", "Shape" }; // NON-NLS - private static final String[] ITEMS = { "a", "b", "c", "d" }; // NON-NLS - private static final String KEY = "terminateEditOnFocusLost"; // NON-NLS + private static final String[] COLUMNS = { "Size", "Shape" }; // NON-NLS: column names + private static final String[] ITEMS = { "a", "b", "c", "d" }; // NON-NLS: combobox content + private static final String KEY = "terminateEditOnFocusLost"; // NON-NLS: property name - public static void main(String[] args) { - SwingUtilities.invokeLater(new Test6505027()); + public static void main(String[] args) throws Throwable { + SwingTest.start(Test6505027.class); + } - Component component = null; - while (component == null) { - try { - Thread.sleep(PAUSE); - } - catch (InterruptedException exception) { - // ignore interrupted exception - } - component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); + private final JTable table = new JTable(new DefaultTableModel(COLUMNS, 2)); + + public Test6505027(JFrame main) { + Container container = main; + if (INTERNAL) { + JInternalFrame frame = new JInternalFrame(); + frame.setBounds(OFFSET, OFFSET, WIDTH, HEIGHT); + frame.setVisible(true); + + JDesktopPane desktop = new JDesktopPane(); + desktop.add(frame, new Integer(1)); + + container.add(desktop); + container = frame; } + if (TERMINATE) { + this.table.putClientProperty(KEY, Boolean.TRUE); + } + TableColumn column = this.table.getColumn(COLUMNS[1]); + column.setCellEditor(new DefaultCellEditor(new JComboBox(ITEMS))); + + container.add(BorderLayout.NORTH, new JTextField()); + container.add(BorderLayout.CENTER, new JScrollPane(this.table)); + } + + public void press() throws AWTException { + Point point = this.table.getCellRect(1, 1, false).getLocation(); + SwingUtilities.convertPointToScreen(point, this.table); + + Robot robot = new Robot(); + robot.mouseMove(point.x + 1, point.y + 1); + robot.mousePress(InputEvent.BUTTON1_MASK); + } + + public static void validate() { + Component component = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner(); if (!component.getClass().equals(JComboBox.class)) { throw new Error("unexpected focus owner: " + component); } - SwingUtilities.getWindowAncestor(component).dispose(); - } - - private JTable table; - private Point point; - - public void run() { - if (this.table == null) { - JFrame main = new JFrame(); - main.setSize(WIDTH + OFFSET * 3, HEIGHT + OFFSET * 5); - main.setLocationRelativeTo(null); - main.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - main.setVisible(true); - - Container container = main; - if (INTERNAL) { - JInternalFrame frame = new JInternalFrame(); - frame.setBounds(OFFSET, OFFSET, WIDTH, HEIGHT); - frame.setVisible(true); - - JDesktopPane desktop = new JDesktopPane(); - desktop.add(frame, new Integer(1)); - - container.add(desktop); - container = frame; - } - this.table = new JTable(new DefaultTableModel(COLUMNS, 2)); - if (TERMINATE) { - this.table.putClientProperty(KEY, Boolean.TRUE); - } - TableColumn column = this.table.getColumn(COLUMNS[1]); - column.setCellEditor(new DefaultCellEditor(new JComboBox(ITEMS))); - - container.add(BorderLayout.NORTH, new JTextField()); - container.add(BorderLayout.CENTER, new JScrollPane(this.table)); - - SwingUtilities.invokeLater(this); - } - else if (this.point == null) { - this.point = this.table.getCellRect(1, 1, false).getLocation(); - SwingUtilities.convertPointToScreen(this.point, this.table); - SwingUtilities.invokeLater(this); - } - else { - try { - Robot robot = new Robot(); - robot.mouseMove(this.point.x + 1, this.point.y + 1); - robot.mousePress(InputEvent.BUTTON1_MASK); - } - catch (AWTException exception) { - throw new Error("unexpected exception", exception); - } - } } } diff --git a/jdk/test/javax/swing/JInternalFrame/Test6802868.java b/jdk/test/javax/swing/JInternalFrame/Test6802868.java index 74410df81fd..9f8eb9bb2e7 100644 --- a/jdk/test/javax/swing/JInternalFrame/Test6802868.java +++ b/jdk/test/javax/swing/JInternalFrame/Test6802868.java @@ -26,83 +26,73 @@ * @bug 6802868 * @summary JInternalFrame is not maximized when maximized parent frame * @author Alexander Potochkin + * @library .. */ -import sun.awt.SunToolkit; - import java.awt.Dimension; import java.awt.Point; -import java.awt.Robot; -import java.awt.Toolkit; import java.beans.PropertyVetoException; import javax.swing.JDesktopPane; import javax.swing.JFrame; import javax.swing.JInternalFrame; -import javax.swing.SwingUtilities; public class Test6802868 { - static JInternalFrame jif; - static JFrame frame; - static Dimension size; - static Point location; - public static void main(String[] args) throws Exception { - Robot robot = new Robot(); - robot.setAutoDelay(20); - SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + public static void main(String[] args) throws Throwable { + SwingTest.start(Test6802868.class); + } - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - frame = new JFrame(); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + private final JFrame frame; + private final JInternalFrame internal; + private Dimension size; + private Point location; - JDesktopPane jdp = new JDesktopPane(); - frame.getContentPane().add(jdp); + public Test6802868(JFrame frame) { + JDesktopPane desktop = new JDesktopPane(); - jif = new JInternalFrame("Title", true, true, true, true); - jdp.add(jif); - jif.setVisible(true); + this.frame = frame; + this.frame.add(desktop); - frame.setSize(200, 200); - frame.setLocationRelativeTo(null); - frame.setVisible(true); + this.internal = new JInternalFrame(getClass().getName(), true, true, true, true); + this.internal.setVisible(true); - try { - jif.setMaximum(true); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - toolkit.realSync(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - size = jif.getSize(); - frame.setSize(300, 300); - } - }); - toolkit.realSync(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - if (jif.getSize().equals(size)) { - throw new RuntimeException("InternalFrame hasn't changed its size"); - } - try { - jif.setIcon(true); - } catch (PropertyVetoException e) { - e.printStackTrace(); - } - location = jif.getDesktopIcon().getLocation(); - frame.setSize(400, 400); - } - }); - toolkit.realSync(); - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - if (jif.getDesktopIcon().getLocation().equals(location)) { - throw new RuntimeException("JDesktopIcon hasn't moved"); - } - } - }); + desktop.add(this.internal); + } + + public void firstAction() throws PropertyVetoException { + this.internal.setMaximum(true); + } + + public void firstTest() { + this.size = this.internal.getSize(); + resizeFrame(); + } + + public void firstValidation() { + if (this.internal.getSize().equals(this.size)) { + throw new Error("InternalFrame hasn't changed its size"); + } + } + + public void secondAction() throws PropertyVetoException { + this.internal.setIcon(true); + } + + public void secondTest() { + this.location = this.internal.getDesktopIcon().getLocation(); + resizeFrame(); + } + + public void secondValidation() { + if (this.internal.getDesktopIcon().getLocation().equals(this.location)) { + throw new Error("JDesktopIcon hasn't moved"); + } + } + + private void resizeFrame() { + Dimension size = this.frame.getSize(); + size.width += 10; + size.height += 10; + this.frame.setSize(size); } } diff --git a/jdk/test/javax/swing/JScrollPane/Test6526631.java b/jdk/test/javax/swing/JScrollPane/Test6526631.java index ec324623ee5..61a39c6371e 100644 --- a/jdk/test/javax/swing/JScrollPane/Test6526631.java +++ b/jdk/test/javax/swing/JScrollPane/Test6526631.java @@ -27,10 +27,9 @@ * @summary Resizes right-oriented scroll pane * @author Sergey Malenkov * @library .. - * @build SwingTest - * @run main Test6526631 */ +import java.awt.ComponentOrientation; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JScrollBar; @@ -38,15 +37,13 @@ import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JViewport; -import static java.awt.ComponentOrientation.RIGHT_TO_LEFT; - public class Test6526631 { private static final int COLS = 90; private static final int ROWS = 50; private static final int OFFSET = 10; - public static void main(String[] args) { + public static void main(String[] args) throws Throwable { SwingTest.start(Test6526631.class); } @@ -55,7 +52,7 @@ public class Test6526631 { public Test6526631(JFrame frame) { this.pane = new JScrollPane(new JTextArea(ROWS, COLS)); - this.pane.setComponentOrientation(RIGHT_TO_LEFT); + this.pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); this.frame = frame; this.frame.add(this.pane); } @@ -79,24 +76,24 @@ public class Test6526631 { public void validateThird() { JViewport viewport = this.pane.getViewport(); JScrollBar scroller = this.pane.getHorizontalScrollBar(); - if (!scroller.getComponentOrientation().equals(RIGHT_TO_LEFT)) { - throw new IllegalStateException("unexpected component orientation"); + if (!scroller.getComponentOrientation().equals(ComponentOrientation.RIGHT_TO_LEFT)) { + throw new Error("unexpected component orientation"); } int value = scroller.getValue(); if (value != 0) { - throw new IllegalStateException("unexpected scroll value"); + throw new Error("unexpected scroll value"); } int extent = viewport.getExtentSize().width; if (extent != scroller.getVisibleAmount()) { - throw new IllegalStateException("unexpected visible amount"); + throw new Error("unexpected visible amount"); } int size = viewport.getViewSize().width; if (size != scroller.getMaximum()) { - throw new IllegalStateException("unexpected maximum"); + throw new Error("unexpected maximum"); } int pos = size - extent - value; if (pos != viewport.getViewPosition().x) { - throw new IllegalStateException("unexpected position"); + throw new Error("unexpected position"); } } } diff --git a/jdk/test/javax/swing/SwingTest.java b/jdk/test/javax/swing/SwingTest.java index 7f486122e8c..006808880eb 100644 --- a/jdk/test/javax/swing/SwingTest.java +++ b/jdk/test/javax/swing/SwingTest.java @@ -21,7 +21,8 @@ * have any questions. */ -import java.io.PrintWriter; +import sun.awt.SunToolkit; +import java.awt.Toolkit; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -30,12 +31,18 @@ import java.util.Iterator; import java.util.Set; import java.util.TreeSet; import javax.swing.JFrame; - -import static javax.swing.SwingUtilities.invokeLater; +import javax.swing.SwingUtilities; /** - * SwingTestHelper is a utility class for writing regression tests + * SwingTest is a utility class for writing regression tests * that require interacting with the UI. + * It uses reflection to invoke all public methods without parameters. + * All static methods are starting on the current thread. + * Other methods including constructor are starting on the EDT. + * Between each method invocation all pending events are processed. + * The methods are sorted by name and invoked in that order. + * Failure of the test is signaled by any method throwing an exception. + * If no methods throw an exception the test is assumed to have passed. * * @author Sergey A. Malenkov */ @@ -44,99 +51,56 @@ final class SwingTest implements Runnable { private static final int WIDTH = 640; private static final int HEIGHT = 480; - public static void start(Class type) { + public static void start(Class type) throws Throwable { new SwingTest(type).start(); } - private final PrintWriter writer = new PrintWriter(System.out, true); + private final Class type; + private final Iterator methods; - private Class type; private JFrame frame; - private Iterator methods; private Object object; private Method method; private Throwable error; private SwingTest(Class type) { + Set methods = new TreeSet(new Comparator() { + public int compare(Method first, Method second) { + return first.getName().compareTo(second.getName()); + } + }); + for (Method method : type.getMethods()) { + if (method.getDeclaringClass().equals(type)) { + if (method.getReturnType().equals(void.class)) { + if (0 == method.getParameterTypes().length) { + methods.add(method); + } + } + } + } this.type = type; + this.methods = methods.iterator(); } public void run() { - synchronized (this.writer) { - if (this.error != null) { - this.frame.dispose(); - this.frame = null; - } - else if (this.object == null) { - invoke(); - Set methods = new TreeSet(new Comparator() { - public int compare(Method first, Method second) { - return first.getName().compareTo(second.getName()); - } - }); - for (Method method : this.type.getMethods()) { - if (method.getDeclaringClass().equals(this.type)) { - if (method.getReturnType().equals(void.class)) { - if (0 == method.getParameterTypes().length) { - methods.add(method); - } - } - } - } - this.methods = methods.iterator(); - } - else if (this.method != null) { - invoke(); - } - else if (this.methods.hasNext()) { - this.method = this.methods.next(); - } - else { - this.frame.dispose(); - this.frame = null; - this.type = null; - } - this.writer.notifyAll(); - } - } - - private void start() { - synchronized (this.writer) { - while (this.type != null) { - if ((this.method != null) && Modifier.isStatic(this.method.getModifiers())) { - invoke(); - } - else { - invokeLater(this); - try { - this.writer.wait(); - } - catch (InterruptedException exception) { - exception.printStackTrace(this.writer); - } - } - if ((this.frame == null) && (this.error != null)) { - throw new Error("unexpected error", this.error); - } - } - } - } - - private void invoke() { try { - if (this.method != null) { - this.writer.println(this.method); - this.method.invoke(this.object); - this.method = null; - } - else { - this.writer.println(this.type); + if (this.object == null) { + System.out.println(this.type); this.frame = new JFrame(this.type.getSimpleName()); this.frame.setSize(WIDTH, HEIGHT); this.frame.setLocationRelativeTo(null); - this.object = this.type.getConstructor(JFrame.class).newInstance(this.frame); + this.object = this.type.getConstructor(this.frame.getClass()).newInstance(this.frame); this.frame.setVisible(true); } + else if (this.method != null) { + System.out.println(this.method); + this.method.invoke(this.object); + } + else { + System.out.println((this.error == null) ? "PASSED" : "FAILED"); // NON-NLS: debug + this.frame.dispose(); + this.frame = null; + } } catch (NoSuchMethodException exception) { this.error = exception; @@ -156,5 +120,29 @@ final class SwingTest implements Runnable { catch (InvocationTargetException exception) { this.error = exception.getTargetException(); } + System.out.flush(); + this.method = this.methods.hasNext() && (this.error == null) + ? this.methods.next() + : null; + } + + private void start() throws Throwable { + do { + if ((this.method != null) && Modifier.isStatic(this.method.getModifiers())) { + run(); // invoke static method on the current thread + } + else { + SwingUtilities.invokeLater(this); // invoke on the event dispatch thread + } + Toolkit tk = Toolkit.getDefaultToolkit(); + if (tk instanceof SunToolkit) { + SunToolkit stk = (SunToolkit) tk; + stk.realSync(); // wait until done + } + } + while (this.frame != null); + if (this.error != null) { + throw this.error; + } } } From 426d2a0ee7502bbb428a2b85926f45642fe71a10 Mon Sep 17 00:00:00 2001 From: Alexey Utkin Date: Fri, 31 Jul 2009 17:24:27 +0400 Subject: [PATCH 35/70] 6851688: Hung up in applet application Reviewed-by: art, dcherepanov --- jdk/src/windows/native/sun/windows/awt_Toolkit.cpp | 6 +++--- jdk/src/windows/native/sun/windows/awt_Toolkit.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp index 5158ef6c43e..b612bd1bf16 100644 --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.cpp @@ -1596,18 +1596,18 @@ void AwtToolkit::RegisterEmbedderProcessId(HWND embedder) } JNIEnv* AwtToolkit::m_env; -HANDLE AwtToolkit::m_thread; +DWORD AwtToolkit::m_threadId; void AwtToolkit::SetEnv(JNIEnv *env) { if (m_env != NULL) { // If already cashed (by means of embeddedInit() call). return; } - m_thread = GetCurrentThread(); + m_threadId = GetCurrentThreadId(); m_env = env; } JNIEnv* AwtToolkit::GetEnv() { - return (m_env == NULL || m_thread != GetCurrentThread()) ? + return (m_env == NULL || m_threadId != GetCurrentThreadId()) ? (JNIEnv*)JNU_GetEnv(jvm, JNI_VERSION_1_2) : m_env; } diff --git a/jdk/src/windows/native/sun/windows/awt_Toolkit.h b/jdk/src/windows/native/sun/windows/awt_Toolkit.h index 0673201d026..efaf9ff8432 100644 --- a/jdk/src/windows/native/sun/windows/awt_Toolkit.h +++ b/jdk/src/windows/native/sun/windows/awt_Toolkit.h @@ -442,7 +442,7 @@ public: private: static JNIEnv *m_env; - static HANDLE m_thread; + static DWORD m_threadId; public: static void SetEnv(JNIEnv *env); static JNIEnv* GetEnv(); From 3fef36803a7a223a8b701fb19c865d644d77da35 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Sun, 2 Aug 2009 13:40:03 +0800 Subject: [PATCH 36/70] 6867687: keytool's standard.sh test timeout sometimes Reviewed-by: xuelei --- jdk/test/sun/security/tools/keytool/standard.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/test/sun/security/tools/keytool/standard.sh b/jdk/test/sun/security/tools/keytool/standard.sh index fe4a0a81312..f3e052ed510 100644 --- a/jdk/test/sun/security/tools/keytool/standard.sh +++ b/jdk/test/sun/security/tools/keytool/standard.sh @@ -24,6 +24,7 @@ # @test # @summary (almost) all keytool behaviors # @author Weijun Wang +# @run shell/timeout=600 standard.sh # # This test is always excecuted. # From 82eb86f2beac59294365b1b267500ca8da921439 Mon Sep 17 00:00:00 2001 From: Sergey Groznyh Date: Mon, 3 Aug 2009 19:22:02 +0400 Subject: [PATCH 37/70] 6539700: JTextPane line wrap radically different from previous versions in jre 1.5.0_10+ Reviewed-by: peterz --- .../classes/javax/swing/text/GlyphView.java | 25 +--- .../javax/swing/text/ParagraphView.java | 30 +---- .../text/GlyphView/6539700/bug6539700.java | 114 ++++++++++++++++++ 3 files changed, 116 insertions(+), 53 deletions(-) create mode 100644 jdk/test/javax/swing/text/GlyphView/6539700/bug6539700.java diff --git a/jdk/src/share/classes/javax/swing/text/GlyphView.java b/jdk/src/share/classes/javax/swing/text/GlyphView.java index 087e9201545..64db8cd6cd1 100644 --- a/jdk/src/share/classes/javax/swing/text/GlyphView.java +++ b/jdk/src/share/classes/javax/swing/text/GlyphView.java @@ -540,30 +540,7 @@ public class GlyphView extends View implements TabableView, Cloneable { */ @Override public float getMinimumSpan(int axis) { - switch (axis) { - case View.X_AXIS: - if (minimumSpan < 0) { - minimumSpan = 0; - int p0 = getStartOffset(); - int p1 = getEndOffset(); - while (p1 > p0) { - int breakSpot = getBreakSpot(p0, p1); - if (breakSpot == BreakIterator.DONE) { - // the rest of the view is non-breakable - breakSpot = p0; - } - minimumSpan = Math.max(minimumSpan, - getPartialSpan(breakSpot, p1)); - // Note: getBreakSpot returns the *last* breakspot - p1 = breakSpot - 1; - } - } - return minimumSpan; - case View.Y_AXIS: - return super.getMinimumSpan(axis); - default: - throw new IllegalArgumentException("Invalid axis: " + axis); - } + return super.getMinimumSpan(axis); } /** diff --git a/jdk/src/share/classes/javax/swing/text/ParagraphView.java b/jdk/src/share/classes/javax/swing/text/ParagraphView.java index 2b5f7826a08..c02ea4d810e 100644 --- a/jdk/src/share/classes/javax/swing/text/ParagraphView.java +++ b/jdk/src/share/classes/javax/swing/text/ParagraphView.java @@ -721,35 +721,7 @@ public class ParagraphView extends FlowView implements TabExpander { @Override protected SizeRequirements calculateMinorAxisRequirements(int axis, SizeRequirements r) { - r = super.calculateMinorAxisRequirements(axis, r); - - float min = 0; - float glue = 0; - int n = getLayoutViewCount(); - for (int i = 0; i < n; i++) { - View v = getLayoutView(i); - float span = v.getMinimumSpan(axis); - if (v.getBreakWeight(axis, 0, v.getMaximumSpan(axis)) - > View.BadBreakWeight) { - // find the longest non-breakable fragments at the view edges - int p0 = v.getStartOffset(); - int p1 = v.getEndOffset(); - float start = findEdgeSpan(v, axis, p0, p0, p1); - float end = findEdgeSpan(v, axis, p1, p0, p1); - glue += start; - min = Math.max(min, Math.max(span, glue)); - glue = end; - } else { - // non-breakable view - glue += span; - min = Math.max(min, glue); - } - } - r.minimum = Math.max(r.minimum, (int) min); - r.preferred = Math.max(r.minimum, r.preferred); - r.maximum = Math.max(r.preferred, r.maximum); - - return r; + return super.calculateMinorAxisRequirements(axis, r); } /** diff --git a/jdk/test/javax/swing/text/GlyphView/6539700/bug6539700.java b/jdk/test/javax/swing/text/GlyphView/6539700/bug6539700.java new file mode 100644 index 00000000000..8d83f2e22d4 --- /dev/null +++ b/jdk/test/javax/swing/text/GlyphView/6539700/bug6539700.java @@ -0,0 +1,114 @@ +/* + * 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 6539700 + * @summary test that the long space-less lines are correctly soft-wrapped + * @author Sergey Groznyh + * @run main bug6539700 + */ + +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.text.ParagraphView; +import javax.swing.text.View; + +public class bug6539700 { + static JFrame f; + static JEditorPane ep; + static String text = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAA"; + static int size = 100; + static Class rowClass = null; + + static void createContentPane() { + ep = new JEditorPane(); + ep.setContentType("text/html"); + ep.setEditable(false); + ep.setText(text); + f = new JFrame(); + f.setSize(size, 2 * size); + f.add(ep); + f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + f.setVisible(true); + } + + static void checkRows(View v, boolean last) { + int width = (int) v.getPreferredSpan(View.X_AXIS); + + if (v.getClass() == rowClass) { + // Row width shouldn't exceed the container width + if (width > size) { + throw new RuntimeException("too long row: " + width); + } + + // Row shouldn't be too short (except for the last one) + if (!last) { + if (width < size * 2 / 3) { + throw new RuntimeException("too short row: " + width); + } + } + } + + int n = v.getViewCount(); + if (n > 0) { + for (int i = 0; i < n; i++) { + View c = v.getView(i); + checkRows(c, i == n - 1); + } + } + } + + public static void main(String[] argv) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createContentPane(); + } + }); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + + Class[] pvchildren = ParagraphView.class.getDeclaredClasses(); + for (Class c : pvchildren) { + if (c.getName().equals("javax.swing.text.ParagraphView$Row")) { + rowClass = c; + break; + } + } + if (rowClass == null) { + throw new RuntimeException("can't find ParagraphView.Row class"); + } + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + checkRows(ep.getUI().getRootView(ep), true); + } + }); + + System.out.println("OK"); + } +} From 6dfe09a9a619e753084d64831c66cbc8a81527f4 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Tue, 4 Aug 2009 12:44:03 -0700 Subject: [PATCH 38/70] 4116222: Errors in Arabic code-conversion tables, part II Updated the IBM420 datatable Reviewed-by: alanb --- jdk/make/tools/CharsetMapping/IBM420.c2b | 188 ++++++- jdk/make/tools/CharsetMapping/IBM420.map | 510 +++++++++--------- jdk/make/tools/CharsetMapping/IBM420.nr | 2 +- .../tools/charsetmapping/GenerateSBCS.java | 194 +++---- 4 files changed, 543 insertions(+), 351 deletions(-) diff --git a/jdk/make/tools/CharsetMapping/IBM420.c2b b/jdk/make/tools/CharsetMapping/IBM420.c2b index 6cb38028124..7e0c201b41b 100644 --- a/jdk/make/tools/CharsetMapping/IBM420.c2b +++ b/jdk/make/tools/CharsetMapping/IBM420.c2b @@ -1 +1,187 @@ -0x15 U+0085 +# +# The diff of 01A434B0.TXMAP110 and 34B001A4.RXMAP110 +# +# Added: 0x15 U+0085 +# +0x15 U+0085 +0x42 U+FE7C +0x46 U+FE80 +0x47 U+FE81 +0x49 U+FE83 +0x4B U+066C +0x4B U+FF0E +0x4C U+FF1C +0x4D U+FF08 +0x4E U+FF0B +0x4F U+FF5C +0x50 U+FF06 +0x52 U+FE85 +0x52 U+FE86 +0x55 U+FE89 +0x55 U+FE8A +0x55 U+FE8B +0x55 U+FE8C +0x56 U+0625 +0x56 U+FE87 +0x56 U+FE8D +0x57 U+FE88 +0x58 U+FE8F +0x58 U+FE90 +0x59 U+FE92 +0x5A U+FF01 +0x5B U+FF04 +0x5C U+066D +0x5C U+FF0A +0x5D U+FF09 +0x5E U+FF1B +0x60 U+FF0D +0x61 U+FF0F +0x62 U+FE93 +0x62 U+FE94 +0x63 U+FE95 +0x63 U+FE96 +0x64 U+FE98 +0x65 U+FE99 +0x65 U+FE9A +0x66 U+FE9C +0x67 U+FE9D +0x67 U+FE9E +0x68 U+FEA0 +0x69 U+FEA1 +0x69 U+FEA2 +0x6B U+066B +0x6B U+FF0C +0x6C U+066A +0x6C U+FF05 +0x6D U+FF3F +0x6E U+FF1E +0x6F U+FF1F +0x70 U+FEA4 +0x71 U+FEA5 +0x71 U+FEA6 +0x72 U+FEA8 +0x73 U+FEA9 +0x73 U+FEAA +0x74 U+FEAB +0x74 U+FEAC +0x75 U+FEAD +0x75 U+FEAE +0x76 U+FEAF +0x76 U+FEB0 +0x77 U+FEB1 +0x77 U+FEB2 +0x78 U+FEB4 +0x7A U+FF1A +0x7B U+FF03 +0x7C U+FF20 +0x7D U+FF07 +0x7E U+FF1D +0x7F U+FF02 +0x80 U+FEB5 +0x80 U+FEB6 +0x81 U+FF41 +0x82 U+FF42 +0x83 U+FF43 +0x84 U+FF44 +0x85 U+FF45 +0x86 U+FF46 +0x87 U+FF47 +0x88 U+FF48 +0x89 U+FF49 +0x8A U+FEB8 +0x8B U+FEB9 +0x8B U+FEBA +0x8C U+FEBC +0x8D U+FEBD +0x8D U+FEBE +0x8E U+FEC0 +0x8F U+FEC1 +0x8F U+FEC2 +0x8F U+FEC3 +0x8F U+FEC4 +0x90 U+FEC5 +0x90 U+FEC6 +0x90 U+FEC7 +0x90 U+FEC8 +0x91 U+FF4A +0x92 U+FF4B +0x93 U+FF4C +0x94 U+FF4D +0x95 U+FF4E +0x96 U+FF4F +0x97 U+FF50 +0x98 U+FF51 +0x99 U+FF52 +0x9A U+FEC9 +0x9E U+FECD +0xA2 U+FF53 +0xA3 U+FF54 +0xA4 U+FF55 +0xA5 U+FF56 +0xA6 U+FF57 +0xA7 U+FF58 +0xA8 U+FF59 +0xA9 U+FF5A +0xAB U+FED1 +0xAB U+FED2 +0xAC U+FED4 +0xAD U+FED5 +0xAD U+FED6 +0xAE U+FED8 +0xAF U+FED9 +0xAF U+FEDA +0xB0 U+FEDC +0xB1 U+FEDD +0xB1 U+FEDE +0xB8 U+FEF9 +0xB9 U+FEFA +0xBA U+FEE0 +0xBB U+FEE1 +0xBB U+FEE2 +0xBC U+FEE4 +0xBD U+FEE5 +0xBD U+FEE6 +0xBE U+FEE8 +0xBF U+FEE9 +0xBF U+FEEA +0xC1 U+FF21 +0xC2 U+FF22 +0xC3 U+FF23 +0xC4 U+FF24 +0xC5 U+FF25 +0xC6 U+FF26 +0xC7 U+FF27 +0xC8 U+FF28 +0xC9 U+FF29 +0xCF U+FEED +0xCF U+FEEE +0xD1 U+FF2A +0xD2 U+FF2B +0xD3 U+FF2C +0xD4 U+FF2D +0xD5 U+FF2E +0xD6 U+FF2F +0xD7 U+FF30 +0xD8 U+FF31 +0xD9 U+FF32 +0xDA U+FEEF +0xDC U+FEF1 +0xDE U+FEF4 +0xE2 U+FF33 +0xE3 U+FF34 +0xE4 U+FF35 +0xE5 U+FF36 +0xE6 U+FF37 +0xE7 U+FF38 +0xE8 U+FF39 +0xE9 U+FF3A +0xF0 U+FF10 +0xF1 U+FF11 +0xF2 U+FF12 +0xF3 U+FF13 +0xF4 U+FF14 +0xF5 U+FF15 +0xF6 U+FF16 +0xF7 U+FF17 +0xF8 U+FF18 +0xF9 U+FF19 diff --git a/jdk/make/tools/CharsetMapping/IBM420.map b/jdk/make/tools/CharsetMapping/IBM420.map index d4ce19249b3..f4f78533d27 100644 --- a/jdk/make/tools/CharsetMapping/IBM420.map +++ b/jdk/make/tools/CharsetMapping/IBM420.map @@ -1,257 +1,253 @@ -#Generated from IBM420.java -0x00 U+0000 -0x01 U+0001 -0x02 U+0002 -0x03 U+0003 -0x04 U+009c -0x05 U+0009 -0x06 U+0086 -0x07 U+007f -0x08 U+0097 -0x09 U+008d -0x0a U+008e -0x0b U+000b -0x0c U+000c -0x0d U+000d -0x0e U+000e -0x0f U+000f -0x10 U+0010 -0x11 U+0011 -0x12 U+0012 -0x13 U+0013 -0x14 U+009d -0x15 U+000a -0x16 U+0008 -0x17 U+0087 -0x18 U+0018 -0x19 U+0019 -0x1a U+0092 -0x1b U+008f -0x1c U+001c -0x1d U+001d -0x1e U+001e -0x1f U+001f -0x20 U+0080 -0x21 U+0081 -0x22 U+0082 -0x23 U+0083 -0x24 U+0084 -0x25 U+000a -0x26 U+0017 -0x27 U+001b -0x28 U+0088 -0x29 U+0089 -0x2a U+008a -0x2b U+008b -0x2c U+008c -0x2d U+0005 -0x2e U+0006 -0x2f U+0007 -0x30 U+0090 -0x31 U+0091 -0x32 U+0016 -0x33 U+0093 -0x34 U+0094 -0x35 U+0095 -0x36 U+0096 -0x37 U+0004 -0x38 U+0098 -0x39 U+0099 -0x3a U+009a -0x3b U+009b -0x3c U+0014 -0x3d U+0015 -0x3e U+009e -0x3f U+001a -0x40 U+0020 -0x41 U+00a0 -0x42 U+fe7c -0x43 U+fe7d -0x44 U+0640 -0x45 U+f8fc -0x46 U+fe80 -0x47 U+fe81 -0x48 U+fe82 -0x49 U+fe83 -0x4a U+00a2 -0x4b U+002e -0x4c U+003c -0x4d U+0028 -0x4e U+002b -0x4f U+007c -0x50 U+0026 -0x51 U+fe84 -0x52 U+fe85 -0x53 U+fffd -0x54 U+fffd -0x55 U+fe8b -0x56 U+fe8d -0x57 U+fe8e -0x58 U+fe8f -0x59 U+fe91 -0x5a U+0021 -0x5b U+0024 -0x5c U+002a -0x5d U+0029 -0x5e U+003b -0x5f U+00ac -0x60 U+002d -0x61 U+002f -0x62 U+fe93 -0x63 U+fe95 -0x64 U+fe97 -0x65 U+fe99 -0x66 U+fe9b -0x67 U+fe9d -0x68 U+fe9f -0x69 U+fea1 -0x6a U+00a6 -0x6b U+002c -0x6c U+0025 -0x6d U+005f -0x6e U+003e -0x6f U+003f -0x70 U+fea3 -0x71 U+fea5 -0x72 U+fea7 -0x73 U+fea9 -0x74 U+feab -0x75 U+fead -0x76 U+feaf -0x77 U+f8f6 -0x78 U+feb3 -0x79 U+060c -0x7a U+003a -0x7b U+0023 -0x7c U+0040 -0x7d U+0027 -0x7e U+003d -0x7f U+0022 -0x80 U+f8f5 -0x81 U+0061 -0x82 U+0062 -0x83 U+0063 -0x84 U+0064 -0x85 U+0065 -0x86 U+0066 -0x87 U+0067 -0x88 U+0068 -0x89 U+0069 -0x8a U+feb7 -0x8b U+f8f4 -0x8c U+febb -0x8d U+f8f7 -0x8e U+febf -0x8f U+fec3 -0x90 U+fec7 -0x91 U+006a -0x92 U+006b -0x93 U+006c -0x94 U+006d -0x95 U+006e -0x96 U+006f -0x97 U+0070 -0x98 U+0071 -0x99 U+0072 -0x9a U+fec9 -0x9b U+feca -0x9c U+fecb -0x9d U+fecc -0x9e U+fecd -0x9f U+fece -0xa0 U+fecf -0xa1 U+00f7 -0xa2 U+0073 -0xa3 U+0074 -0xa4 U+0075 -0xa5 U+0076 -0xa6 U+0077 -0xa7 U+0078 -0xa8 U+0079 -0xa9 U+007a -0xaa U+fed0 -0xab U+fed1 -0xac U+fed3 -0xad U+fed5 -0xae U+fed7 -0xaf U+fed9 -0xb0 U+fedb -0xb1 U+fedd -0xb2 U+fef5 -0xb3 U+fef6 -0xb4 U+fef7 -0xb5 U+fef8 -0xb6 U+fffd -0xb7 U+fffd -0xb8 U+fefb -0xb9 U+fefc -0xba U+fedf -0xbb U+fee1 -0xbc U+fee3 -0xbd U+fee5 -0xbe U+fee7 -0xbf U+fee9 -0xc0 U+061b -0xc1 U+0041 -0xc2 U+0042 -0xc3 U+0043 -0xc4 U+0044 -0xc5 U+0045 -0xc6 U+0046 -0xc7 U+0047 -0xc8 U+0048 -0xc9 U+0049 -0xca U+00ad -0xcb U+feeb -0xcc U+fffd -0xcd U+feec -0xce U+fffd -0xcf U+feed -0xd0 U+061f -0xd1 U+004a -0xd2 U+004b -0xd3 U+004c -0xd4 U+004d -0xd5 U+004e -0xd6 U+004f -0xd7 U+0050 -0xd8 U+0051 -0xd9 U+0052 -0xda U+feef -0xdb U+fef0 -0xdc U+fef1 -0xdd U+fef2 -0xde U+fef3 -0xdf U+0660 -0xe0 U+00d7 -0xe1 U+2007 -0xe2 U+0053 -0xe3 U+0054 -0xe4 U+0055 -0xe5 U+0056 -0xe6 U+0057 -0xe7 U+0058 -0xe8 U+0059 -0xe9 U+005a -0xea U+0661 -0xeb U+0662 -0xec U+fffd -0xed U+0663 -0xee U+0664 -0xef U+0665 -0xf0 U+0030 -0xf1 U+0031 -0xf2 U+0032 -0xf3 U+0033 -0xf4 U+0034 -0xf5 U+0035 -0xf6 U+0036 -0xf7 U+0037 -0xf8 U+0038 -0xf9 U+0039 -0xfa U+fffd -0xfb U+0666 -0xfc U+0667 -0xfd U+0668 -0xfe U+0669 -0xff U+009f +# +# Frm IBMCDC datatable 01A434B0.TXMAP110 +# +# Changed +# 0x15 U+0085 -> 0x15 U+000a +# +0x00 U+0000 +0x01 U+0001 +0x02 U+0002 +0x03 U+0003 +0x04 U+009C +0x05 U+0009 +0x06 U+0086 +0x07 U+007F +0x08 U+0097 +0x09 U+008D +0x0A U+008E +0x0B U+000B +0x0C U+000C +0x0D U+000D +0x0E U+000E +0x0F U+000F +0x10 U+0010 +0x11 U+0011 +0x12 U+0012 +0x13 U+0013 +0x14 U+009D +0x15 U+000A +0x16 U+0008 +0x17 U+0087 +0x18 U+0018 +0x19 U+0019 +0x1A U+0092 +0x1B U+008F +0x1C U+001C +0x1D U+001D +0x1E U+001E +0x1F U+001F +0x20 U+0080 +0x21 U+0081 +0x22 U+0082 +0x23 U+0083 +0x24 U+0084 +0x25 U+000A +0x26 U+0017 +0x27 U+001B +0x28 U+0088 +0x29 U+0089 +0x2A U+008A +0x2B U+008B +0x2C U+008C +0x2D U+0005 +0x2E U+0006 +0x2F U+0007 +0x30 U+0090 +0x31 U+0091 +0x32 U+0016 +0x33 U+0093 +0x34 U+0094 +0x35 U+0095 +0x36 U+0096 +0x37 U+0004 +0x38 U+0098 +0x39 U+0099 +0x3A U+009A +0x3B U+009B +0x3C U+0014 +0x3D U+0015 +0x3E U+009E +0x3F U+001A +0x40 U+0020 +0x41 U+00A0 +0x42 U+0651 +0x43 U+FE7D +0x44 U+0640 +0x45 U+200B +0x46 U+0621 +0x47 U+0622 +0x48 U+FE82 +0x49 U+0623 +0x4A U+00A2 +0x4B U+002E +0x4C U+003C +0x4D U+0028 +0x4E U+002B +0x4F U+007C +0x50 U+0026 +0x51 U+FE84 +0x52 U+0624 +0x55 U+0626 +0x56 U+0627 +0x57 U+FE8E +0x58 U+0628 +0x59 U+FE91 +0x5A U+0021 +0x5B U+0024 +0x5C U+002A +0x5D U+0029 +0x5E U+003B +0x5F U+00AC +0x60 U+002D +0x61 U+002F +0x62 U+0629 +0x63 U+062A +0x64 U+FE97 +0x65 U+062B +0x66 U+FE9B +0x67 U+062C +0x68 U+FE9F +0x69 U+062D +0x6A U+00A6 +0x6B U+002C +0x6C U+0025 +0x6D U+005F +0x6E U+003E +0x6F U+003F +0x70 U+FEA3 +0x71 U+062E +0x72 U+FEA7 +0x73 U+062F +0x74 U+0630 +0x75 U+0631 +0x76 U+0632 +0x77 U+0633 +0x78 U+FEB3 +0x79 U+060C +0x7A U+003A +0x7B U+0023 +0x7C U+0040 +0x7D U+0027 +0x7E U+003D +0x7F U+0022 +0x80 U+0634 +0x81 U+0061 +0x82 U+0062 +0x83 U+0063 +0x84 U+0064 +0x85 U+0065 +0x86 U+0066 +0x87 U+0067 +0x88 U+0068 +0x89 U+0069 +0x8A U+FEB7 +0x8B U+0635 +0x8C U+FEBB +0x8D U+0636 +0x8E U+FEBF +0x8F U+0637 +0x90 U+0638 +0x91 U+006A +0x92 U+006B +0x93 U+006C +0x94 U+006D +0x95 U+006E +0x96 U+006F +0x97 U+0070 +0x98 U+0071 +0x99 U+0072 +0x9A U+0639 +0x9B U+FECA +0x9C U+FECB +0x9D U+FECC +0x9E U+063A +0x9F U+FECE +0xA0 U+FECF +0xA1 U+00F7 +0xA2 U+0073 +0xA3 U+0074 +0xA4 U+0075 +0xA5 U+0076 +0xA6 U+0077 +0xA7 U+0078 +0xA8 U+0079 +0xA9 U+007A +0xAA U+FED0 +0xAB U+0641 +0xAC U+FED3 +0xAD U+0642 +0xAE U+FED7 +0xAF U+0643 +0xB0 U+FEDB +0xB1 U+0644 +0xB2 U+FEF5 +0xB3 U+FEF6 +0xB4 U+FEF7 +0xB5 U+FEF8 +0xB8 U+FEFB +0xB9 U+FEFC +0xBA U+FEDF +0xBB U+0645 +0xBC U+FEE3 +0xBD U+0646 +0xBE U+FEE7 +0xBF U+0647 +0xC0 U+061B +0xC1 U+0041 +0xC2 U+0042 +0xC3 U+0043 +0xC4 U+0044 +0xC5 U+0045 +0xC6 U+0046 +0xC7 U+0047 +0xC8 U+0048 +0xC9 U+0049 +0xCA U+00AD +0xCB U+FEEB +0xCD U+FEEC +0xCF U+0648 +0xD0 U+061F +0xD1 U+004A +0xD2 U+004B +0xD3 U+004C +0xD4 U+004D +0xD5 U+004E +0xD6 U+004F +0xD7 U+0050 +0xD8 U+0051 +0xD9 U+0052 +0xDA U+0649 +0xDB U+FEF0 +0xDC U+064A +0xDD U+FEF2 +0xDE U+FEF3 +0xDF U+0660 +0xE0 U+00D7 +0xE2 U+0053 +0xE3 U+0054 +0xE4 U+0055 +0xE5 U+0056 +0xE6 U+0057 +0xE7 U+0058 +0xE8 U+0059 +0xE9 U+005A +0xEA U+0661 +0xEB U+0662 +0xED U+0663 +0xEE U+0664 +0xEF U+0665 +0xF0 U+0030 +0xF1 U+0031 +0xF2 U+0032 +0xF3 U+0033 +0xF4 U+0034 +0xF5 U+0035 +0xF6 U+0036 +0xF7 U+0037 +0xF8 U+0038 +0xF9 U+0039 +0xFB U+0666 +0xFC U+0667 +0xFD U+0668 +0xFE U+0669 +0xFF U+009F diff --git a/jdk/make/tools/CharsetMapping/IBM420.nr b/jdk/make/tools/CharsetMapping/IBM420.nr index 675451906d4..c3d93ee4774 100644 --- a/jdk/make/tools/CharsetMapping/IBM420.nr +++ b/jdk/make/tools/CharsetMapping/IBM420.nr @@ -1 +1 @@ -0x25 U+000a +0x25 U+000a diff --git a/jdk/make/tools/src/build/tools/charsetmapping/GenerateSBCS.java b/jdk/make/tools/src/build/tools/charsetmapping/GenerateSBCS.java index 5d791d51591..8a57a6521bc 100644 --- a/jdk/make/tools/src/build/tools/charsetmapping/GenerateSBCS.java +++ b/jdk/make/tools/src/build/tools/charsetmapping/GenerateSBCS.java @@ -26,6 +26,7 @@ package build.tools.charsetmapping; import java.io.*; +import java.util.Arrays; import java.util.ArrayList; import java.util.Scanner; import java.util.Formatter; @@ -54,33 +55,19 @@ public class GenerateSBCS { String pkgName = fields[4]; System.out.printf("%s,%s,%s,%b,%s%n", clzName, csName, hisName, isASCII, pkgName); - StringBuilder b2c = new StringBuilder(); - int c2bLen = genB2C( - new FileInputStream(new File(args[0], clzName+".map")), b2c); - - String b2cNR = null; - File nrF = new File(args[0], clzName+".nr"); - if (nrF.exists()) { - b2cNR = genNR(new FileInputStream(nrF)); - } - - String c2bNR = null; - File c2bF = new File(args[0], clzName+".c2b"); - if (c2bF.exists()) { - c2bNR = genC2BNR(new FileInputStream(c2bF)); - } - - genSBCSClass(args[0], args[1], "SingleByte-X.java", - clzName, csName, hisName, pkgName, isASCII, - b2c.toString(), b2cNR, c2bNR, c2bLen); + genClass(args[0], args[1], "SingleByte-X.java", + clzName, csName, hisName, pkgName, isASCII); } } private static void toString(char[] sb, int off, int end, - Formatter out, String closure) { + Formatter out, String closure, + boolean comment) { while (off < end) { out.format(" \""); for (int j = 0; j < 8; j++) { + if (off == end) + break; char c = sb[off++]; switch (c) { case '\b': @@ -103,101 +90,124 @@ public class GenerateSBCS { out.format("\\u%04X", c & 0xffff); } } - if (off == end) - out.format("\" %s // 0x%02x - 0x%02x%n", closure, off-8, off-1); - else - out.format("\" + // 0x%02x - 0x%02x%n", off-8, off-1); + if (comment) { + if (off == end) + out.format("\" %s // 0x%02x - 0x%02x%n", + closure, off-8, off-1); + else + out.format("\" + // 0x%02x - 0x%02x%n", + off-8, off-1); + } else { + if (off == end) + out.format("\"%s%n", closure); + else + out.format("\" +%n"); + } } } static Pattern sbmap = Pattern.compile("0x(\\p{XDigit}++)\\s++U\\+(\\p{XDigit}++)(\\s++#.*)?"); - private static int genB2C(InputStream in, StringBuilder out) + + private static void genClass(String srcDir, String dstDir, + String template, + String clzName, + String csName, + String hisName, + String pkgName, + boolean isASCII) throws Exception { + StringBuilder b2cSB = new StringBuilder(); + StringBuilder b2cNRSB = new StringBuilder(); + StringBuilder c2bNRSB = new StringBuilder(); + char[] sb = new char[0x100]; - int[] indexC2B = new int[0x100]; + char[] c2bIndex = new char[0x100]; + int c2bOff = 0; + Arrays.fill(sb, UNMAPPABLE_DECODING); + Arrays.fill(c2bIndex, UNMAPPABLE_DECODING); - for (int i = 0; i < sb.length; i++) - sb[i] = UNMAPPABLE_DECODING; - - // parse the b2c mapping table + // (1)read in .map to parse all b->c entries + FileInputStream in = new FileInputStream( + new File(srcDir, clzName + ".map")); Parser p = new Parser(in, sbmap); Entry e = null; - int off = 0; + while ((e = p.next()) != null) { sb[e.bs] = (char)e.cp; - if (indexC2B[e.cp>>8] == 0) { - off += 0x100; - indexC2B[e.cp>>8] = 1; + if (c2bIndex[e.cp>>8] == UNMAPPABLE_DECODING) { + c2bOff += 0x100; + c2bIndex[e.cp>>8] = 1; } } - Formatter fm = new Formatter(out); + Formatter fm = new Formatter(b2cSB); fm.format("%n"); // vm -server shows cc[byte + 128] access is much faster than // cc[byte&0xff] so we output the upper segment first - toString(sb, 0x80, 0x100, fm, "+"); - toString(sb, 0x00, 0x80, fm, ";"); - + toString(sb, 0x80, 0x100, fm, "+", true); + toString(sb, 0x00, 0x80, fm, ";", true); fm.close(); - return off; - } - // generate non-roundtrip entries from xxx.nr file - private static String genNR(InputStream in) throws Exception - { - StringBuilder sb = new StringBuilder(); - Formatter fm = new Formatter(sb); - Parser p = new Parser(in, sbmap); - Entry e = null; - fm.format("// remove non-roundtrip entries%n"); - fm.format(" b2cMap = b2cTable.toCharArray();%n"); - while ((e = p.next()) != null) { - fm.format(" b2cMap[%d] = UNMAPPABLE_DECODING;%n", - (e.bs>=0x80)?(e.bs-0x80):(e.bs+0x80)); - } - fm.close(); - return sb.toString(); - } + // (2)now the .nr file which includes "b->c" non-roundtrip entries + File f = new File(srcDir, clzName + ".nr"); + if (f.exists()) { + in = new FileInputStream(f); + fm = new Formatter(b2cNRSB); + p = new Parser(in, sbmap); + e = null; - // generate c2b only entries from xxx.c2b file - private static String genC2BNR(InputStream in) throws Exception - { - StringBuilder sb = new StringBuilder(); - Formatter fm = new Formatter(sb); - Parser p = new Parser(in, sbmap); - ArrayList es = new ArrayList(); - Entry e = null; - while ((e = p.next()) != null) { - es.add(e); + fm.format("// remove non-roundtrip entries%n"); + fm.format(" b2cMap = b2cTable.toCharArray();%n"); + while ((e = p.next()) != null) { + fm.format(" b2cMap[%d] = UNMAPPABLE_DECODING;%n", + (e.bs>=0x80)?(e.bs-0x80):(e.bs+0x80)); + } + fm.close(); } - fm.format("// non-roundtrip c2b only entries%n"); - fm.format(" c2bNR = new char[%d];%n", es.size() * 2); - int i = 0; - for (Entry entry: es) { - fm.format(" c2bNR[%d] = 0x%x; c2bNR[%d] = 0x%x;%n", - i++, entry.bs, i++, entry.cp); + // (3)finally the .c2b file which includes c->b non-roundtrip entries + f = new File(srcDir, clzName + ".c2b"); + if (f.exists()) { + in = new FileInputStream(f); + fm = new Formatter(c2bNRSB); + p = new Parser(in, sbmap); + e = null; + ArrayList es = new ArrayList(); + while ((e = p.next()) != null) { + if (c2bIndex[e.cp>>8] == UNMAPPABLE_DECODING) { + c2bOff += 0x100; + c2bIndex[e.cp>>8] = 1; + } + es.add(e); + } + fm.format("// non-roundtrip c2b only entries%n"); + if (es.size() < 100) { + fm.format(" c2bNR = new char[%d];%n", es.size() * 2); + int i = 0; + for (Entry entry: es) { + fm.format(" c2bNR[%d] = 0x%x; c2bNR[%d] = 0x%x;%n", + i++, entry.bs, i++, entry.cp); + } + } else { + char[] cc = new char[es.size() * 2]; + int i = 0; + for (Entry entry: es) { + cc[i++] = (char)entry.bs; + cc[i++] = (char)entry.cp; + } + fm.format(" c2bNR = (%n"); + toString(cc, 0, i, fm, ").toCharArray();", false); + } + fm.close(); } - fm.close(); - return sb.toString(); - } - private static void genSBCSClass(String srcDir, - String dstDir, - String template, - String clzName, - String csName, - String hisName, - String pkgName, - boolean isASCII, - String b2c, - String b2cNR, - String c2bNR, - int c2blen) - throws Exception - { + // (4)it's time to generate the source file + String b2c = b2cSB.toString(); + String b2cNR = b2cNRSB.toString(); + String c2bNR = c2bNRSB.toString(); + Scanner s = new Scanner(new File(srcDir, template)); PrintStream out = new PrintStream(new FileOutputStream( new File(dstDir, clzName + ".java"))); @@ -239,16 +249,16 @@ public class GenerateSBCS { line = line.replace("$B2CTABLE$", b2c); } if (line.indexOf("$C2BLENGTH$") != -1) { - line = line.replace("$C2BLENGTH$", "0x" + Integer.toString(c2blen, 16)); + line = line.replace("$C2BLENGTH$", "0x" + Integer.toString(c2bOff, 16)); } if (line.indexOf("$NONROUNDTRIP_B2C$") != -1) { - if (b2cNR == null) + if (b2cNR.length() == 0) continue; line = line.replace("$NONROUNDTRIP_B2C$", b2cNR); } if (line.indexOf("$NONROUNDTRIP_C2B$") != -1) { - if (c2bNR == null) + if (c2bNR.length() == 0) continue; line = line.replace("$NONROUNDTRIP_C2B$", c2bNR); } From c857f977c3b496e30ccf5c0d1ae33c07076ce550 Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Tue, 4 Aug 2009 19:18:15 -0700 Subject: [PATCH 39/70] 6868160: (process) Use vfork, not fork, on Linux to avoid swap exhaustion Boldly go where no jdk has dared go before Reviewed-by: michaelm --- .../solaris/native/java/lang/UNIXProcess_md.c | 200 ++++++++++++------ 1 file changed, 138 insertions(+), 62 deletions(-) diff --git a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c index d0226d07735..8b0147bdfb7 100644 --- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c +++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c @@ -50,27 +50,72 @@ #include /* - * (Hopefully temporarily) disable the clone-exec feature pending - * further investigation and bug-fixing. - * 32-bit (but not 64-bit) Linux fails on the program - * Runtime.getRuntime().exec("/bin/true").waitFor(); - * with: - * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536 - * # Error: pthread_getattr_np failed with errno = 3 (ESRCH) - * Linux kernel/pthread gurus are invited to figure this out. + * There are 3 possible strategies we might use to "fork": + * + * - fork(2). Very portable and reliable but subject to + * failure due to overcommit (see the documentation on + * /proc/sys/vm/overcommit_memory in Linux proc(5)). + * This is the ancient problem of spurious failure whenever a large + * process starts a small subprocess. + * + * - vfork(). Using this is scary because all relevant man pages + * contain dire warnings, e.g. Linux vfork(2). But at least it's + * documented in the glibc docs and is standardized by XPG4. + * http://www.opengroup.org/onlinepubs/000095399/functions/vfork.html + * On Linux, one might think that vfork() would be implemented using + * the clone system call with flag CLONE_VFORK, but in fact vfork is + * a separate system call (which is a good sign, suggesting that + * vfork will continue to be supported at least on Linux). + * Another good sign is that glibc implements posix_spawn using + * vfork whenever possible. Note that we cannot use posix_spawn + * ourselves because there's no reliable way to close all inherited + * file descriptors. + * + * - clone() with flags CLONE_VM but not CLONE_THREAD. clone() is + * Linux-specific, but this ought to work - at least the glibc + * sources contain code to handle different combinations of CLONE_VM + * and CLONE_THREAD. However, when this was implemented, it + * appeared to fail on 32-bit i386 (but not 64-bit x86_64) Linux with + * the simple program + * Runtime.getRuntime().exec("/bin/true").waitFor(); + * with: + * # Internal Error (os_linux_x86.cpp:683), pid=19940, tid=2934639536 + * # Error: pthread_getattr_np failed with errno = 3 (ESRCH) + * We believe this is a glibc bug, reported here: + * http://sources.redhat.com/bugzilla/show_bug.cgi?id=10311 + * but the glibc maintainers closed it as WONTFIX. + * + * Based on the above analysis, we are currently using vfork() on + * Linux and fork() on other Unix systems, but the code to use clone() + * remains. */ -#define USE_CLONE 0 -#ifndef USE_CLONE -#ifdef __linux__ -#define USE_CLONE 1 -#else -#define USE_CLONE 0 -#endif +#define START_CHILD_USE_CLONE 0 /* clone() currently disabled; see above. */ + +#ifndef START_CHILD_USE_CLONE + #ifdef __linux__ + #define START_CHILD_USE_CLONE 1 + #else + #define START_CHILD_USE_CLONE 0 + #endif #endif -#if USE_CLONE +/* By default, use vfork() on Linux. */ +#ifndef START_CHILD_USE_VFORK + #ifdef __linux__ + #define START_CHILD_USE_VFORK 1 + #else + #define START_CHILD_USE_VFORK 0 + #endif +#endif + +#if START_CHILD_USE_CLONE #include +#define START_CHILD_SYSTEM_CALL "clone" +#elif START_CHILD_USE_VFORK +#define START_CHILD_SYSTEM_CALL "vfork" +#else +#define START_CHILD_SYSTEM_CALL "fork" #endif #ifndef STDIN_FILENO @@ -95,6 +140,20 @@ #define FAIL_FILENO (STDERR_FILENO + 1) +/* This is one of the rare times it's more portable to declare an + * external symbol explicitly, rather than via a system header. + * The declaration is standardized as part of UNIX98, but there is + * no standard (not even de-facto) header file where the + * declaration is to be found. See: + * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html + * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html + * + * "All identifiers in this volume of IEEE Std 1003.1-2001, except + * environ, are defined in at least one of the headers" (!) + */ +extern char **environ; + + static void setSIGCHLDHandler(JNIEnv *env) { @@ -434,13 +493,13 @@ execve_with_shell_fallback(const char *file, const char *argv[], const char *const envp[]) { -#if USE_CLONE +#if START_CHILD_USE_CLONE || START_CHILD_USE_VFORK + /* shared address space; be very careful. */ execve(file, (char **) argv, (char **) envp); if (errno == ENOEXEC) execve_as_traditional_shell_script(file, argv, envp); #else - /* Our address space is unshared, so can mutate environ. */ - extern char **environ; + /* unshared address space; we can mutate environ. */ environ = (char **) envp; execvp(file, (char **) argv); #endif @@ -458,19 +517,6 @@ JDK_execvpe(const char *file, const char *argv[], const char *const envp[]) { - /* This is one of the rare times it's more portable to declare an - * external symbol explicitly, rather than via a system header. - * The declaration is standardized as part of UNIX98, but there is - * no standard (not even de-facto) header file where the - * declaration is to be found. See: - * http://www.opengroup.org/onlinepubs/009695399/functions/environ.html - * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_02.html - * - * "All identifiers in this volume of IEEE Std 1003.1-2001, except - * environ, are defined in at least one of the headers" (!) - */ - extern char **environ; - if (envp == NULL || (char **) envp == environ) { execvp(file, (char **) argv); return; @@ -589,6 +635,9 @@ typedef struct _ChildStuff const char **envv; const char *pdir; jboolean redirectErrorStream; +#if START_CHILD_USE_CLONE + void *clone_stack; +#endif } ChildStuff; static void @@ -668,6 +717,55 @@ childProcess(void *arg) return 0; /* Suppress warning "no return value from function" */ } +/** + * Start a child process running function childProcess. + * This function only returns in the parent. + * We are unusually paranoid; use of clone/vfork is + * especially likely to tickle gcc/glibc bugs. + */ +#ifdef __attribute_noinline__ /* See: sys/cdefs.h */ +__attribute_noinline__ +#endif +static pid_t +startChild(ChildStuff *c) { +#if START_CHILD_USE_CLONE +#define START_CHILD_CLONE_STACK_SIZE (64 * 1024) + /* + * See clone(2). + * Instead of worrying about which direction the stack grows, just + * allocate twice as much and start the stack in the middle. + */ + if ((c->clone_stack = malloc(2 * START_CHILD_CLONE_STACK_SIZE)) == NULL) + /* errno will be set to ENOMEM */ + return -1; + return clone(childProcess, + c->clone_stack + START_CHILD_CLONE_STACK_SIZE, + CLONE_VFORK | CLONE_VM | SIGCHLD, c); +#else + #if START_CHILD_USE_VFORK + /* + * We separate the call to vfork into a separate function to make + * very sure to keep stack of child from corrupting stack of parent, + * as suggested by the scary gcc warning: + * warning: variable 'foo' might be clobbered by 'longjmp' or 'vfork' + */ + volatile pid_t resultPid = vfork(); + #else + /* + * From Solaris fork(2): In Solaris 10, a call to fork() is + * identical to a call to fork1(); only the calling thread is + * replicated in the child process. This is the POSIX-specified + * behavior for fork(). + */ + pid_t resultPid = fork(); + #endif + if (resultPid == 0) + childProcess(c); + assert(resultPid != 0); /* childProcess never returns */ + return resultPid; +#endif /* ! START_CHILD_USE_CLONE */ +} + JNIEXPORT jint JNICALL Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, jobject process, @@ -680,9 +778,6 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, { int errnum; int resultPid = -1; -#if USE_CLONE - void *clone_stack = NULL; -#endif int in[2], out[2], err[2], fail[2]; jint *fds = NULL; const char *pprog = NULL; @@ -696,6 +791,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, c->argv = NULL; c->envv = NULL; c->pdir = NULL; +#if START_CHILD_USE_CLONE + c->clone_stack = NULL; +#endif /* Convert prog + argBlock into a char ** argv. * Add one word room for expansion of argv for use by @@ -741,36 +839,14 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, c->redirectErrorStream = redirectErrorStream; - { -#if USE_CLONE - /* See clone(2). - * Instead of worrying about which direction the stack grows, just - * allocate twice as much and start the stack in the middle. */ - const int stack_size = 64 * 1024; - if ((clone_stack = NEW(char, 2 * stack_size)) == NULL) goto Catch; - resultPid = clone(childProcess, clone_stack + stack_size, - /* CLONE_VFORK | // works, but unnecessary */ - CLONE_VM | SIGCHLD, c); -#else - /* From fork(2): In Solaris 10, a call to fork() is identical - * to a call to fork1(); only the calling thread is replicated - * in the child process. This is the POSIX-specified behavior - * for fork(). */ - resultPid = fork(); - if (resultPid == 0) { - childProcess(c); - assert(0); /* childProcess must not return */ - } -#endif - } + resultPid = startChild(c); + assert(resultPid != 0); if (resultPid < 0) { - throwIOException(env, errno, "Fork failed"); + throwIOException(env, errno, START_CHILD_SYSTEM_CALL " failed"); goto Catch; } - /* parent process */ - close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ switch (readFully(fail[0], &errnum, sizeof(errnum))) { @@ -789,8 +865,8 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, fds[2] = (err[0] != -1) ? err[0] : -1; Finally: -#if USE_CLONE - free(clone_stack); +#if START_CHILD_USE_CLONE + free(c->clone_stack); #endif /* Always clean up the child's side of the pipes */ From 31e53b285c6c2867bdb583e26e38233b4e5f406d Mon Sep 17 00:00:00 2001 From: Martin Buchholz Date: Tue, 4 Aug 2009 19:18:15 -0700 Subject: [PATCH 40/70] 6856590: (process) Use RESTARTABLE in UNIXProcess_md.c Wrap all system calls with RESTARTABLE Reviewed-by: michaelm --- .../solaris/native/java/lang/UNIXProcess_md.c | 99 +++++++++++++------ 1 file changed, 70 insertions(+), 29 deletions(-) diff --git a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c index 8b0147bdfb7..3e1895926df 100644 --- a/jdk/src/solaris/native/java/lang/UNIXProcess_md.c +++ b/jdk/src/solaris/native/java/lang/UNIXProcess_md.c @@ -140,6 +140,13 @@ #define FAIL_FILENO (STDERR_FILENO + 1) +/* TODO: Refactor. */ +#define RESTARTABLE(_cmd, _result) do { \ + do { \ + _result = _cmd; \ + } while((_result == -1) && (errno == EINTR)); \ +} while(0) + /* This is one of the rare times it's more portable to declare an * external symbol explicitly, rather than via a system header. * The declaration is standardized as part of UNIX98, but there is @@ -342,6 +349,36 @@ Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env, } } +static ssize_t +restartableWrite(int fd, const void *buf, size_t count) +{ + ssize_t result; + RESTARTABLE(write(fd, buf, count), result); + return result; +} + +static int +restartableDup2(int fd_from, int fd_to) +{ + int err; + RESTARTABLE(dup2(fd_from, fd_to), err); + return err; +} + +static int +restartableClose(int fd) +{ + int err; + RESTARTABLE(close(fd), err); + return err; +} + +static int +closeSafely(int fd) +{ + return (fd == -1) ? 0 : restartableClose(fd); +} + static int isAsciiDigit(char c) { @@ -362,8 +399,8 @@ closeDescriptors(void) * the lowest numbered file descriptor, just like open(). So we * close a couple explicitly. */ - close(from_fd); /* for possible use by opendir() */ - close(from_fd + 1); /* another one for good luck */ + restartableClose(from_fd); /* for possible use by opendir() */ + restartableClose(from_fd + 1); /* another one for good luck */ if ((dp = opendir("/proc/self/fd")) == NULL) return 0; @@ -375,7 +412,7 @@ closeDescriptors(void) int fd; if (isAsciiDigit(dirp->d_name[0]) && (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2) - close(fd); + restartableClose(fd); } closedir(dp); @@ -383,13 +420,15 @@ closeDescriptors(void) return 1; } -static void +static int moveDescriptor(int fd_from, int fd_to) { if (fd_from != fd_to) { - dup2(fd_from, fd_to); - close(fd_from); + if ((restartableDup2(fd_from, fd_to) == -1) || + (restartableClose(fd_from) == -1)) + return -1; } + return 0; } static const char * @@ -586,13 +625,6 @@ JDK_execvpe(const char *file, } } -static void -closeSafely(int fd) -{ - if (fd != -1) - close(fd); -} - /* * Reads nbyte bytes from file descriptor fd into buf, * The read operation is retried in case of EINTR or partial reads. @@ -661,31 +693,40 @@ childProcess(void *arg) /* Close the parent sides of the pipes. Closing pipe fds here is redundant, since closeDescriptors() would do it anyways, but a little paranoia is a good thing. */ - closeSafely(p->in[1]); - closeSafely(p->out[0]); - closeSafely(p->err[0]); - closeSafely(p->fail[0]); + if ((closeSafely(p->in[1]) == -1) || + (closeSafely(p->out[0]) == -1) || + (closeSafely(p->err[0]) == -1) || + (closeSafely(p->fail[0]) == -1)) + goto WhyCantJohnnyExec; /* Give the child sides of the pipes the right fileno's. */ /* Note: it is possible for in[0] == 0 */ - moveDescriptor(p->in[0] != -1 ? p->in[0] : p->fds[0], STDIN_FILENO); - moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1], STDOUT_FILENO); + if ((moveDescriptor(p->in[0] != -1 ? p->in[0] : p->fds[0], + STDIN_FILENO) == -1) || + (moveDescriptor(p->out[1]!= -1 ? p->out[1] : p->fds[1], + STDOUT_FILENO) == -1)) + goto WhyCantJohnnyExec; if (p->redirectErrorStream) { - closeSafely(p->err[1]); - dup2(STDOUT_FILENO, STDERR_FILENO); + if ((closeSafely(p->err[1]) == -1) || + (restartableDup2(STDOUT_FILENO, STDERR_FILENO) == -1)) + goto WhyCantJohnnyExec; } else { - moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2], STDERR_FILENO); + if (moveDescriptor(p->err[1] != -1 ? p->err[1] : p->fds[2], + STDERR_FILENO) == -1) + goto WhyCantJohnnyExec; } - moveDescriptor(p->fail[1], FAIL_FILENO); + if (moveDescriptor(p->fail[1], FAIL_FILENO) == -1) + goto WhyCantJohnnyExec; /* close everything */ if (closeDescriptors() == 0) { /* failed, close the old way */ int max_fd = (int)sysconf(_SC_OPEN_MAX); - int i; - for (i = FAIL_FILENO + 1; i < max_fd; i++) - close(i); + int fd; + for (fd = FAIL_FILENO + 1; fd < max_fd; fd++) + if (restartableClose(fd) == -1 && errno != EBADF) + goto WhyCantJohnnyExec; } /* change to the new working directory */ @@ -710,9 +751,9 @@ childProcess(void *arg) */ { int errnum = errno; - write(FAIL_FILENO, &errnum, sizeof(errnum)); + restartableWrite(FAIL_FILENO, &errnum, sizeof(errnum)); } - close(FAIL_FILENO); + restartableClose(FAIL_FILENO); _exit(-1); return 0; /* Suppress warning "no return value from function" */ } @@ -847,7 +888,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, goto Catch; } - close(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ + restartableClose(fail[1]); fail[1] = -1; /* See: WhyCantJohnnyExec */ switch (readFully(fail[0], &errnum, sizeof(errnum))) { case 0: break; /* Exec succeeded */ From 8790c489e1e9fc78ec7976252a32c7455d95ef5d Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Wed, 5 Aug 2009 13:17:30 -0600 Subject: [PATCH 41/70] 6868533: 3/4 JDI: remove '-source 1.5' and '-target 1.5' options from com.sun.jdi tests We are long past needing to make sure these tests can build on Tiger/JDK1.5.0. Reviewed-by: tbell --- jdk/test/com/sun/jdi/EnumTest.java | 2 +- jdk/test/com/sun/jdi/GenericsTest.java | 2 +- jdk/test/com/sun/jdi/JdbVarargsTest.sh | 1 - jdk/test/com/sun/jdi/StepTest.java | 2 +- jdk/test/com/sun/jdi/UTF8Test.java | 2 +- jdk/test/com/sun/jdi/VarargsTest.java | 2 +- 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/jdk/test/com/sun/jdi/EnumTest.java b/jdk/test/com/sun/jdi/EnumTest.java index be06c0f4524..51d3a976ad5 100644 --- a/jdk/test/com/sun/jdi/EnumTest.java +++ b/jdk/test/com/sun/jdi/EnumTest.java @@ -29,7 +29,7 @@ * @author jjh * * @run build TestScaffold VMConnection TargetListener TargetAdapter - * @run compile -source 1.5 -target 1.5 -g EnumTest.java + * @run compile -g EnumTest.java * @run main EnumTest */ import com.sun.jdi.*; diff --git a/jdk/test/com/sun/jdi/GenericsTest.java b/jdk/test/com/sun/jdi/GenericsTest.java index 2220dd7bbfc..5156e9d8e09 100644 --- a/jdk/test/com/sun/jdi/GenericsTest.java +++ b/jdk/test/com/sun/jdi/GenericsTest.java @@ -29,7 +29,7 @@ * @author jjh * * @run build TestScaffold VMConnection TargetListener TargetAdapter - * @run compile -source 1.5 -target 1.5 -g GenericsTest.java + * @run compile -g GenericsTest.java * @run main GenericsTest */ import com.sun.jdi.*; diff --git a/jdk/test/com/sun/jdi/JdbVarargsTest.sh b/jdk/test/com/sun/jdi/JdbVarargsTest.sh index 72d9561f54c..82e0b18e60e 100644 --- a/jdk/test/com/sun/jdi/JdbVarargsTest.sh +++ b/jdk/test/com/sun/jdi/JdbVarargsTest.sh @@ -32,7 +32,6 @@ # @run shell JdbVarargsTest.sh classname=JdbVarargsTest -compileOptions="-source 1.5 -target 1.5" createJavaFile() { cat < $classname.java.1 diff --git a/jdk/test/com/sun/jdi/StepTest.java b/jdk/test/com/sun/jdi/StepTest.java index 9c2344d09db..041507a8b9d 100644 --- a/jdk/test/com/sun/jdi/StepTest.java +++ b/jdk/test/com/sun/jdi/StepTest.java @@ -27,7 +27,7 @@ * @author Gordon Hirsch * * @run build TestScaffold VMConnection TargetAdapter TargetListener - * @run compile -g -target 1.5 MethodCalls.java + * @run compile -g MethodCalls.java * @run compile -g MethodCallsReflection.java * @run compile -g ControlFlow.java * @run build StepTest diff --git a/jdk/test/com/sun/jdi/UTF8Test.java b/jdk/test/com/sun/jdi/UTF8Test.java index b7b28665894..4396770e093 100644 --- a/jdk/test/com/sun/jdi/UTF8Test.java +++ b/jdk/test/com/sun/jdi/UTF8Test.java @@ -29,7 +29,7 @@ * @author jjh * * @run build TestScaffold VMConnection TargetListener TargetAdapter - * @run compile -g -source 1.5 UTF8Test.java + * @run compile -g UTF8Test.java * @run main UTF8Test */ diff --git a/jdk/test/com/sun/jdi/VarargsTest.java b/jdk/test/com/sun/jdi/VarargsTest.java index ed4323e2d4f..1ea51ad245b 100644 --- a/jdk/test/com/sun/jdi/VarargsTest.java +++ b/jdk/test/com/sun/jdi/VarargsTest.java @@ -29,7 +29,7 @@ * @author jjh * * @run build TestScaffold VMConnection TargetListener TargetAdapter - * @run compile -g -source 1.5 -target 1.5 VarargsTest.java + * @run compile -g VarargsTest.java * @run main VarargsTest */ import com.sun.jdi.*; From 872d3ebfc728132613a43a8f41fcf4abf0bc5955 Mon Sep 17 00:00:00 2001 From: Lillian Angel Date: Thu, 6 Aug 2009 16:04:47 +0100 Subject: [PATCH 42/70] 6593649: Word wrap broken for JTextArea Layout correctly resizes components based on actual dimensions of the window they are in. Reviewed-by: gsm --- .../javax/swing/text/WrappedPlainView.java | 36 +++++++- .../javax/swing/JTextArea/Test6593649.java | 89 +++++++++++++++++++ 2 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 jdk/test/javax/swing/JTextArea/Test6593649.java diff --git a/jdk/src/share/classes/javax/swing/text/WrappedPlainView.java b/jdk/src/share/classes/javax/swing/text/WrappedPlainView.java index fb7aede7374..b845419ad78 100644 --- a/jdk/src/share/classes/javax/swing/text/WrappedPlainView.java +++ b/jdk/src/share/classes/javax/swing/text/WrappedPlainView.java @@ -327,13 +327,45 @@ public class WrappedPlainView extends BoxView implements TabExpander { /** * Return reasonable default values for the view dimensions. The standard * text terminal size 80x24 is pretty suitable for the wrapped plain view. + * + * The size should not be larger than the component housing the view's + * container. */ private float getDefaultSpan(int axis) { + Container host = getContainer(); + Component parent = null; + + if (host != null) { + parent = host.getParent(); + } + switch (axis) { case View.X_AXIS: - return 80 * metrics.getWidths()['M']; + int defaultWidth = 80 * metrics.getWidths()['M']; + int parentWidth = 0; + + if (parent != null) { + parentWidth = parent.getWidth(); + } + + if (defaultWidth > parentWidth) { + return parentWidth; + } + return defaultWidth; + case View.Y_AXIS: - return 24 * metrics.getHeight(); + int defaultHeight = 24 * metrics.getHeight(); + int parentHeight = 0; + + if (parent != null) { + parentHeight = parent.getHeight(); + } + + if (defaultHeight > parentHeight) { + return parentHeight; + } + return defaultHeight; + default: throw new IllegalArgumentException("Invalid axis: " + axis); } diff --git a/jdk/test/javax/swing/JTextArea/Test6593649.java b/jdk/test/javax/swing/JTextArea/Test6593649.java new file mode 100644 index 00000000000..8de478b3825 --- /dev/null +++ b/jdk/test/javax/swing/JTextArea/Test6593649.java @@ -0,0 +1,89 @@ +/* + * 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. + * + * 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 6593649 + @summary Word wrap does not work in JTextArea: long lines are not wrapped + @author Lillian Angel + @run main Test6593649 +*/ + +import javax.swing.*; +import java.awt.*; + +public class Test6593649 extends JFrame { + static JTextArea txt; + static JPanel innerPanel; + + public Test6593649(Dimension d) + { + super("Word Wrap Testcase"); + + setSize(d); + + final Container contentPane = getContentPane(); + + innerPanel = new JPanel(); + innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.LINE_AXIS)); + + txt = new JTextArea("This is a long line that should wrap, but doesn't..."); + txt.setLineWrap(true); + txt.setWrapStyleWord(true); + + innerPanel.add(txt); + + contentPane.add(innerPanel, BorderLayout.SOUTH); + } + + public static void main(String[] args) throws InterruptedException + { + int size = 100; + Dimension d; + Test6593649 cp; + Dimension txtSize; + Dimension innerSize; + Dimension cpSize; + + while (size <= 600) + { + d = new Dimension(size, size); + cp = new Test6593649(d); + cp.setVisible(true); + + txtSize = txt.getPreferredSize(); + innerSize = innerPanel.getPreferredSize(); + cpSize = cp.getSize(); + + if (!(txtSize.getWidth() == innerPanel.getWidth() && txtSize.getHeight() == innerPanel.getHeight() && + txtSize.getWidth() <= cpSize.getWidth() && txtSize.getHeight() <= cpSize.getHeight())) + { + throw new RuntimeException("Test failed: Text area size does not properly match panel and frame sizes"); + } + + Thread.sleep(2000); + + cp.hide(); + size += 50; + } + } +} From fc188b8b292d7f987191f68aba8267a92d892f99 Mon Sep 17 00:00:00 2001 From: Bradford Wetmore Date: Thu, 6 Aug 2009 17:56:59 -0700 Subject: [PATCH 43/70] 6867657: Many JSN tests do not run under cygwin Reviewed-by: ohair --- jdk/test/java/net/Authenticator/B4933582.sh | 10 ++-- .../ADatagramSocket.sh | 4 ++ jdk/test/java/net/Socket/OldSocketImpl.sh | 4 ++ jdk/test/java/net/URL/B5086147.sh | 4 ++ jdk/test/java/net/URL/runconstructor.sh | 4 ++ jdk/test/java/net/URLClassLoader/B5077773.sh | 4 ++ .../net/URLClassLoader/sealing/checksealed.sh | 12 +++-- .../java/net/URLConnection/6212146/test.sh | 4 ++ .../ClassLoaderDeadlock.sh | 6 ++- .../Security/ClassLoaderDeadlock/Deadlock.sh | 6 ++- .../java/security/Security/signedfirst/Dyn.sh | 6 ++- .../security/Security/signedfirst/Static.sh | 8 ++- .../crypto/SecretKeyFactory/FailOverTest.sh | 9 +++- .../javax/security/auth/Subject/doAs/Test.sh | 5 ++ .../lib/security/java.policy/Ext_AllPolicy.sh | 6 +++ jdk/test/sun/net/www/MarkResetTest.sh | 4 ++ .../ChunkedInputStream/ChunkedCharEncoding.sh | 4 ++ .../sun/net/www/http/HttpClient/RetryPost.sh | 4 ++ jdk/test/sun/net/www/protocol/jar/B5105410.sh | 4 ++ .../sun/net/www/protocol/jar/jarbug/run.sh | 49 +++++++++++++++---- .../pkcs11/Provider/ConfigQuotedString.sh | 14 ++++++ .../sun/security/pkcs11/Provider/Login.sh | 14 ++++++ .../PolicyFile/getinstance/getinstance.sh | 4 ++ .../ssl/SSLSocketImpl/NotifyHandshakeTest.sh | 23 ++++++--- .../https/HttpsURLConnection/PostThruProxy.sh | 7 ++- .../PostThruProxyWithAuth.sh | 8 ++- .../security/tools/jarsigner/AlgOptions.sh | 7 +++ .../security/tools/jarsigner/PercentSign.sh | 7 +++ .../sun/security/tools/jarsigner/oldsig.sh | 7 +++ .../security/tools/keytool/AltProviderPath.sh | 31 ++++++++++-- .../tools/keytool/CloneKeyAskPassword.sh | 4 ++ .../sun/security/tools/keytool/NoExtNPE.sh | 3 ++ .../sun/security/tools/keytool/SecretKeyKS.sh | 6 +++ .../security/tools/keytool/StandardAlgName.sh | 6 +++ jdk/test/sun/security/tools/keytool/i18n.sh | 6 +++ .../sun/security/tools/keytool/printssl.sh | 3 ++ .../sun/security/tools/keytool/resource.sh | 5 ++ .../sun/security/tools/keytool/standard.sh | 6 ++- 38 files changed, 280 insertions(+), 38 deletions(-) diff --git a/jdk/test/java/net/Authenticator/B4933582.sh b/jdk/test/java/net/Authenticator/B4933582.sh index b103592f42d..0826063a805 100644 --- a/jdk/test/java/net/Authenticator/B4933582.sh +++ b/jdk/test/java/net/Authenticator/B4933582.sh @@ -30,6 +30,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" @@ -39,7 +43,7 @@ case "$OS" in exit 1; ;; esac -${TESTJAVA}${FS}bin${FS}javac -d . -classpath ${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest ${TESTSRC}${FS}B4933582.java +${TESTJAVA}${FS}bin${FS}javac -d . -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest" ${TESTSRC}${FS}B4933582.java rm -f cache.ser auth.save -${TESTJAVA}${FS}bin${FS}java -classpath ${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}. B4933582 first -${TESTJAVA}${FS}bin${FS}java -classpath ${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}. B4933582 second +${TESTJAVA}${FS}bin${FS}java -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 first +${TESTJAVA}${FS}bin${FS}java -classpath "${TESTSRC}${FS}..${FS}..${FS}..${FS}sun${FS}net${FS}www${FS}httptest${PS}." B4933582 second diff --git a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh index ba8b7cb5184..18f7c0ea94c 100644 --- a/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh +++ b/jdk/test/java/net/DatagramSocket/SetDatagramSocketImplFactory/ADatagramSocket.sh @@ -35,6 +35,10 @@ case "$OS" in PATHSEP=":" FILESEP="/" ;; + CYGWIN* ) + PATHSEP=";" + FILESEP="/" + ;; Windows* ) PATHSEP=";" FILESEP="\\" diff --git a/jdk/test/java/net/Socket/OldSocketImpl.sh b/jdk/test/java/net/Socket/OldSocketImpl.sh index 85845464f2b..50692f8e045 100644 --- a/jdk/test/java/net/Socket/OldSocketImpl.sh +++ b/jdk/test/java/net/Socket/OldSocketImpl.sh @@ -32,6 +32,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/java/net/URL/B5086147.sh b/jdk/test/java/net/URL/B5086147.sh index 53034443a80..aaa9eadf31c 100644 --- a/jdk/test/java/net/URL/B5086147.sh +++ b/jdk/test/java/net/URL/B5086147.sh @@ -29,6 +29,10 @@ case "$OS" in SunOS | Linux ) exit 0 ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/java/net/URL/runconstructor.sh b/jdk/test/java/net/URL/runconstructor.sh index 93a80de4b3c..30ae96a3c10 100644 --- a/jdk/test/java/net/URL/runconstructor.sh +++ b/jdk/test/java/net/URL/runconstructor.sh @@ -31,6 +31,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/java/net/URLClassLoader/B5077773.sh b/jdk/test/java/net/URLClassLoader/B5077773.sh index 6dcba9c39a9..43bff5ad4a1 100644 --- a/jdk/test/java/net/URLClassLoader/B5077773.sh +++ b/jdk/test/java/net/URLClassLoader/B5077773.sh @@ -42,6 +42,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/java/net/URLClassLoader/sealing/checksealed.sh b/jdk/test/java/net/URLClassLoader/sealing/checksealed.sh index e46ac2915ce..191ff6f4750 100644 --- a/jdk/test/java/net/URLClassLoader/sealing/checksealed.sh +++ b/jdk/test/java/net/URLClassLoader/sealing/checksealed.sh @@ -35,6 +35,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" @@ -49,10 +53,10 @@ esac if [ x"$TESTJAVA" = x ]; then TESTJAVA=$1; fi if [ x"$TESTSRC" = x ]; then TESTSRC=.; fi -CLASSPATH=.${PS}${TESTSRC}${FS}a${PS}${TESTSRC}${FS}b.jar +CLASSPATH=".${PS}${TESTSRC}${FS}a${PS}${TESTSRC}${FS}b.jar" -${TESTJAVA}${FS}bin${FS}javac -classpath ${CLASSPATH} -d . ${TESTSRC}${FS}CheckSealed.java -${TESTJAVA}${FS}bin${FS}java -cp ${CLASSPATH} CheckSealed 1 +${TESTJAVA}${FS}bin${FS}javac -classpath "${CLASSPATH}" -d . ${TESTSRC}${FS}CheckSealed.java +${TESTJAVA}${FS}bin${FS}java -cp "${CLASSPATH}" CheckSealed 1 if [ $? != 0 ]; then exit 1; fi -${TESTJAVA}${FS}bin${FS}java -cp ${CLASSPATH} CheckSealed 2 +${TESTJAVA}${FS}bin${FS}java -cp "${CLASSPATH}" CheckSealed 2 if [ $? != 0 ]; then exit 1; fi diff --git a/jdk/test/java/net/URLConnection/6212146/test.sh b/jdk/test/java/net/URLConnection/6212146/test.sh index 29b187ab307..cdf970db41e 100644 --- a/jdk/test/java/net/URLConnection/6212146/test.sh +++ b/jdk/test/java/net/URLConnection/6212146/test.sh @@ -41,6 +41,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh b/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh index 02ab6fcfd50..a1c1d80d696 100644 --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/ClassLoaderDeadlock.sh @@ -54,6 +54,10 @@ case "$OS" in PATHSEP=":" FILESEP="/" ;; + CYGWIN* ) + PATHSEP=";" + FILESEP="/" + ;; Windows* ) PATHSEP=";" FILESEP="\\" @@ -81,7 +85,7 @@ ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ # run the test ${TESTJAVA}${FILESEP}bin${FILESEP}java \ - -classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar \ + -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" \ ClassLoaderDeadlock exit $? diff --git a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh index 4ed9b785e5f..e631389f023 100644 --- a/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh +++ b/jdk/test/java/security/Security/ClassLoaderDeadlock/Deadlock.sh @@ -42,6 +42,10 @@ case "$OS" in PATHSEP=":" FILESEP="/" ;; + CYGWIN* ) + PATHSEP=";" + FILESEP="/" + ;; Windows* ) PATHSEP=";" FILESEP="\\" @@ -54,5 +58,5 @@ esac JAVA="${TESTJAVA}${FILESEP}bin${FILESEP}java" -${JAVA} -cp ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar Deadlock +${JAVA} -cp "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}Deadlock.jar" Deadlock diff --git a/jdk/test/java/security/Security/signedfirst/Dyn.sh b/jdk/test/java/security/Security/signedfirst/Dyn.sh index b64a6b6621b..b897d5900a9 100644 --- a/jdk/test/java/security/Security/signedfirst/Dyn.sh +++ b/jdk/test/java/security/Security/signedfirst/Dyn.sh @@ -54,6 +54,10 @@ case "$OS" in PATHSEP=":" FILESEP="/" ;; + CYGWIN* ) + PATHSEP=";" + FILESEP="/" + ;; Windows* ) PATHSEP=";" FILESEP="\\" @@ -76,7 +80,7 @@ ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ # run the test ${TESTJAVA}${FILESEP}bin${FILESEP}java \ - -classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar \ + -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \ DynSignedProvFirst exit $? diff --git a/jdk/test/java/security/Security/signedfirst/Static.sh b/jdk/test/java/security/Security/signedfirst/Static.sh index cec9df72279..519766f9d60 100644 --- a/jdk/test/java/security/Security/signedfirst/Static.sh +++ b/jdk/test/java/security/Security/signedfirst/Static.sh @@ -54,6 +54,10 @@ case "$OS" in PATHSEP=":" FILESEP="/" ;; + CYGWIN* ) + PATHSEP=";" + FILESEP="/" + ;; Windows* ) PATHSEP=";" FILESEP="\\" @@ -70,14 +74,14 @@ rm StaticSignedProvFirst.class # compile the test program ${TESTJAVA}${FILESEP}bin${FILESEP}javac \ - -classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar \ + -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \ -d ${TESTCLASSES}${FILESEP} \ ${TESTSRC}${FILESEP}StaticSignedProvFirst.java # run the test cd ${TESTSRC}${FILESEP} ${TESTJAVA}${FILESEP}bin${FILESEP}java \ - -classpath ${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar \ + -classpath "${TESTCLASSES}${PATHSEP}${TESTSRC}${FILESEP}exp.jar" \ -Djava.security.properties=file:${TESTSRC}${FILESEP}Static.props \ StaticSignedProvFirst diff --git a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh index b433dedb221..6eef3944d9f 100644 --- a/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh +++ b/jdk/test/javax/crypto/SecretKeyFactory/FailOverTest.sh @@ -56,6 +56,11 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + ;; Windows* ) NULL=NUL PS=";" @@ -69,7 +74,7 @@ esac ${TESTJAVA}${FS}bin${FS}javac \ -d . \ - -classpath ${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar \ + -classpath "${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar" \ ${TESTSRC}${FS}FailOverTest.java if [ $? -ne 0 ]; then @@ -77,7 +82,7 @@ if [ $? -ne 0 ]; then fi ${TESTJAVA}${FS}bin${FS}java \ - -classpath ${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}. \ + -classpath "${TESTSRC}${FS}P1.jar${PS}${TESTSRC}${FS}P2.jar${PS}." \ FailOverTest result=$? diff --git a/jdk/test/javax/security/auth/Subject/doAs/Test.sh b/jdk/test/javax/security/auth/Subject/doAs/Test.sh index 9844c994968..61c4d7cd6cf 100644 --- a/jdk/test/javax/security/auth/Subject/doAs/Test.sh +++ b/jdk/test/javax/security/auth/Subject/doAs/Test.sh @@ -43,6 +43,11 @@ case "$OS" in FS="/" RM="/bin/rm -f" ;; + CYGWIN* ) + PS=";" + FS="/" + RM="rm" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh index 357a586b443..288dedf15fa 100644 --- a/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh +++ b/jdk/test/lib/security/java.policy/Ext_AllPolicy.sh @@ -56,6 +56,12 @@ case "$OS" in FS="/" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + TMP=/tmp + ;; Windows_95 | Windows_98 | Windows_NT ) NULL=NUL PS=";" diff --git a/jdk/test/sun/net/www/MarkResetTest.sh b/jdk/test/sun/net/www/MarkResetTest.sh index 61e73344b0a..bf0b0ceb3c1 100644 --- a/jdk/test/sun/net/www/MarkResetTest.sh +++ b/jdk/test/sun/net/www/MarkResetTest.sh @@ -32,6 +32,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh index 615d1e5a293..06d10520ebb 100644 --- a/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh +++ b/jdk/test/sun/net/www/http/ChunkedInputStream/ChunkedCharEncoding.sh @@ -32,6 +32,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh b/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh index b72b168c208..677a13cc69a 100644 --- a/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh +++ b/jdk/test/sun/net/www/http/HttpClient/RetryPost.sh @@ -32,6 +32,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/sun/net/www/protocol/jar/B5105410.sh b/jdk/test/sun/net/www/protocol/jar/B5105410.sh index 3250ecba807..7b1d33ea4fb 100644 --- a/jdk/test/sun/net/www/protocol/jar/B5105410.sh +++ b/jdk/test/sun/net/www/protocol/jar/B5105410.sh @@ -39,6 +39,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh b/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh index 7db91d98862..351614dde3d 100644 --- a/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh +++ b/jdk/test/sun/net/www/protocol/jar/jarbug/run.sh @@ -28,23 +28,54 @@ # @summary various resource and classloading bugs related to jar files #set -x DEST=`pwd` + +OS=`uname -s` +case "$OS" in + SunOS ) + PS=":" + FS="/" + ;; + Linux ) + PS=":" + FS="/" + ;; + Windows* ) + PS=";" + FS="\\" + ;; + CYGWIN* ) + PS=";" + FS="/" + # + # javac does not like /cygdrive produced by `pwd`. + # + DEST=`cygpath -d ${DEST}` + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; +esac + # # build jar1 # -mkdir ${DEST}/jar1 -cd ${TESTSRC}/etc/jar1 -cp -r . ${DEST}/jar1 -${TESTJAVA}/bin/javac -d ${DEST}/jar1 ${TESTSRC}/src/jar1/LoadResourceBundle.java -${TESTJAVA}/bin/javac -d ${DEST}/jar1 ${TESTSRC}/src/jar1/GetResource.java -cd ${DEST}/jar1 -${TESTJAVA}/bin/jar cfM jar1.jar jar1 res1.txt +mkdir -p ${DEST}${FS}jar1 +cd ${TESTSRC}${FS}etc${FS}jar1 +cp -r . ${DEST}${FS}jar1 +${TESTJAVA}${FS}bin${FS}javac -d ${DEST}${FS}jar1 \ + ${TESTSRC}${FS}src${FS}jar1${FS}LoadResourceBundle.java +${TESTJAVA}${FS}bin${FS}javac -d ${DEST}${FS}jar1 \ + ${TESTSRC}${FS}src${FS}jar1${FS}GetResource.java +cd ${DEST}${FS}jar1 +${TESTJAVA}${FS}bin${FS}jar cfM jar1.jar jar1 res1.txt mv jar1.jar .. # # build the test sources and run them # -${TESTJAVA}/bin/javac -d ${DEST} ${TESTSRC}/src/test/*.java +${TESTJAVA}${FS}bin${FS}javac -d ${DEST} ${TESTSRC}${FS}src${FS}test${FS}*.java cd ${DEST} -${TESTJAVA}/bin/java RunAllTests +${TESTJAVA}${FS}bin${FS}java RunAllTests result=$? if [ "$result" -ne "0" ]; then exit 1 diff --git a/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh b/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh index 4711e7e3cd3..8974fe62d45 100644 --- a/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh +++ b/jdk/test/sun/security/pkcs11/Provider/ConfigQuotedString.sh @@ -68,6 +68,20 @@ case "$OS" in CP="cp" CHMOD="chmod" ;; + CYGWIN* ) + FS="/" + PS=";" + CP="cp" + CHMOD="chmod" + # + # javac does not like /cygdrive produced by `pwd` + # + TESTSRC=`cygpath -d ${TESTSRC}` + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; esac # compile test diff --git a/jdk/test/sun/security/pkcs11/Provider/Login.sh b/jdk/test/sun/security/pkcs11/Provider/Login.sh index a41720b63de..6b285adb82d 100644 --- a/jdk/test/sun/security/pkcs11/Provider/Login.sh +++ b/jdk/test/sun/security/pkcs11/Provider/Login.sh @@ -69,6 +69,20 @@ case "$OS" in CP="cp" CHMOD="chmod" ;; + CYGWIN* ) + FS="/" + PS=";" + CP="cp" + CHMOD="chmod" + # + # javac does not like /cygdrive produced by `pwd` + # + TESTSRC=`cygpath -d ${TESTSRC}` + ;; + * ) + echo "Unrecognized system!" + exit 1; + ;; esac # first make cert/key DBs writable diff --git a/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh b/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh index cb4325b464b..9cb9d04de95 100644 --- a/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh +++ b/jdk/test/sun/security/provider/PolicyFile/getinstance/getinstance.sh @@ -55,6 +55,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh index 9ebf5ee3f64..1f49a952fb3 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh @@ -43,10 +43,17 @@ fi OS=`uname -s` case "$OS" in SunOS | Linux ) + FILESEP="/" PATHSEP=":" ;; + CYGWIN* ) + FILESEP="/" + PATHSEP=";" + ;; + Windows* ) + FILESEP="\\" PATHSEP=";" ;; esac @@ -56,11 +63,13 @@ set -ex # # Compile the tests, package into their respective jars # -${TESTJAVA}/bin/javac -d . \ - ${TESTSRC}/NotifyHandshakeTest.java \ - ${TESTSRC}/NotifyHandshakeTestHeyYou.java -${TESTJAVA}/bin/jar -cvf com.jar com/NotifyHandshakeTest*.class -${TESTJAVA}/bin/jar -cvf edu.jar edu/NotifyHandshakeTestHeyYou.class +${TESTJAVA}${FILESEP}bin${FILESEP}javac -d . \ + ${TESTSRC}${FILESEP}NotifyHandshakeTest.java \ + ${TESTSRC}${FILESEP}NotifyHandshakeTestHeyYou.java +${TESTJAVA}${FILESEP}bin${FILESEP}jar -cvf com.jar \ + com${FILESEP}NotifyHandshakeTest*.class +${TESTJAVA}${FILESEP}bin${FILESEP}jar -cvf edu.jar \ + edu${FILESEP}NotifyHandshakeTestHeyYou.class # # Don't want the original class files to be used, because @@ -73,11 +82,11 @@ rm -rf com edu # This is the only thing we really care about as far as # test status goes. # -${TESTJAVA}/bin/java \ +${TESTJAVA}${FILESEP}bin${FILESEP}java \ -Dtest.src=${TESTSRC} \ -classpath "com.jar${PATHSEP}edu.jar" \ -Djava.security.manager \ - -Djava.security.policy=${TESTSRC}/NotifyHandshakeTest.policy \ + -Djava.security.policy=${TESTSRC}${FILESEP}NotifyHandshakeTest.policy \ com.NotifyHandshakeTest retval=$? diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh index 3e66175cf66..de5f0318e8b 100644 --- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh +++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxy.sh @@ -36,6 +36,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" @@ -46,6 +50,7 @@ case "$OS" in ;; esac -${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxy.java +${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java \ + ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxy.java ${TESTJAVA}${FS}bin${FS}java PostThruProxy ${HOSTNAME} ${TESTSRC} exit diff --git a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh index 2a40eb790ce..e9e20336222 100644 --- a/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh +++ b/jdk/test/sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/PostThruProxyWithAuth.sh @@ -36,6 +36,10 @@ case "$OS" in PS=":" FS="/" ;; + CYGWIN* ) + PS=";" + FS="/" + ;; Windows* ) PS=";" FS="\\" @@ -46,6 +50,8 @@ case "$OS" in ;; esac -${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java ${TESTSRC}${FS}ProxyTunnelServer.java ${TESTSRC}${FS}PostThruProxyWithAuth.java +${TESTJAVA}${FS}bin${FS}javac -d . ${TESTSRC}${FS}OriginServer.java \ + ${TESTSRC}${FS}ProxyTunnelServer.java \ + ${TESTSRC}${FS}PostThruProxyWithAuth.java ${TESTJAVA}${FS}bin${FS}java PostThruProxyWithAuth ${HOSTNAME} ${TESTSRC} exit diff --git a/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh b/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh index 5501116b9c9..3dda55f30c2 100644 --- a/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh +++ b/jdk/test/sun/security/tools/jarsigner/AlgOptions.sh @@ -53,6 +53,13 @@ case "$OS" in CP="${FS}bin${FS}cp -f" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + CP="cp -f" + TMP=/tmp + ;; Windows_* ) NULL=NUL PS=";" diff --git a/jdk/test/sun/security/tools/jarsigner/PercentSign.sh b/jdk/test/sun/security/tools/jarsigner/PercentSign.sh index a07011f0a2a..3a9f315d015 100644 --- a/jdk/test/sun/security/tools/jarsigner/PercentSign.sh +++ b/jdk/test/sun/security/tools/jarsigner/PercentSign.sh @@ -53,6 +53,13 @@ case "$OS" in CP="${FS}bin${FS}cp -f" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + CP="cp -f" + TMP=/tmp + ;; Windows_* ) NULL=NUL PS=";" diff --git a/jdk/test/sun/security/tools/jarsigner/oldsig.sh b/jdk/test/sun/security/tools/jarsigner/oldsig.sh index 14668810446..d7420dc4f3e 100644 --- a/jdk/test/sun/security/tools/jarsigner/oldsig.sh +++ b/jdk/test/sun/security/tools/jarsigner/oldsig.sh @@ -49,6 +49,13 @@ case "$OS" in CP="${FS}bin${FS}cp -f" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + CP="cp -f" + TMP=/tmp + ;; Windows_* ) NULL=NUL PS=";" diff --git a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh index 7deb733c095..8f253a76c9b 100644 --- a/jdk/test/sun/security/tools/keytool/AltProviderPath.sh +++ b/jdk/test/sun/security/tools/keytool/AltProviderPath.sh @@ -52,6 +52,12 @@ case "$OS" in FS="/" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + TMP=/tmp + ;; Windows_* ) NULL=NUL PS=";" @@ -66,14 +72,21 @@ esac # the test code #genkey -${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias dummyTestCA -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 -keypass storepass -keystore keystoreCA.dks -storepass storepass -storetype "dks" -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} +${TESTJAVA}${FS}bin${FS}keytool -genkey -v -alias dummyTestCA \ + -keyalg "RSA" -keysize 1024 -sigalg "ShA1WithRSA" \ + -dname "cn=Dummy Test CA, ou=JSN, o=JavaSoft, c=US" -validity 3650 \ + -keypass storepass -keystore keystoreCA.dks -storepass storepass \ + -storetype "dks" -provider "org.test.dummy.DummyProvider" \ + -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then exit 1 fi #Change keystore password -${TESTJAVA}${FS}bin${FS}keytool -storepasswd -new storepass2 -keystore keystoreCA.dks -storetype "dks" -storepass storepass -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} +${TESTJAVA}${FS}bin${FS}keytool -storepasswd -new storepass2 \ + -keystore keystoreCA.dks -storetype "dks" -storepass storepass \ + -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then exit 1 @@ -81,21 +94,29 @@ fi #Change keystore key password -${TESTJAVA}${FS}bin${FS}keytool -keypasswd -alias "dummyTestCA" -keypass storepass -new keypass -keystore keystoreCA.dks -storetype "dks" -storepass storepass2 -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} +${TESTJAVA}${FS}bin${FS}keytool -keypasswd -alias "dummyTestCA" \ + -keypass storepass -new keypass -keystore keystoreCA.dks \ + -storetype "dks" -storepass storepass2 \ + -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then exit 1 fi #Export certificate -${TESTJAVA}${FS}bin${FS}keytool -v -export -rfc -alias "dummyTestCA" -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dks" -storepass storepass2 -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} +${TESTJAVA}${FS}bin${FS}keytool -v -export -rfc -alias "dummyTestCA" \ + -file "dummyTestCA.der" -keystore keystoreCA.dks -storetype "dks" \ + -storepass storepass2 -provider "org.test.dummy.DummyProvider" \ + -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then exit 1 fi #list keystore -${TESTJAVA}${FS}bin${FS}keytool -v -list -keystore keystoreCA.dks -storetype "dks" -storepass storepass2 -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} +${TESTJAVA}${FS}bin${FS}keytool -v -list -keystore keystoreCA.dks \ + -storetype "dks" -storepass storepass2 \ + -provider "org.test.dummy.DummyProvider" -providerPath ${TESTCLASSES} if [ $? -ne 0 ]; then exit 1 diff --git a/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh b/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh index c5bbca9786c..4934fc7b6ce 100644 --- a/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh +++ b/jdk/test/sun/security/tools/keytool/CloneKeyAskPassword.sh @@ -55,6 +55,10 @@ case "$OS" in PATHSEP=":" FILESEP="/" ;; + CYGWIN* ) + PATHSEP=";" + FILESEP="/" + ;; Windows* ) PATHSEP=";" FILESEP="\\" diff --git a/jdk/test/sun/security/tools/keytool/NoExtNPE.sh b/jdk/test/sun/security/tools/keytool/NoExtNPE.sh index 3e929b5354f..80cc3c85aea 100644 --- a/jdk/test/sun/security/tools/keytool/NoExtNPE.sh +++ b/jdk/test/sun/security/tools/keytool/NoExtNPE.sh @@ -48,6 +48,9 @@ case "$OS" in Linux ) FILESEP="/" ;; + CYGWIN* ) + FILESEP="/" + ;; Windows* ) FILESEP="\\" ;; diff --git a/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh b/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh index 96a1885db9f..787e37e04a5 100644 --- a/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh +++ b/jdk/test/sun/security/tools/keytool/SecretKeyKS.sh @@ -51,6 +51,12 @@ case "$OS" in FS="/" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + TMP=/tmp + ;; Windows_* ) NULL=NUL PS=";" diff --git a/jdk/test/sun/security/tools/keytool/StandardAlgName.sh b/jdk/test/sun/security/tools/keytool/StandardAlgName.sh index 77e9a98ef93..82e9e208e10 100644 --- a/jdk/test/sun/security/tools/keytool/StandardAlgName.sh +++ b/jdk/test/sun/security/tools/keytool/StandardAlgName.sh @@ -52,6 +52,12 @@ case "$OS" in FS="/" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + TMP=/tmp + ;; Windows_* ) NULL=NUL PS=";" diff --git a/jdk/test/sun/security/tools/keytool/i18n.sh b/jdk/test/sun/security/tools/keytool/i18n.sh index 2d37ae97664..33abf76f62e 100644 --- a/jdk/test/sun/security/tools/keytool/i18n.sh +++ b/jdk/test/sun/security/tools/keytool/i18n.sh @@ -52,6 +52,12 @@ case "$OS" in FS="/" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + PS=";" + FS="/" + TMP=/tmp + ;; Windows* ) NULL=NUL PS=";" diff --git a/jdk/test/sun/security/tools/keytool/printssl.sh b/jdk/test/sun/security/tools/keytool/printssl.sh index 9fc19cd9b20..73bd21cb83b 100644 --- a/jdk/test/sun/security/tools/keytool/printssl.sh +++ b/jdk/test/sun/security/tools/keytool/printssl.sh @@ -40,6 +40,9 @@ case "$OS" in SunOS | Linux ) FS="/" ;; + CYGWIN* ) + FS="/" + ;; Windows_* ) FS="\\" ;; diff --git a/jdk/test/sun/security/tools/keytool/resource.sh b/jdk/test/sun/security/tools/keytool/resource.sh index ab8e9520555..1fc515217ae 100644 --- a/jdk/test/sun/security/tools/keytool/resource.sh +++ b/jdk/test/sun/security/tools/keytool/resource.sh @@ -48,6 +48,11 @@ case "$OS" in FS="/" TMP=/tmp ;; + CYGWIN* ) + NULL=/dev/null + FS="/" + TMP=/tmp + ;; Windows_* ) NULL=NUL FS="\\" diff --git a/jdk/test/sun/security/tools/keytool/standard.sh b/jdk/test/sun/security/tools/keytool/standard.sh index f3e052ed510..4328c681454 100644 --- a/jdk/test/sun/security/tools/keytool/standard.sh +++ b/jdk/test/sun/security/tools/keytool/standard.sh @@ -44,11 +44,15 @@ fi # set platform-dependent variables OS=`uname -s` case "$OS" in + SunOS | Linux | CYGWIN* ) + FS="/" + ;; Windows_* ) FS="\\" ;; * ) - FS="/" + echo "Unrecognized system!" + exit 1; ;; esac From d8b50037deb6faedcaa86d9982ee96fa0427675b Mon Sep 17 00:00:00 2001 From: John R Rose Date: Thu, 6 Aug 2009 18:30:33 -0700 Subject: [PATCH 44/70] 6838598: Legal notice repair: jdk/src/share/classes/sun/dyn/FilterGeneric.java Reviewed-by: xdono --- jdk/src/share/classes/sun/dyn/FilterGeneric.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/share/classes/sun/dyn/FilterGeneric.java b/jdk/src/share/classes/sun/dyn/FilterGeneric.java index a99eb26c9ee..a746ad21b95 100644 --- a/jdk/src/share/classes/sun/dyn/FilterGeneric.java +++ b/jdk/src/share/classes/sun/dyn/FilterGeneric.java @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Sf, tifth Floor, Boston, MA 02110-1301 USA. + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or From 75379fe244cd0b17776116f0ef7ea4496508cfa4 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 7 Aug 2009 10:50:26 +0100 Subject: [PATCH 45/70] 6826780: URLClassPath should use HashMap instead of HashMap Replace URL with a String representation. Reviewed-by: michaelm, jccollet --- jdk/make/sun/net/FILES_java.gmk | 1 + .../share/classes/sun/misc/URLClassPath.java | 28 ++++--- .../share/classes/sun/net/util/URLUtil.java | 80 +++++++++++++++++++ 3 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 jdk/src/share/classes/sun/net/util/URLUtil.java diff --git a/jdk/make/sun/net/FILES_java.gmk b/jdk/make/sun/net/FILES_java.gmk index 3d729947667..5082c3d370f 100644 --- a/jdk/make/sun/net/FILES_java.gmk +++ b/jdk/make/sun/net/FILES_java.gmk @@ -41,6 +41,7 @@ FILES_java = \ sun/net/NetProperties.java \ sun/net/NetHooks.java \ sun/net/util/IPAddressUtil.java \ + sun/net/util/URLUtil.java \ sun/net/dns/ResolverConfiguration.java \ sun/net/dns/ResolverConfigurationImpl.java \ sun/net/ftp/FtpClient.java \ diff --git a/jdk/src/share/classes/sun/misc/URLClassPath.java b/jdk/src/share/classes/sun/misc/URLClassPath.java index d9b1035ba6d..5c60e2fe81d 100644 --- a/jdk/src/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/share/classes/sun/misc/URLClassPath.java @@ -51,6 +51,7 @@ import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; import java.security.cert.Certificate; import sun.misc.FileURLMapper; +import sun.net.util.URLUtil; /** * This class is used to maintain a search path of URLs for loading classes @@ -80,7 +81,7 @@ public class URLClassPath { ArrayList loaders = new ArrayList(); /* Map of each URL opened to its corresponding Loader */ - HashMap lmap = new HashMap(); + HashMap lmap = new HashMap(); /* The jar protocol handler to use when creating new URLs */ private URLStreamHandler jarHandler; @@ -317,7 +318,8 @@ public class URLClassPath { // Skip this URL if it already has a Loader. (Loader // may be null in the case where URL has not been opened // but is referenced by a JAR index.) - if (lmap.containsKey(url)) { + String urlNoFragString = URLUtil.urlNoFragString(url); + if (lmap.containsKey(urlNoFragString)) { continue; } // Otherwise, create a new Loader for the URL. @@ -336,7 +338,7 @@ public class URLClassPath { } // Finally, add the Loader to the search path. loaders.add(loader); - lmap.put(url, loader); + lmap.put(urlNoFragString, loader); } return loaders.get(index); } @@ -576,7 +578,7 @@ public class URLClassPath { private JarIndex index; private MetaIndex metaIndex; private URLStreamHandler handler; - private HashMap lmap; + private HashMap lmap; private boolean closed = false; /* @@ -584,7 +586,7 @@ public class URLClassPath { * a JAR file. */ JarLoader(URL url, URLStreamHandler jarHandler, - HashMap loaderMap) + HashMap loaderMap) throws IOException { super(new URL("jar", "", -1, url + "!/", jarHandler)); @@ -663,8 +665,9 @@ public class URLClassPath { try { URL jarURL = new URL(csu, jarfiles[i]); // If a non-null loader already exists, leave it alone. - if (!lmap.containsKey(jarURL)) { - lmap.put(jarURL, null); + String urlNoFragString = URLUtil.urlNoFragString(jarURL); + if (!lmap.containsKey(urlNoFragString)) { + lmap.put(urlNoFragString, null); } } catch (MalformedURLException e) { continue; @@ -806,7 +809,7 @@ public class URLClassPath { if (index == null) return null; - HashSet visited = new HashSet(); + HashSet visited = new HashSet(); return getResource(name, check, visited); } @@ -818,7 +821,7 @@ public class URLClassPath { * non-existent resource */ Resource getResource(final String name, boolean check, - Set visited) { + Set visited) { Resource res; Object[] jarFiles; @@ -843,7 +846,8 @@ public class URLClassPath { try{ url = new URL(csu, jarName); - if ((newLoader = (JarLoader)lmap.get(url)) == null) { + String urlNoFragString = URLUtil.urlNoFragString(url); + if ((newLoader = (JarLoader)lmap.get(urlNoFragString)) == null) { /* no loader has been set up for this jar file * before */ @@ -867,7 +871,7 @@ public class URLClassPath { } /* put it in the global hashtable */ - lmap.put(url, newLoader); + lmap.put(urlNoFragString, newLoader); } } catch (java.security.PrivilegedActionException pae) { continue; @@ -879,7 +883,7 @@ public class URLClassPath { /* Note that the addition of the url to the list of visited * jars incorporates a check for presence in the hashmap */ - boolean visitedURL = !visited.add(url); + boolean visitedURL = !visited.add(URLUtil.urlNoFragString(url)); if (!visitedURL) { try { newLoader.ensureOpen(); diff --git a/jdk/src/share/classes/sun/net/util/URLUtil.java b/jdk/src/share/classes/sun/net/util/URLUtil.java new file mode 100644 index 00000000000..047df3ebe9a --- /dev/null +++ b/jdk/src/share/classes/sun/net/util/URLUtil.java @@ -0,0 +1,80 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.net.util; + +import java.net.URL; + +/** + * URL Utility class. + */ +public class URLUtil { + /** + * Returns a string form of the url suitable for use as a key in HashMap/Sets. + * + * The string form should be behave in the same manner as the URL when + * compared for equality in a HashMap/Set, except that no nameservice + * lookup is done on the hostname (only string comparison), and the fragment + * is not considered. + * + * @see java.net.URLStreamHandler.sameFile(java.net.URL) + */ + public static String urlNoFragString(URL url) { + StringBuilder strForm = new StringBuilder(); + + String protocol = url.getProtocol(); + if (protocol != null) { + /* protocol is compared case-insensitive, so convert to lowercase */ + protocol = protocol.toLowerCase(); + strForm.append(protocol); + strForm.append("://"); + } + + String host = url.getHost(); + if (host != null) { + /* host is compared case-insensitive, so convert to lowercase */ + host = host.toLowerCase(); + strForm.append(host); + + int port = url.getPort(); + if (port == -1) { + /* if no port is specificed then use the protocols + * default, if there is one */ + port = url.getDefaultPort(); + } + if (port != -1) { + strForm.append(":").append(port); + } + } + + String file = url.getFile(); + if (file != null) { + strForm.append(file); + } + + return strForm.toString(); + } +} + From aca1227406040fd2663b684acc00692d62b342e9 Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Fri, 7 Aug 2009 10:51:25 +0100 Subject: [PATCH 46/70] 6826801: JarFileFactory should not use HashMap Replace URL with a String representation. Reviewed-by: michaelm, jccollet --- .../net/www/protocol/jar/JarFileFactory.java | 26 ++++++++++--------- .../net/www/protocol/jar/JarFileFactory.java | 26 ++++++++++--------- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java index c51f15eaec9..0d1b3099836 100644 --- a/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/solaris/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -25,12 +25,14 @@ package sun.net.www.protocol.jar; -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.jar.*; -import java.util.zip.ZipFile; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.jar.JarFile; import java.security.Permission; +import sun.net.util.URLUtil; /* A factory for cached JAR file. This class is used to both retrieve * and cache Jar files. @@ -41,13 +43,13 @@ import java.security.Permission; class JarFileFactory implements URLJarFile.URLJarFileCloseController { /* the url to file cache */ - private static HashMap fileCache = new HashMap(); + private static HashMap fileCache = new HashMap(); /* the file to url cache */ - private static HashMap urlCache = new HashMap(); + private static HashMap urlCache = new HashMap(); URLConnection getConnection(JarFile jarFile) throws IOException { - URL u = (URL)urlCache.get(jarFile); + URL u = urlCache.get(jarFile); if (u != null) return u.openConnection(); @@ -72,7 +74,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (this) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(url, local_result); + fileCache.put(URLUtil.urlNoFragString(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -97,15 +99,15 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { * remove the JarFile from the cache */ public void close(JarFile jarFile) { - URL urlRemoved = (URL) urlCache.remove(jarFile); + URL urlRemoved = urlCache.remove(jarFile); if( urlRemoved != null) { - fileCache.remove(urlRemoved); + fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { - JarFile result = (JarFile)fileCache.get(url); + JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { diff --git a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java index 3192c52d030..9df86326e40 100644 --- a/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -25,12 +25,14 @@ package sun.net.www.protocol.jar; -import java.io.*; -import java.net.*; -import java.util.*; -import java.util.jar.*; -import java.util.zip.ZipFile; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.jar.JarFile; import java.security.Permission; +import sun.net.util.URLUtil; /* A factory for cached JAR file. This class is used to both retrieve * and cache Jar files. @@ -41,13 +43,13 @@ import java.security.Permission; class JarFileFactory implements URLJarFile.URLJarFileCloseController { /* the url to file cache */ - private static HashMap fileCache = new HashMap(); + private static HashMap fileCache = new HashMap(); /* the file to url cache */ - private static HashMap urlCache = new HashMap(); + private static HashMap urlCache = new HashMap(); URLConnection getConnection(JarFile jarFile) throws IOException { - URL u = (URL)urlCache.get(jarFile); + URL u = urlCache.get(jarFile); if (u != null) return u.openConnection(); @@ -82,7 +84,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (this) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(url, local_result); + fileCache.put(URLUtil.urlNoFragString(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -107,14 +109,14 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { * remove the JarFile from the cache */ public void close(JarFile jarFile) { - URL urlRemoved = (URL) urlCache.remove(jarFile); + URL urlRemoved = urlCache.remove(jarFile); if( urlRemoved != null) { - fileCache.remove(urlRemoved); + fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { - JarFile result = (JarFile)fileCache.get(url); + JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { From 24fdb8e4be217007eb3a6e772a77af0db10d529d Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 7 Aug 2009 19:06:56 +0400 Subject: [PATCH 47/70] 6868189: Nested enum class with custom BeanInfo fails Reviewed-by: peterz --- .../com/sun/beans/finder/BeanInfoFinder.java | 2 +- .../java/beans/Introspector/Test6868189.java | 66 +++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/beans/Introspector/Test6868189.java diff --git a/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java b/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java index 3e1c37c2d57..faab85cafa9 100644 --- a/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java +++ b/jdk/src/share/classes/com/sun/beans/finder/BeanInfoFinder.java @@ -48,7 +48,7 @@ public final class BeanInfoFinder } private static boolean isValid(Class type, Method method) { - return (method != null) && type.equals(method.getDeclaringClass()); + return (method != null) && method.getDeclaringClass().isAssignableFrom(type); } @Override diff --git a/jdk/test/java/beans/Introspector/Test6868189.java b/jdk/test/java/beans/Introspector/Test6868189.java new file mode 100644 index 00000000000..3aa10aa6d86 --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test6868189.java @@ -0,0 +1,66 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6868189 + * @summary Tests custom BeanInfo in the same package + * @author Sergey Malenkov + */ + +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.beans.SimpleBeanInfo; + +public class Test6868189 { + + private static final String PROPERTY = "$?"; // NON-NLS: the property name + private static final String GETTER = "name"; // NON-NLS: the method name + private static final String SETTER = null; + + public static void main(String[] args) throws IntrospectionException { + PropertyDescriptor[] pds = Introspector.getBeanInfo(Enumeration.class).getPropertyDescriptors(); + if ((pds.length != 1)|| !PROPERTY.equals(pds[0].getName())){ + throw new Error("unexpected property"); + } + } + + public enum Enumeration { + FIRST, SECOND + } + + public static class EnumerationBeanInfo extends SimpleBeanInfo { + @Override + public PropertyDescriptor[] getPropertyDescriptors() { + try { + return new PropertyDescriptor[] { + new PropertyDescriptor(PROPERTY, Enumeration.class, GETTER, SETTER) + }; + } + catch (IntrospectionException exception) { + throw new Error("unexpected exception", exception); + } + } + } +} From 9a5d0532c5334b2448bff1946250972594c82a9d Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Fri, 7 Aug 2009 18:15:03 +0100 Subject: [PATCH 48/70] 6869697: Missing entry in makefiles for java/lang/ReflectiveOperationException.java Add new dependency explicitly so all compilers pick it up Reviewed-by: darcy, ohair --- jdk/make/java/java/FILES_java.gmk | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/make/java/java/FILES_java.gmk b/jdk/make/java/java/FILES_java.gmk index f9dd26383ce..e8a2223f67a 100644 --- a/jdk/make/java/java/FILES_java.gmk +++ b/jdk/make/java/java/FILES_java.gmk @@ -77,6 +77,7 @@ JAVA_JAVA_java = \ java/lang/Compiler.java \ java/lang/Throwable.java \ java/lang/Exception.java \ + java/lang/ReflectiveOperationException.java \ java/lang/IllegalAccessException.java \ java/lang/InstantiationException.java \ java/lang/ClassNotFoundException.java \ From 452d4d3f20cfd85048a39c252bf5de62eba2022b Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Fri, 7 Aug 2009 11:31:24 -0700 Subject: [PATCH 49/70] 6803688: Integrate latest JAX-WS (2.1.6) in to JDK 6u14 Reviewed-by: darcy, ramap --- THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/THIRD_PARTY_README b/THIRD_PARTY_README index 9f4d7e5087a..4d3163cbce7 100644 --- a/THIRD_PARTY_README +++ b/THIRD_PARTY_README @@ -32,7 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. --- end of LICENSE file --- %% This notice is provided with respect to ASM, which may be included with this software: -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2007 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without From f8a396b166267c9bb94c27c298ace1f607fd7fae Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Fri, 7 Aug 2009 11:31:35 -0700 Subject: [PATCH 50/70] 6803688: Integrate latest JAX-WS (2.1.6) in to JDK 6u14 Reviewed-by: darcy, ramap --- corba/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/corba/THIRD_PARTY_README b/corba/THIRD_PARTY_README index 9f4d7e5087a..4d3163cbce7 100644 --- a/corba/THIRD_PARTY_README +++ b/corba/THIRD_PARTY_README @@ -32,7 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. --- end of LICENSE file --- %% This notice is provided with respect to ASM, which may be included with this software: -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2007 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without From cbc42a9c38d2e348be383930262ea26a2c153d19 Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Fri, 7 Aug 2009 11:31:42 -0700 Subject: [PATCH 51/70] 6803688: Integrate latest JAX-WS (2.1.6) in to JDK 6u14 Reviewed-by: darcy, ramap --- hotspot/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hotspot/THIRD_PARTY_README b/hotspot/THIRD_PARTY_README index 9f4d7e5087a..4d3163cbce7 100644 --- a/hotspot/THIRD_PARTY_README +++ b/hotspot/THIRD_PARTY_README @@ -32,7 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. --- end of LICENSE file --- %% This notice is provided with respect to ASM, which may be included with this software: -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2007 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without From 354661db004ec563e26f188258b6286085ad8e3e Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Fri, 7 Aug 2009 11:31:46 -0700 Subject: [PATCH 52/70] 6803688: Integrate latest JAX-WS (2.1.6) in to JDK 6u14 Reviewed-by: darcy, ramap --- jaxp/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jaxp/THIRD_PARTY_README b/jaxp/THIRD_PARTY_README index 690890548f2..43058486295 100644 --- a/jaxp/THIRD_PARTY_README +++ b/jaxp/THIRD_PARTY_README @@ -32,7 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. --- end of LICENSE file --- %% This notice is provided with respect to ASM, which may be included with this software: -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2007 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without From 02d508cbf217eb2029384a21757d030cf7ebe8f1 Mon Sep 17 00:00:00 2001 From: Abhijit Saha Date: Fri, 7 Aug 2009 11:32:04 -0700 Subject: [PATCH 53/70] 6803688: Integrate latest JAX-WS (2.1.6) in to JDK 6u14 Reviewed-by: darcy, ramap --- jdk/THIRD_PARTY_README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/THIRD_PARTY_README b/jdk/THIRD_PARTY_README index 690890548f2..43058486295 100644 --- a/jdk/THIRD_PARTY_README +++ b/jdk/THIRD_PARTY_README @@ -32,7 +32,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. --- end of LICENSE file --- %% This notice is provided with respect to ASM, which may be included with this software: -Copyright (c) 2000-2005 INRIA, France Telecom +Copyright (c) 2000-2007 INRIA, France Telecom All rights reserved. Redistribution and use in source and binary forms, with or without From aedd67d988c58dad47c5704c0e6310404a50cd14 Mon Sep 17 00:00:00 2001 From: Pavel Porvatov Date: Mon, 10 Aug 2009 14:55:10 +0400 Subject: [PATCH 54/70] 6461173: One JCK test([NewFolderAction0001]) failed on Windows due to lack of PropertyPermission(s) Reviewed-by: peterz, malenkov --- .../swing/filechooser/FileSystemView.java | 11 +++++- .../sun/awt/shell/Win32ShellFolder2.java | 13 +------ .../awt/shell/Win32ShellFolderManager2.java | 37 +++++++++++++------ 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java b/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java index c2ff7bb8df8..9f969796bdd 100644 --- a/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/jdk/src/share/classes/javax/swing/filechooser/FileSystemView.java @@ -37,6 +37,8 @@ import java.util.Vector; import java.lang.ref.WeakReference; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; +import java.security.AccessController; +import java.security.PrivilegedAction; import sun.awt.shell.*; @@ -718,8 +720,13 @@ class WindowsFileSystemView extends FileSystemView { return isFileSystemRoot(dir); } - public boolean isFloppyDrive(File dir) { - String path = dir.getAbsolutePath(); + public boolean isFloppyDrive(final File dir) { + String path = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return dir.getAbsolutePath(); + } + }); + return (path != null && (path.equals("A:\\") || path.equals("B:\\"))); } diff --git a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java index 1b81007fe8e..c1efb0de52c 100644 --- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java @@ -73,12 +73,7 @@ final class Win32ShellFolder2 extends ShellFolder { private static native void initIDs(); - private static final boolean is98; - static { - String osName = System.getProperty("os.name"); - is98 = (osName != null && osName.startsWith("Windows 98")); - initIDs(); } @@ -305,7 +300,6 @@ final class Win32ShellFolder2 extends ShellFolder { }, RuntimeException.class) ); this.disposer.relativePIDL = relativePIDL; - getAbsolutePath(); sun.java2d.Disposer.addRecord(this, disposer); } @@ -616,11 +610,8 @@ final class Win32ShellFolder2 extends ShellFolder { public boolean isDirectory() { if (isDir == null) { // Folders with SFGAO_BROWSABLE have "shell extension" handlers and are - // not traversable in JFileChooser. An exception is "My Documents" on - // Windows 98. - if (hasAttribute(ATTRIB_FOLDER) - && (!hasAttribute(ATTRIB_BROWSABLE) || - (is98 && equals(Win32ShellFolderManager2.getPersonal())))) { + // not traversable in JFileChooser. + if (hasAttribute(ATTRIB_FOLDER) && !hasAttribute(ATTRIB_BROWSABLE)) { isDir = Boolean.TRUE; } else if (isLink()) { ShellFolder linkLocation = getLinkLocation(false); diff --git a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java index 4471a3ec0da..8b692fa685a 100644 --- a/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java +++ b/jdk/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java @@ -105,9 +105,11 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { private static Win32ShellFolder2 network; private static Win32ShellFolder2 personal; - private static String osVersion = System.getProperty("os.version"); - private static final boolean useShell32Icons = - (osVersion != null && osVersion.compareTo("5.1") >= 0); + private static final boolean USE_SHELL32_ICONS = AccessController.doPrivileged(new PrivilegedAction() { + public Boolean run() { + return OSInfo.getWindowsVersion().compareTo(OSInfo.WINDOWS_XP) >= 0; + } + }); static Win32ShellFolder2 getDesktop() { if (desktop == null) { @@ -307,15 +309,15 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { i = Integer.parseInt(name); } catch (NumberFormatException ex) { if (name.equals("ListView")) { - i = (useShell32Icons) ? 21 : 2; + i = (USE_SHELL32_ICONS) ? 21 : 2; } else if (name.equals("DetailsView")) { - i = (useShell32Icons) ? 23 : 3; + i = (USE_SHELL32_ICONS) ? 23 : 3; } else if (name.equals("UpFolder")) { - i = (useShell32Icons) ? 28 : 8; + i = (USE_SHELL32_ICONS) ? 28 : 8; } else if (name.equals("NewFolder")) { - i = (useShell32Icons) ? 31 : 11; + i = (USE_SHELL32_ICONS) ? 31 : 11; } else if (name.equals("ViewMenu")) { - i = (useShell32Icons) ? 21 : 2; + i = (USE_SHELL32_ICONS) ? 21 : 2; } } if (i >= 0) { @@ -352,11 +354,16 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { * Does dir represent a "computer" such as a node on the network, or * "My Computer" on the desktop. */ - public boolean isComputerNode(File dir) { + public boolean isComputerNode(final File dir) { if (dir != null && dir == getDrives()) { return true; } else { - String path = dir.getAbsolutePath(); + String path = AccessController.doPrivileged(new PrivilegedAction() { + public String run() { + return dir.getAbsolutePath(); + } + }); + return (path.startsWith("\\\\") && path.indexOf("\\", 2) < 0); //Network path } } @@ -501,7 +508,7 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { // thread, we don't need to delegate the task return task.call(); } else { - Future future; + final Future future; try { future = submit(task); @@ -512,7 +519,13 @@ public class Win32ShellFolderManager2 extends ShellFolderManager { try { return future.get(); } catch (InterruptedException e) { - future.cancel(true); + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + future.cancel(true); + + return null; + } + }); throw e; } catch (ExecutionException e) { From 3f2aa03af786a8b0977dea815d15550adb5f81a0 Mon Sep 17 00:00:00 2001 From: Alexander Potochkin Date: Mon, 10 Aug 2009 16:29:30 +0400 Subject: [PATCH 55/70] 6822696: Integrating JXLayer component to Swing library Reviewed-by: peterz, art --- jdk/src/share/classes/javax/swing/JLayer.java | 788 ++++++++++++++++++ .../classes/javax/swing/plaf/LayerUI.java | 370 ++++++++ .../SerializationTest/SerializationTest.java | 53 ++ 3 files changed, 1211 insertions(+) create mode 100644 jdk/src/share/classes/javax/swing/JLayer.java create mode 100644 jdk/src/share/classes/javax/swing/plaf/LayerUI.java create mode 100644 jdk/test/javax/swing/JLayer/SerializationTest/SerializationTest.java diff --git a/jdk/src/share/classes/javax/swing/JLayer.java b/jdk/src/share/classes/javax/swing/JLayer.java new file mode 100644 index 00000000000..b8cc69e9bcd --- /dev/null +++ b/jdk/src/share/classes/javax/swing/JLayer.java @@ -0,0 +1,788 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package javax.swing; + +import javax.swing.plaf.LayerUI; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.Serializable; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Iterator; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * {@code JLayer} is a universal decorator for Swing components + * which enables you to implement various advanced painting effects as well as + * receive notifications of all {@code AWTEvent}s generated within its borders. + *

    + * {@code JLayer} delegates the handling of painting and input events to a + * {@link javax.swing.plaf.LayerUI} object, which performs the actual decoration. + *

    + * The custom painting implemented in the {@code LayerUI} and events notification + * work for the JLayer itself and all its subcomponents. + * This combination enables you to enrich existing components + * by adding new advanced functionality such as temporary locking of a hierarchy, + * data tips for compound components, enhanced mouse scrolling etc and so on. + *

    + * {@code JLayer} is a good solution if you only need to do custom painting + * over compound component or catch input events from its subcomponents. + *

    + *         // create a component to be decorated with the layer
    + *        JPanel panel = new JPanel();
    + *        panel.add(new JButton("JButton"));
    + *        // This custom layerUI will fill the layer with translucent green
    + *        // and print out all mouseMotion events generated within its borders
    + *        LayerUI<JPanel> layerUI = new LayerUI<JPanel>() {
    + *            public void paint(Graphics g, JCompo  nent c) {
    + *                // paint the layer as is
    + *                super.paint(g, c);
    + *                // fill it with the translucent green
    + *                g.setColor(new Color(0, 128, 0, 128));
    + *                g.fillRect(0, 0, c.getWidth(), c.getHeight());
    + *            }
    + *            // overridden method which catches MouseMotion events
    + *            public void eventDispatched(AWTEvent e, JLayer<JPanel> l) {
    + *                System.out.println("AWTEvent detected: " + e);
    + *            }
    + *        };
    + *        // create the layer for the panel using our custom layerUI
    + *        JLayer<JPanel> layer = new JLayer<JPanel>(panel, layerUI);
    + *        // work with the layer as with any other Swing component
    + *        frame.add(layer);
    + * 
    + * + * Note: {@code JLayer} doesn't support the following methods: + *
      + *
    • {@link Container#add(java.awt.Component)}
    • + *
    • {@link Container#add(String, java.awt.Component)}
    • + *
    • {@link Container#add(java.awt.Component, int)}
    • + *
    • {@link Container#add(java.awt.Component, Object)}
    • + *
    • {@link Container#add(java.awt.Component, Object, int)}
    • + *
    + * using any of of them will cause {@code UnsupportedOperationException} to be thrown, + * to add a component to {@code JLayer} + * use {@link #setView(Component)} or {@link #setGlassPane(JPanel)}. + * + * @param the type of {@code JLayer}'s view component + * + * @see #JLayer(Component) + * @see #setView(Component) + * @see #getView() + * @see javax.swing.plaf.LayerUI + * @see #JLayer(Component, LayerUI) + * @see #setUI(javax.swing.plaf.LayerUI) + * @see #getUI() + * @since 1.7 + * + * @author Alexander Potochkin + */ +public final class JLayer + extends JComponent + implements Scrollable, PropertyChangeListener { + private V view; + // this field is necessary because JComponent.ui is transient + // when layerUI is serializable + private LayerUI layerUI; + private JPanel glassPane; + private boolean isPainting; + private static final DefaultLayerLayout sharedLayoutInstance = + new DefaultLayerLayout(); + private long eventMask; + + private static final LayerEventController eventController = + new LayerEventController(); + + private static final long ACCEPTED_EVENTS = + AWTEvent.COMPONENT_EVENT_MASK | + AWTEvent.CONTAINER_EVENT_MASK | + AWTEvent.FOCUS_EVENT_MASK | + AWTEvent.KEY_EVENT_MASK | + AWTEvent.MOUSE_WHEEL_EVENT_MASK | + AWTEvent.MOUSE_MOTION_EVENT_MASK | + AWTEvent.MOUSE_EVENT_MASK | + AWTEvent.INPUT_METHOD_EVENT_MASK | + AWTEvent.HIERARCHY_EVENT_MASK | + AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK; + + /** + * Creates a new {@code JLayer} object with a {@code null} view component + * and {@code null} {@link javax.swing.plaf.LayerUI}. + * + * @see #setView + * @see #setUI + */ + public JLayer() { + this(null); + } + + /** + * Creates a new {@code JLayer} object + * with {@code null} {@link javax.swing.plaf.LayerUI}. + * + * @param view the component to be decorated by this {@code JLayer} + * + * @see #setUI + */ + public JLayer(V view) { + this(view, null); + } + + /** + * Creates a new {@code JLayer} object with the specified view component + * and {@link javax.swing.plaf.LayerUI} object. + * + * @param view the component to be decorated + * @param ui the {@link javax.swing.plaf.LayerUI} delegate + * to be used by this {@code JLayer} + */ + public JLayer(V view, LayerUI ui) { + setLayout(sharedLayoutInstance); + setGlassPane(createGlassPane()); + setView(view); + setUI(ui); + } + + /** + * Returns the {@code JLayer}'s view component or {@code null}. + *
    This is a bound property. + * + * @return the {@code JLayer}'s view component + * or {@code null} if none exists + * + * @see #setView(V) + */ + public V getView() { + return view; + } + + /** + * Sets the {@code JLayer}'s view component, which can be {@code null}. + *
    This is a bound property. + * + * @param view the view component for this {@code JLayer} + * + * @see #getView() + */ + public void setView(V view) { + Component oldView = getView(); + if (oldView != null) { + super.remove(oldView); + } + if (view != null) { + super.addImpl(view, null, getComponentCount()); + } + this.view = view; + firePropertyChange("view", oldView, view); + revalidate(); + repaint(); + } + + /** + * Sets the {@link javax.swing.plaf.LayerUI} which will perform painting + * and receive input events for this {@code JLayer}. + * + * @param ui the {@link javax.swing.plaf.LayerUI} for this {@code JLayer} + */ + public void setUI(LayerUI ui) { + this.layerUI = ui; + super.setUI(ui); + } + + /** + * Returns the {@link javax.swing.plaf.LayerUI} for this {@code JLayer}. + * + * @return the {@code LayerUI} for this {@code JLayer} + */ + public LayerUI getUI() { + return layerUI; + } + + /** + * Returns the {@code JLayer}'s glassPane component or {@code null}. + *
    This is a bound property. + * + * @return the {@code JLayer}'s glassPane component + * or {@code null} if none exists + * + * @see #setGlassPane(JPanel) + */ + public JPanel getGlassPane() { + return glassPane; + } + + /** + * Sets the {@code JLayer}'s glassPane component, which can be {@code null}. + *
    This is a bound property. + * + * @param glassPane the glassPane component of this {@code JLayer} + * + * @see #getGlassPane() + */ + public void setGlassPane(JPanel glassPane) { + Component oldGlassPane = getGlassPane(); + if (oldGlassPane != null) { + super.remove(oldGlassPane); + } + if (glassPane != null) { + super.addImpl(glassPane, null, 0); + } + this.glassPane = glassPane; + firePropertyChange("glassPane", oldGlassPane, glassPane); + revalidate(); + repaint(); + } + + /** + * Called by the constructor methods to create a default {@code glassPane}. + * By default this method creates a new JPanel with visibility set to true + * and opacity set to false. + * + * @return the default {@code glassPane} + */ + public JPanel createGlassPane() { + return new DefaultLayerGlassPane(); + } + + /** + * This method is not supported by {@code JLayer} + * and always throws {@code UnsupportedOperationException} + * + * @throws UnsupportedOperationException this method is not supported + * + * @see #setView(Component) + * @see #setGlassPane(Component) + */ + protected void addImpl(Component comp, Object constraints, int index) { + throw new UnsupportedOperationException( + "Adding components to JLayer is not supported, " + + "use setView() or setGlassPane() instead"); + } + + /** + * {@inheritDoc} + */ + public void remove(Component comp) { + if (comp == getView()) { + setView(null); + } else if (comp == getGlassPane()) { + setGlassPane(null); + } else { + super.remove(comp); + } + } + + /** + * {@inheritDoc} + */ + public void removeAll() { + setView(null); + setGlassPane(null); + } + + /** + * Delegates all painting to the {@link javax.swing.plaf.LayerUI} object. + * + * @param g the {@code Graphics} to render to + */ + public void paint(Graphics g) { + if (!isPainting) { + isPainting = true; + super.paintComponent(g); + isPainting = false; + } else { + super.paint(g); + } + } + + /** + * This method is empty, because all painting is done by + * {@link #paint(Graphics)} and + * {@link javax.swing.plaf.LayerUI#update(Graphics, JComponent)} methods + */ + protected void paintComponent(Graphics g) { + } + + /** + * To enable the correct painting of the {@code glassPane} and view component, + * the {@code JLayer} overrides the default implementation of + * this method to return {@code false} when the {@code glassPane} is visible. + * + * @return false if {@code JLayer}'s {@code glassPane} is visible + */ + public boolean isOptimizedDrawingEnabled() { + return !glassPane.isVisible(); + } + + /** + * {@inheritDoc} + */ + public void propertyChange(PropertyChangeEvent evt) { + if (getUI() != null) { + getUI().applyPropertyChange(evt, this); + } + } + + /** + * Sets the bitmask of event types to receive by this {@code JLayer}. + * Here is the list of the supported event types: + *
      + *
    • AWTEvent.COMPONENT_EVENT_MASK
    • + *
    • AWTEvent.CONTAINER_EVENT_MASK
    • + *
    • AWTEvent.FOCUS_EVENT_MASK
    • + *
    • AWTEvent.KEY_EVENT_MASK
    • + *
    • AWTEvent.MOUSE_WHEEL_EVENT_MASK
    • + *
    • AWTEvent.MOUSE_MOTION_EVENT_MASK
    • + *
    • AWTEvent.MOUSE_EVENT_MASK
    • + *
    • AWTEvent.INPUT_METHOD_EVENT_MASK
    • + *
    • AWTEvent.HIERARCHY_EVENT_MASK
    • + *
    • AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK
    • + *
    + *

    + * If {@code LayerUI} is installed, + * {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method + * will only receive events that match the event mask. + *

    + * The following example shows how to correclty use this method + * in the {@code LayerUI} implementations: + *

    +     *    public void installUI(JComponent c) {
    +     *       super.installUI(c);
    +     *       JLayer l = (JLayer) c;
    +     *       // this LayerUI will receive only key and focus events
    +     *       l.setLayerEventMask(AWTEvent.KEY_EVENT_MASK | AWTEvent.FOCUS_EVENT_MASK);
    +     *    }
    +     *
    +     *    public void uninstallUI(JComponent c) {
    +     *       super.uninstallUI(c);
    +     *       JLayer l = (JLayer) c;
    +     *       // JLayer must be returned to its initial state
    +     *       l.setLayerEventMask(0);
    +     *    }
    +     * 
    + * + * By default {@code JLayer} receives no events. + * + * @param layerEventMask the bitmask of event types to receive + * + * @throws IllegalArgumentException if the {@code layerEventMask} parameter + * contains unsupported event types + * @see #getLayerEventMask() + */ + public void setLayerEventMask(long layerEventMask) { + if (layerEventMask != (layerEventMask & ACCEPTED_EVENTS)) { + throw new IllegalArgumentException( + "The event bitmask contains unsupported event types"); + } + long oldEventMask = getLayerEventMask(); + this.eventMask = layerEventMask; + firePropertyChange("layerEventMask", oldEventMask, layerEventMask); + if (layerEventMask != oldEventMask) { + disableEvents(oldEventMask); + enableEvents(eventMask); + eventController.updateAWTEventListener(this); + } + } + + /** + * Returns the bitmap of event mask to receive by this {@code JLayer} + * and its {@code LayerUI}. + *

    + * It means that {@link javax.swing.plaf.LayerUI#eventDispatched(AWTEvent, JLayer)} method + * will only receive events that match the event mask. + *

    + * By default {@code JLayer} receives no events. + * + * @return the bitmask of event types to receive for this {@code JLayer} + */ + public long getLayerEventMask() { + return eventMask; + } + + /** + * Delegates its functionality to the {@link javax.swing.plaf.LayerUI#updateUI(JLayer)} method, + * if {@code LayerUI} is set. + */ + public void updateUI() { + if (getUI() != null) { + getUI().updateUI(this); + } + } + + /** + * Returns the preferred size of the viewport for a view component. + *

    + * If the ui delegate of this layer is not {@code null}, this method delegates its + * implementation to the {@code LayerUI.getPreferredScrollableViewportSize(JLayer)} + * + * @return the preferred size of the viewport for a view component + * + * @see Scrollable + * @see LayerUI#getPreferredScrollableViewportSize(JLayer) + */ + public Dimension getPreferredScrollableViewportSize() { + if (getUI() != null) { + return getUI().getPreferredScrollableViewportSize(this); + } + return getPreferredSize(); + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one block of rows or columns, depending on the value of orientation. + *

    + * If the ui delegate of this layer is not {@code null}, this method delegates its + * implementation to the {@code LayerUI.getScrollableBlockIncrement(JLayer,Rectangle,int,int)} + * + * @return the "block" increment for scrolling in the specified direction + * + * @see Scrollable + * @see LayerUI#getScrollableBlockIncrement(JLayer, Rectangle, int, int) + */ + public int getScrollableBlockIncrement(Rectangle visibleRect, + int orientation, int direction) { + if (getUI() != null) { + return getUI().getScrollableBlockIncrement(this, visibleRect, + orientation, direction); + } + return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : + visibleRect.width; + } + + /** + * Returns {@code false} to indicate that the height of the viewport does not + * determine the height of the layer, unless the preferred height + * of the layer is smaller than the height of the viewport. + *

    + * If the ui delegate of this layer is not null, this method delegates its + * implementation to the {@code LayerUI.getScrollableTracksViewportHeight(JLayer)} + * + * @return whether the layer should track the height of the viewport + * + * @see Scrollable + * @see LayerUI#getScrollableTracksViewportHeight(JLayer) + */ + public boolean getScrollableTracksViewportHeight() { + if (getUI() != null) { + return getUI().getScrollableTracksViewportHeight(this); + } + if (getParent() instanceof JViewport) { + return ((getParent()).getHeight() > getPreferredSize().height); + } + return false; + } + + /** + * Returns {@code false} to indicate that the width of the viewport does not + * determine the width of the layer, unless the preferred width + * of the layer is smaller than the width of the viewport. + *

    + * If the ui delegate of this layer is not null, this method delegates its + * implementation to the {@code LayerUI.getScrollableTracksViewportWidth(JLayer)} + * + * @return whether the layer should track the width of the viewport + * + * @see Scrollable + * @see LayerUI#getScrollableTracksViewportWidth(JLayer) + */ + public boolean getScrollableTracksViewportWidth() { + if (getUI() != null) { + return getUI().getScrollableTracksViewportWidth(this); + } + if (getParent() instanceof JViewport) { + return ((getParent()).getWidth() > getPreferredSize().width); + } + return false; + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one new row or column, depending on the value of orientation. + * Ideally, components should handle a partially exposed row or column + * by returning the distance required to completely expose the item. + *

    + * Scrolling containers, like {@code JScrollPane}, will use this method + * each time the user requests a unit scroll. + *

    + * If the ui delegate of this layer is not {@code null}, this method delegates its + * implementation to the {@code LayerUI.getScrollableUnitIncrement(JLayer,Rectangle,int,int)} + * + * @return The "unit" increment for scrolling in the specified direction. + * This value should always be positive. + * + * @see Scrollable + * @see LayerUI#getScrollableUnitIncrement(JLayer, Rectangle, int, int) + */ + public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, + int direction) { + if (getUI() != null) { + return getUI().getScrollableUnitIncrement( + this, visibleRect, orientation, direction); + } + return 1; + } + + private void readObject(ObjectInputStream s) + throws IOException, ClassNotFoundException { + s.defaultReadObject(); + if (getUI() != null) { + setUI(getUI()); + } + if (getLayerEventMask() != 0) { + eventController.updateAWTEventListener(this); + } + } + + /** + * static AWTEventListener to be shared with all AbstractLayerUIs + */ + private static class LayerEventController implements AWTEventListener { + private ArrayList> layerList = + new ArrayList>(); + + private long currentEventMask; + + @SuppressWarnings("unchecked") + public void eventDispatched(AWTEvent event) { + Object source = event.getSource(); + if (source instanceof Component) { + Component component = (Component) source; + while (component != null) { + if (component instanceof JLayer) { + JLayer l = (JLayer) component; + LayerUI ui = l.getUI(); + if (ui != null && + isEventEnabled(l.getLayerEventMask(), + event.getID())) { + ui.eventDispatched(event, l); + } + } + component = component.getParent(); + } + } + } + + private boolean layerListContains(JLayer l) { + for (WeakReference layerWeakReference : layerList) { + if (layerWeakReference.get() == l) { + return true; + } + } + return false; + } + + private void updateAWTEventListener(JLayer layer) { + if (!layerListContains(layer) && layer.getLayerEventMask() != 0) { + layerList.add(new WeakReference(layer)); + } + long combinedMask = 0; + Iterator> it = layerList.iterator(); + while (it.hasNext()) { + WeakReference weakRef = it.next(); + JLayer currLayer = weakRef.get(); + if (currLayer == null) { + it.remove(); + } else { + combinedMask |= currLayer.getLayerEventMask(); + } + } + if (combinedMask == 0) { + removeAWTEventListener(); + layerList.clear(); + } else if (getCurrentEventMask() != combinedMask) { + removeAWTEventListener(); + addAWTEventListener(combinedMask); + } + } + + private long getCurrentEventMask() { + return currentEventMask; + } + + private void addAWTEventListener(final long eventMask) { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + Toolkit.getDefaultToolkit(). + addAWTEventListener(LayerEventController.this, eventMask); + return null; + } + }); + currentEventMask = eventMask; + } + + private void removeAWTEventListener() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + Toolkit.getDefaultToolkit(). + removeAWTEventListener(LayerEventController.this); + return null; + } + }); + currentEventMask = 0; + } + + private boolean isEventEnabled(long eventMask, int id) { + return (((eventMask & AWTEvent.COMPONENT_EVENT_MASK) != 0 && + id >= ComponentEvent.COMPONENT_FIRST && + id <= ComponentEvent.COMPONENT_LAST) + || ((eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 && + id >= ContainerEvent.CONTAINER_FIRST && + id <= ContainerEvent.CONTAINER_LAST) + || ((eventMask & AWTEvent.FOCUS_EVENT_MASK) != 0 && + id >= FocusEvent.FOCUS_FIRST && + id <= FocusEvent.FOCUS_LAST) + || ((eventMask & AWTEvent.KEY_EVENT_MASK) != 0 && + id >= KeyEvent.KEY_FIRST && + id <= KeyEvent.KEY_LAST) + || ((eventMask & AWTEvent.MOUSE_WHEEL_EVENT_MASK) != 0 && + id == MouseEvent.MOUSE_WHEEL) + || ((eventMask & AWTEvent.MOUSE_MOTION_EVENT_MASK) != 0 && + (id == MouseEvent.MOUSE_MOVED || + id == MouseEvent.MOUSE_DRAGGED)) + || ((eventMask & AWTEvent.MOUSE_EVENT_MASK) != 0 && + id != MouseEvent.MOUSE_MOVED && + id != MouseEvent.MOUSE_DRAGGED && + id != MouseEvent.MOUSE_WHEEL && + id >= MouseEvent.MOUSE_FIRST && + id <= MouseEvent.MOUSE_LAST) + || ((eventMask & AWTEvent.INPUT_METHOD_EVENT_MASK) != 0 && + id >= InputMethodEvent.INPUT_METHOD_FIRST && + id <= InputMethodEvent.INPUT_METHOD_LAST) + || ((eventMask & AWTEvent.HIERARCHY_EVENT_MASK) != 0 && + id == HierarchyEvent.HIERARCHY_CHANGED) + || ((eventMask & AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK) != 0 && + (id == HierarchyEvent.ANCESTOR_MOVED || + id == HierarchyEvent.ANCESTOR_RESIZED))); + } + } + + /** + * The default glassPane for the {@link javax.swing.JLayer}. + * It is a subclass of {@code JPanel} which is non opaque by default. + */ + private static class DefaultLayerGlassPane extends JPanel { + /** + * Creates a new {@link DefaultLayerGlassPane} + */ + public DefaultLayerGlassPane() { + setOpaque(false); + } + + /** + * First, implementatation of this method iterates through + * glassPane's child components and returns {@code true} + * if any of them is visible and contains passed x,y point. + * After that it checks if no mouseListeners is attached to this component + * and no mouse cursor is set, then it returns {@code false}, + * otherwise calls the super implementation of this method. + * + * @param x the x coordinate of the point + * @param y the y coordinate of the point + * @return true if this component logically contains x,y + */ + public boolean contains(int x, int y) { + for (int i = 0; i < getComponentCount(); i++) { + Component c = getComponent(i); + Point point = SwingUtilities.convertPoint(this, new Point(x, y), c); + if(c.isVisible() && c.contains(point)){ + return true; + } + } + if (getMouseListeners().length == 0 + && getMouseMotionListeners().length == 0 + && getMouseWheelListeners().length == 0 + && !isCursorSet()) { + return false; + } + return super.contains(x, y); + } + } + + /** + * The default layout manager for the {@link javax.swing.JLayer}.
    + * It places the glassPane on top of the view component + * and makes it the same size as {@code JLayer}, + * it also makes the view component the same size but minus layer's insets
    + */ + private static class DefaultLayerLayout implements LayoutManager, Serializable { + /** + * {@inheritDoc} + */ + public void layoutContainer(Container parent) { + JLayer layer = (JLayer) parent; + Component view = layer.getView(); + Component glassPane = layer.getGlassPane(); + if (view != null) { + Insets insets = layer.getInsets(); + view.setLocation(insets.left, insets.top); + view.setSize(layer.getWidth() - insets.left - insets.right, + layer.getHeight() - insets.top - insets.bottom); + } + if (glassPane != null) { + glassPane.setLocation(0, 0); + glassPane.setSize(layer.getWidth(), layer.getHeight()); + } + } + + /** + * {@inheritDoc} + */ + public Dimension minimumLayoutSize(Container parent) { + JLayer layer = (JLayer) parent; + Insets insets = layer.getInsets(); + Dimension ret = new Dimension(insets.left + insets.right, + insets.top + insets.bottom); + Component view = layer.getView(); + if (view != null) { + Dimension size = view.getMinimumSize(); + ret.width += size.width; + ret.height += size.height; + } + if (ret.width == 0 || ret.height == 0) { + ret.width = ret.height = 4; + } + return ret; + } + + /** + * {@inheritDoc} + */ + public Dimension preferredLayoutSize(Container parent) { + JLayer layer = (JLayer) parent; + Insets insets = layer.getInsets(); + Dimension ret = new Dimension(insets.left + insets.right, + insets.top + insets.bottom); + Component view = layer.getView(); + if (view != null) { + Dimension size = view.getPreferredSize(); + if (size.width > 0 && size.height > 0) { + ret.width += size.width; + ret.height += size.height; + } + } + return ret; + } + + /** + * {@inheritDoc} + */ + public void addLayoutComponent(String name, Component comp) { + } + + /** + * {@inheritDoc} + */ + public void removeLayoutComponent(Component comp) { + } + } +} \ No newline at end of file diff --git a/jdk/src/share/classes/javax/swing/plaf/LayerUI.java b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java new file mode 100644 index 00000000000..44c57ce3cad --- /dev/null +++ b/jdk/src/share/classes/javax/swing/plaf/LayerUI.java @@ -0,0 +1,370 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + */ + +package javax.swing.plaf; + +import javax.accessibility.Accessible; +import javax.swing.*; +import javax.swing.plaf.ComponentUI; +import java.awt.*; +import java.awt.event.*; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeSupport; +import java.beans.PropertyChangeListener; +import java.io.Serializable; + +/** + * The base class for all {@link javax.swing.JLayer}'s UI delegates. + *

    + * {@link #paint(java.awt.Graphics, javax.swing.JComponent)} method performes the + * painting of the {@code JLayer} + * and {@link #eventDispatched(AWTEvent, JLayer)} method is notified + * about any {@code AWTEvent}s which have been generated by a {@code JLayer} + * or any of its subcomponents. + *

    + * The {@code LayerUI} differs from the UI delegates of the other components, + * because it is LookAndFeel independent and is not updated by default when + * the system LookAndFeel is changed. + *

    + * The subclasses of {@code LayerUI} can either be stateless and shareable + * by multiple {@code JLayer}s or not shareable. + * + * @param one of the super types of {@code JLayer}'s view component + * + * @see JLayer#setUI(LayerUI) + * @see JLayer#setView(Component) + * @see JLayer#getView() + * @since 1.7 + * + * @author Alexander Potochkin + */ +public class LayerUI + extends ComponentUI implements Serializable { + + private final PropertyChangeSupport propertyChangeSupport = + new PropertyChangeSupport(this); + + /** + * Paints the specified component. + * Subclasses should override this method and use + * the specified {@code Graphics} object to + * render the content of the component. + * + * @param g the {@code Graphics} context in which to paint; + * @param c the component being painted; + * it can be safely cast to the {@code JLayer} + */ + @Override + public void paint(Graphics g, JComponent c) { + c.paint(g); + } + + /** + * Dispatches {@code AWTEvent}s for {@code JLayer} + * and all it subcomponents to this {@code LayerUI} instance. + *

    + * To enable the {@code AWTEvent} of the particular type, + * you call {@link javax.swing.JLayer#setLayerEventMask} + * in {@link #installUI(javax.swing.JComponent)} + * and set the layer event mask to {@code 0} + * in {@link #uninstallUI(javax.swing.JComponent)} after that + * + * @param e the event to be dispatched + * @param l the layer this LayerUI is set to + * + * @see JLayer#setLayerEventMask(long) + * @see javax.swing.JLayer#getLayerEventMask() + */ + public void eventDispatched(AWTEvent e, JLayer l){ + } + + /** + * Invoked when {@link javax.swing.JLayer#updateUI()} is called + * by the {@code JLayer} this {@code LayerUI} is set to. + * + * @param l the {@code JLayer} which UI is updated + */ + public void updateUI(JLayer l){ + } + + /** + * Configures the {@code JLayer} this {@code LayerUI} is set to. + * The default implementation registers the {@code LayerUI} + * as a property change listener for the passed {@code JLayer} component. + * + * @param c the {@code JLayer} component where this UI delegate is being installed + */ + public void installUI(JComponent c) { + addPropertyChangeListener((JLayer) c); + } + + /** + * Reverses the configuration which was previously set + * in the {@link #installUI(JComponent)} method. + * The default implementation unregisters the property change listener + * for the passed JLayer component. + * + * @param c the component from which this UI delegate is being removed. + */ + public void uninstallUI(JComponent c) { + removePropertyChangeListener((JLayer) c); + } + + /** + * Adds a PropertyChangeListener to the listener list. The listener is + * registered for all bound properties of this class. + *

    + * If {@code listener} is {@code null}, + * no exception is thrown and no action is performed. + * + * @param listener the property change listener to be added + * @see #removePropertyChangeListener + * @see #getPropertyChangeListeners + * @see #addPropertyChangeListener(String, java.beans.PropertyChangeListener) + */ + public void addPropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(listener); + } + + /** + * Removes a PropertyChangeListener from the listener list. This method + * should be used to remove PropertyChangeListeners that were registered + * for all bound properties of this class. + *

    + * If {@code listener} is {@code null}, + * no exception is thrown and no action is performed. + * + * @param listener the PropertyChangeListener to be removed + * @see #addPropertyChangeListener + * @see #getPropertyChangeListeners + * @see #removePropertyChangeListener(String, PropertyChangeListener) + */ + public void removePropertyChangeListener(PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(listener); + } + + /** + * Returns an array of all the property change listeners + * registered on this component. + * + * @return all of this ui's {@code PropertyChangeListener}s + * or an empty array if no property change + * listeners are currently registered + * @see #addPropertyChangeListener + * @see #removePropertyChangeListener + * @see #getPropertyChangeListeners(String) + */ + public PropertyChangeListener[] getPropertyChangeListeners() { + return propertyChangeSupport.getPropertyChangeListeners(); + } + + /** + * Adds a PropertyChangeListener to the listener list for a specific + * property. + *

    + * If {@code propertyName} or {@code listener} is {@code null}, + * no exception is thrown and no action is taken. + * + * @param propertyName one of the property names listed above + * @param listener the property change listener to be added + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @see #addPropertyChangeListener(String, PropertyChangeListener) + */ + public void addPropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + propertyChangeSupport.addPropertyChangeListener(propertyName, listener); + } + + /** + * Removes a {@code PropertyChangeListener} from the listener + * list for a specific property. This method should be used to remove + * {@code PropertyChangeListener}s + * that were registered for a specific bound property. + *

    + * If {@code propertyName} or {@code listener} is {@code null}, + * no exception is thrown and no action is taken. + * + * @param propertyName a valid property name + * @param listener the PropertyChangeListener to be removed + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners(String) + * @see #removePropertyChangeListener(PropertyChangeListener) + */ + public void removePropertyChangeListener(String propertyName, + PropertyChangeListener listener) { + propertyChangeSupport.removePropertyChangeListener(propertyName, listener); + } + + /** + * Returns an array of all the listeners which have been associated + * with the named property. + * + * @return all of the {@code PropertyChangeListener}s associated with + * the named property; if no such listeners have been added or + * if {@code propertyName} is {@code null}, an empty + * array is returned + * @see #addPropertyChangeListener(String, PropertyChangeListener) + * @see #removePropertyChangeListener(String, PropertyChangeListener) + * @see #getPropertyChangeListeners + */ + public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return propertyChangeSupport.getPropertyChangeListeners(propertyName); + } + + /** + * Support for reporting bound property changes for Object properties. + * This method can be called when a bound property has changed and it will + * send the appropriate PropertyChangeEvent to any registered + * PropertyChangeListeners. + * + * @param propertyName the property whose value has changed + * @param oldValue the property's previous value + * @param newValue the property's new value + */ + protected void firePropertyChange(String propertyName, + Object oldValue, Object newValue) { + propertyChangeSupport.firePropertyChange(propertyName, oldValue, newValue); + } + + /** + * Notifies the {@code LayerUI} when any of its property are changed + * and enables updating every {@code JLayer} this {@code LayerUI} instance is set to. + * + * @param evt the PropertyChangeEvent generated by this {@code LayerUI} + * @param l the {@code JLayer} this LayerUI is set to + */ + public void applyPropertyChange(PropertyChangeEvent evt, JLayer l) { + } + + /** + * Returns the preferred size of the viewport for a view component. + * + * @return the preferred size of the viewport for a view component + * @see Scrollable#getPreferredScrollableViewportSize() + */ + public Dimension getPreferredScrollableViewportSize(JLayer l) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getPreferredScrollableViewportSize(); + } + return l.getPreferredSize(); + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one block of rows or columns, depending on the value of orientation. + * + * @return the "block" increment for scrolling in the specified direction + * @see Scrollable#getScrollableBlockIncrement(Rectangle, int, int) + */ + public int getScrollableBlockIncrement(JLayer l, + Rectangle visibleRect, + int orientation, int direction) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableBlockIncrement( + visibleRect,orientation, direction); + } + return (orientation == SwingConstants.VERTICAL) ? visibleRect.height : + visibleRect.width; + } + + /** + * Returns {@code false} to indicate that the height of the viewport does not + * determine the height of the layer, unless the preferred height + * of the layer is smaller than the height of the viewport. + * + * @return whether the layer should track the height of the viewport + * @see Scrollable#getScrollableTracksViewportHeight() + */ + public boolean getScrollableTracksViewportHeight(JLayer l) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableTracksViewportHeight(); + } + if (l.getParent() instanceof JViewport) { + return (((JViewport)l.getParent()).getHeight() > l.getPreferredSize().height); + } + return false; + } + + /** + * Returns {@code false} to indicate that the width of the viewport does not + * determine the width of the layer, unless the preferred width + * of the layer is smaller than the width of the viewport. + * + * @return whether the layer should track the width of the viewport + * @see Scrollable + * @see LayerUI#getScrollableTracksViewportWidth(JLayer) + */ + public boolean getScrollableTracksViewportWidth(JLayer l) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableTracksViewportWidth(); + } + if (l.getParent() instanceof JViewport) { + return (((JViewport)l.getParent()).getWidth() > l.getPreferredSize().width); + } + return false; + } + + /** + * Returns a scroll increment, which is required for components + * that display logical rows or columns in order to completely expose + * one new row or column, depending on the value of orientation. + * Ideally, components should handle a partially exposed row or column + * by returning the distance required to completely expose the item. + *

    + * Scrolling containers, like JScrollPane, will use this method + * each time the user requests a unit scroll. + * + * @return The "unit" increment for scrolling in the specified direction. + * This value should always be positive. + * @see Scrollable#getScrollableUnitIncrement(Rectangle, int, int) + */ + public int getScrollableUnitIncrement(JLayer l, + Rectangle visibleRect, + int orientation, int direction) { + if (l.getView() instanceof Scrollable) { + return ((Scrollable)l.getView()).getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + return 1; + } + + /** + * If the {@code JLayer}'s view component is not {@code null}, + * this calls the view's {@code getBaseline()} method. + * Otherwise, the default implementation is called. + * + * @param c {@code JLayer} to return baseline resize behavior for + * @param width the width to get the baseline for + * @param height the height to get the baseline for + * @return baseline or a value < 0 indicating there is no reasonable + * baseline + */ + public int getBaseline(JComponent c, int width, int height) { + JLayer l = (JLayer) c; + if (l.getView() != null) { + return l.getView().getBaseline(width, height); + } + return super.getBaseline(c, width, height); + } + + /** + * If the {@code JLayer}'s view component is not {@code null}, + * this calls the view's {@code getBaselineResizeBehavior()} method. + * Otherwise, the default implementation is called. + * + * @param c {@code JLayer} to return baseline resize behavior for + * @return an enum indicating how the baseline changes as the component + * size changes + */ + public Component.BaselineResizeBehavior getBaselineResizeBehavior(JComponent c) { + JLayer l = (JLayer) c; + if (l.getView() != null) { + return l.getView().getBaselineResizeBehavior(); + } + return super.getBaselineResizeBehavior(c); + } +} \ No newline at end of file diff --git a/jdk/test/javax/swing/JLayer/SerializationTest/SerializationTest.java b/jdk/test/javax/swing/JLayer/SerializationTest/SerializationTest.java new file mode 100644 index 00000000000..0c18e41491e --- /dev/null +++ b/jdk/test/javax/swing/JLayer/SerializationTest/SerializationTest.java @@ -0,0 +1,53 @@ +/* + * @test + * @summary Makes sure that JLayer is synchronizable + * @author Alexander Potochkin + * @run main SerializationTest + */ + +import javax.swing.*; +import javax.swing.plaf.LayerUI; +import java.io.ByteArrayInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.ByteArrayOutputStream; + +public class SerializationTest { + + public static void main(String[] args) throws Exception { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream); + + JLayer layer = new JLayer(new JButton("Hello")); + + layer.setUI(new TestLayerUI()); + + outputStream.writeObject(layer); + outputStream.flush(); + + ByteArrayInputStream byteArrayInputStream = + new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream); + + JLayer newLayer = (JLayer) inputStream.readObject(); + + if (newLayer.getLayout() == null) { + throw new RuntimeException("JLayer's layout is null"); + } + if (newLayer.getGlassPane() == null) { + throw new RuntimeException("JLayer's glassPane is null"); + } + if (newLayer.getUI().getClass() != layer.getUI().getClass()) { + throw new RuntimeException("Different UIs"); + } + if (newLayer.getView().getClass() != layer.getView().getClass()) { + throw new RuntimeException("Different Views"); + } + } + + static class TestLayerUI extends LayerUI { + public String toString() { + return "TestLayerUI"; + } + } +} \ No newline at end of file From cb2742d7b21cfe83b391b9dd8a98f326cd12ecf0 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 11 Aug 2009 12:15:24 +0800 Subject: [PATCH 56/70] 6866479: libzip.so caused JVM to crash when running jarsigner Reviewed-by: mullan --- .../classes/sun/security/tools/JarSigner.java | 10 +++ .../sun/security/tools/jarsigner/samename.sh | 61 +++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 jdk/test/sun/security/tools/jarsigner/samename.sh diff --git a/jdk/src/share/classes/sun/security/tools/JarSigner.java b/jdk/src/share/classes/sun/security/tools/JarSigner.java index 76a9c403145..fd0797a854d 100644 --- a/jdk/src/share/classes/sun/security/tools/JarSigner.java +++ b/jdk/src/share/classes/sun/security/tools/JarSigner.java @@ -412,6 +412,16 @@ public class JarSigner { } storetype = KeyStoreUtil.niceStoreTypeName(storetype); + try { + if (signedjar != null && new File(signedjar).getCanonicalPath().equals( + new File(jarfile).getCanonicalPath())) { + signedjar = null; + } + } catch (IOException ioe) { + // File system error? + // Just ignore it. + } + if (P11KEYSTORE.equalsIgnoreCase(storetype) || KeyStoreUtil.isWindowsKeyStore(storetype)) { token = true; diff --git a/jdk/test/sun/security/tools/jarsigner/samename.sh b/jdk/test/sun/security/tools/jarsigner/samename.sh new file mode 100644 index 00000000000..7949088a7b9 --- /dev/null +++ b/jdk/test/sun/security/tools/jarsigner/samename.sh @@ -0,0 +1,61 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6866479 +# @summary libzip.so caused JVM to crash when running jarsigner +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + Windows_* | CYGWIN* ) + SIGNEDJAR=EM.jar + FS="\\" + ;; + * ) + SIGNEDJAR=em.jar + FS="/" + ;; +esac + +KS=samename.jks +JFILE=em.jar + +KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS" +JAR=$TESTJAVA${FS}bin${FS}jar +JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner + +rm $KS $JFILE $SIGNEDJAR +echo A > A +$JAR cvf $JFILE A + +$KT -alias a -dname CN=a -keyalg rsa -genkey -validity 300 + +$JARSIGNER -keystore $KS -storepass changeit -signedjar $SIGNEDJAR $JFILE a + From 50689ce53631940317bc75381f2aedce1b344029 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 11 Aug 2009 12:17:13 +0800 Subject: [PATCH 57/70] 6710360: export Kerberos session key to applications Reviewed-by: valeriep --- .../sun/security/jgss/ExtendedGSSContext.java | 90 +++++++++++++++++++ .../jgss/InquireSecContextPermission.java | 54 +++++++++++ .../com/sun/security/jgss/InquireType.java | 38 ++++++++ .../sun/security/jgss/GSSContextImpl.java | 19 +++- .../sun/security/jgss/krb5/Krb5Context.java | 52 +++++++++++ .../sun/security/jgss/spi/GSSContextSpi.java | 16 +++- .../security/jgss/spnego/SpNegoContext.java | 22 ++++- .../jgss/wrapper/NativeGSSContext.java | 9 +- .../sun/security/tools/PolicyTool.java | 19 ++-- .../InquireSecContextPermissionCheck.java | 50 +++++++++++ jdk/test/sun/security/krb5/auto/Context.java | 16 +++- 11 files changed, 368 insertions(+), 17 deletions(-) create mode 100644 jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java create mode 100644 jdk/src/share/classes/com/sun/security/jgss/InquireSecContextPermission.java create mode 100644 jdk/src/share/classes/com/sun/security/jgss/InquireType.java create mode 100644 jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java diff --git a/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java new file mode 100644 index 00000000000..ed1ab747136 --- /dev/null +++ b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java @@ -0,0 +1,90 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.security.jgss; + +import org.ietf.jgss.*; + +/** + * The extended GSSContext interface for supporting additional + * functionalities not defined by {@code org.ietf.jgss.GSSContext}, + * such as querying context-specific attributes. + */ +public interface ExtendedGSSContext extends GSSContext { + /** + * Return the mechanism-specific attribute associated with {@code type}. + *

    + * For each supported attribute type, the type for the output are + * defined below. + *

      + *
    1. {@code KRB5_GET_SESSION_KEY}: + * the returned object is an instance of {@link java.security.Key}, + * which has the following properties: + *
        + *
      • Algorithm: enctype as a string, where + * enctype is defined in RFC 3961, section 8. + *
      • Format: "RAW" + *
      • Encoded form: the raw key bytes, not in any ASN.1 encoding + *
      + *
    + * + * If there is a security manager, an {@link InquireSecContextPermission} + * with the name {@code type.mech} must be granted. Otherwise, this could + * result in a {@link SecurityException}.

    + * + * Example: + *

    +     *      GSSContext ctxt = m.createContext(...)
    +     *      // Establishing the context
    +     *      if (ctxt instanceof ExtendedGSSContext) {
    +     *          ExtendedGSSContext ex = (ExtendedGSSContext)ctxt;
    +     *          try {
    +     *              Key key = (key)ex.inquireSecContext(
    +     *                      InquireType.KRB5_GET_SESSION_KEY);
    +     *              // read key info
    +     *          } catch (GSSException gsse) {
    +     *              // deal with exception
    +     *          }
    +     *      }
    +     * 
    + * @param type the type of the attribute requested + * @return the attribute, see the method documentation for details. + * @throws GSSException containing the following + * major error codes: + * {@link GSSException#BAD_MECH GSSException.BAD_MECH} if the mechanism + * does not support this method, + * {@link GSSException#UNAVAILABLE GSSException.UNAVAILABLE} if the + * type specified is not supported, + * {@link GSSException#NO_CONTEXT GSSException.NO_CONTEXT} if the + * security context is invalid, + * {@link GSSException#FAILURE GSSException.FAILURE} for other + * unspecified failures. + * @throws SecurityException if a security manager exists and a proper + * {@link InquireSecContextPermission} is not granted. + * @see InquireSecContextPermission + */ + public Object inquireSecContext(InquireType type) + throws GSSException; +} diff --git a/jdk/src/share/classes/com/sun/security/jgss/InquireSecContextPermission.java b/jdk/src/share/classes/com/sun/security/jgss/InquireSecContextPermission.java new file mode 100644 index 00000000000..2acb9ab9e97 --- /dev/null +++ b/jdk/src/share/classes/com/sun/security/jgss/InquireSecContextPermission.java @@ -0,0 +1,54 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.security.jgss; + +import java.security.BasicPermission; + +/** + * This class is used to protect various attributes of an established + * GSS security context that can be accessed using the + * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext} + * method. + * + *

    The target name is the {@link InquireType} allowed. + */ +public final class InquireSecContextPermission extends BasicPermission { + + /** + * Constructs a new {@code InquireSecContextPermission} object with + * the specified name. The name is the symbolic name of the + * {@link InquireType} allowed. + * + * @param name the {@link InquireType} allowed by this + * permission. "*" means all {@link InquireType}s are allowed. + * + * @throws NullPointerException if name is null. + * @throws IllegalArgumentException if name is empty. + */ + public InquireSecContextPermission(String name) { + super(name); + } +} diff --git a/jdk/src/share/classes/com/sun/security/jgss/InquireType.java b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java new file mode 100644 index 00000000000..2b1d8172e72 --- /dev/null +++ b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java @@ -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 com.sun.security.jgss; + +/** + * Attribute types that can be specified as an argument of + * {@link com.sun.security.jgss.ExtendedGSSContext#inquireSecContext} + */ +public enum InquireType { + /** + * Attribute type for retrieving the session key of an + * established security context. + */ + KRB5_GET_SESSION_KEY +} diff --git a/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java b/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java index 046f6478277..de703ef4ded 100644 --- a/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java +++ b/jdk/src/share/classes/sun/security/jgss/GSSContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,14 +27,13 @@ package sun.security.jgss; import org.ietf.jgss.*; import sun.security.jgss.spi.*; -import sun.security.jgss.*; import sun.security.util.ObjectIdentifier; import java.io.InputStream; import java.io.OutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; - +import com.sun.security.jgss.*; /** * This class represents the JGSS security context and its associated @@ -88,7 +87,7 @@ import java.io.IOException; * per-message operations are returned in an instance of the MessageProp * class, which is used as an argument in these calls. */ -class GSSContextImpl implements GSSContext { +class GSSContextImpl implements ExtendedGSSContext { private GSSManagerImpl gssManager = null; @@ -630,4 +629,16 @@ class GSSContextImpl implements GSSContext { srcName = null; targName = null; } + + @Override + public Object inquireSecContext(InquireType type) throws GSSException { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkPermission(new InquireSecContextPermission(type.toString())); + } + if (mechCtxt == null) { + throw new GSSException(GSSException.NO_CONTEXT); + } + return mechCtxt.inquireSecContext(type); + } } diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java index f2ef7d59875..48d62c76c26 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/Krb5Context.java @@ -25,6 +25,7 @@ package sun.security.jgss.krb5; +import com.sun.security.jgss.InquireType; import org.ietf.jgss.*; import sun.misc.HexDumpEncoder; import sun.security.jgss.GSSUtil; @@ -38,6 +39,7 @@ import java.io.IOException; import java.security.Provider; import java.security.AccessController; import java.security.AccessControlContext; +import java.security.Key; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import javax.crypto.Cipher; @@ -1283,4 +1285,54 @@ class Krb5Context implements GSSContextSpi { // Currently used by InitialToken only return caller; } + + /** + * The session key returned by inquireSecContext(KRB5_INQ_SSPI_SESSION_KEY) + */ + static class KerberosSessionKey implements Key { + private EncryptionKey key; + + KerberosSessionKey(EncryptionKey key) { + this.key = key; + } + + @Override + public String getAlgorithm() { + return Integer.toString(key.getEType()); + } + + @Override + public String getFormat() { + return "RAW"; + } + + @Override + public byte[] getEncoded() { + return key.getBytes().clone(); + } + + @Override + public String toString() { + return "Kerberos session key: etype: " + key.getEType() + "\n" + + new sun.misc.HexDumpEncoder().encodeBuffer(key.getBytes()); + } + } + + /** + * Return the mechanism-specific attribute associated with {@code type}. + * Only KRB5_GET_SESSION_KEY is supported now. + */ + public Object inquireSecContext(InquireType type) + throws GSSException { + if (type == InquireType.KRB5_GET_SESSION_KEY) { + if (key == null) { + throw new GSSException(GSSException.NO_CONTEXT, -1, + "Session key not established."); + } else { + return new KerberosSessionKey(key); + } + } + throw new GSSException(GSSException.UNAVAILABLE, -1, + "Inquire type not supported."); + } } diff --git a/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java b/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java index b4ce37a4c0e..5bf359a1f8c 100644 --- a/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java +++ b/jdk/src/share/classes/sun/security/jgss/spi/GSSContextSpi.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,6 +46,7 @@ import org.ietf.jgss.*; import java.io.InputStream; import java.io.OutputStream; import java.security.Provider; +import com.sun.security.jgss.*; /** * This interface is implemented by a mechanism specific instance of a GSS @@ -265,7 +266,6 @@ public interface GSSContextSpi { * @param msgPro on input it contains the requested qop and * confidentiality state, on output, the applied values * @exception GSSException may be thrown - * @see MessageInfo * @see unwrap */ public void wrap(InputStream is, OutputStream os, MessageProp msgProp) @@ -315,7 +315,6 @@ public interface GSSContextSpi { * @param msgProp will contain the applied qop and confidentiality * of the input token and any informatory status values * @exception GSSException may be thrown - * @see MessageInfo * @see wrap */ public void unwrap(InputStream is, OutputStream os, @@ -403,4 +402,15 @@ public interface GSSContextSpi { * @exception GSSException may be thrown */ public void dispose() throws GSSException; + + /** + * Return the mechanism-specific attribute associated with (@code type}. + * + * @param type the type of the attribute requested + * @return the attribute + * @throws GSSException see {@link ExtendedGSSContext#inquireSecContext} + * for details + */ + public Object inquireSecContext(InquireType type) + throws GSSException; } diff --git a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java index a84e8a26001..a436092f1bb 100644 --- a/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java +++ b/jdk/src/share/classes/sun/security/jgss/spnego/SpNegoContext.java @@ -25,10 +25,10 @@ package sun.security.jgss.spnego; +import com.sun.security.jgss.ExtendedGSSContext; +import com.sun.security.jgss.InquireType; import java.io.*; import java.security.Provider; -import java.util.List; -import java.util.ArrayList; import org.ietf.jgss.*; import sun.security.jgss.*; import sun.security.jgss.spi.*; @@ -1185,4 +1185,22 @@ public class SpNegoContext implements GSSContextSpi { return ("Unknown state " + state); } } + + /** + * Retrieve attribute of the context for {@code type}. + */ + public Object inquireSecContext(InquireType type) + throws GSSException { + if (mechContext == null) { + throw new GSSException(GSSException.NO_CONTEXT, -1, + "Underlying mech not established."); + } + if (mechContext instanceof ExtendedGSSContext) { + return ((ExtendedGSSContext)mechContext).inquireSecContext(type); + } else { + throw new GSSException(GSSException.BAD_MECH, -1, + "inquireSecContext not supported by underlying mech."); + } + } + } diff --git a/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java b/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java index 63f37e47614..5b2a670b054 100644 --- a/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java +++ b/jdk/src/share/classes/sun/security/jgss/wrapper/NativeGSSContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import sun.security.util.ObjectIdentifier; import sun.security.jgss.spnego.NegTokenInit; import sun.security.jgss.spnego.NegTokenTarg; import javax.security.auth.kerberos.DelegationPermission; +import com.sun.security.jgss.InquireType; import java.io.*; @@ -615,4 +616,10 @@ class NativeGSSContext implements GSSContextSpi { protected void finalize() throws Throwable { dispose(); } + + public Object inquireSecContext(InquireType type) + throws GSSException { + throw new GSSException(GSSException.UNAVAILABLE, -1, + "Inquire type not supported."); + } } diff --git a/jdk/src/share/classes/sun/security/tools/PolicyTool.java b/jdk/src/share/classes/sun/security/tools/PolicyTool.java index c2c6218bd35..afc3a9b8988 100644 --- a/jdk/src/share/classes/sun/security/tools/PolicyTool.java +++ b/jdk/src/share/classes/sun/security/tools/PolicyTool.java @@ -1,5 +1,5 @@ /* - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,21 +35,16 @@ import java.net.MalformedURLException; import java.lang.reflect.*; import java.text.Collator; import java.text.MessageFormat; -import sun.misc.BASE64Decoder; -import sun.security.provider.PolicyParser.PermissionEntry; import sun.security.util.PropertyExpander; import sun.security.util.PropertyExpander.ExpandException; import java.awt.*; import java.awt.event.*; import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; import java.security.cert.CertificateException; import java.security.*; import sun.security.provider.*; import sun.security.util.PolicyUtil; import javax.security.auth.x500.X500Principal; -import java.util.HashSet; /** * PolicyTool may be used by users and administrators to configure the @@ -1459,6 +1454,7 @@ class ToolDialog extends Dialog { PERM_ARRAY.add(new AWTPerm()); PERM_ARRAY.add(new DelegationPerm()); PERM_ARRAY.add(new FilePerm()); + PERM_ARRAY.add(new InqSecContextPerm()); PERM_ARRAY.add(new LogPerm()); PERM_ARRAY.add(new MgmtPerm()); PERM_ARRAY.add(new MBeanPerm()); @@ -3961,6 +3957,17 @@ class FilePerm extends Perm { } } +class InqSecContextPerm extends Perm { + public InqSecContextPerm() { + super("InquireSecContextPermission", + "com.sun.security.jgss.InquireSecContextPermission", + new String[] { + "KRB5_GET_SESSION_KEY" + }, + null); + } +} + class LogPerm extends Perm { public LogPerm() { super("LoggingPermission", diff --git a/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java b/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java new file mode 100644 index 00000000000..5a940ae91eb --- /dev/null +++ b/jdk/test/com/sun/security/jgss/InquireSecContextPermissionCheck.java @@ -0,0 +1,50 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6710360 + * @summary export Kerberos session key to applications + */ + +import com.sun.security.jgss.InquireSecContextPermission; + +public class InquireSecContextPermissionCheck { + + public static void main(String[] args) throws Exception { + + InquireSecContextPermission p0, p1; + p0 = new InquireSecContextPermission( + "KRB5_GET_SESSION_KEY"); + p1 = new InquireSecContextPermission("*"); + + if (!p1.implies(p0) || !p1.implies(p1) || !p0.implies(p0)) { + throw new Exception("Check failed"); + } + + if (p0.implies(p1)) { + throw new Exception("This is bad"); + } + } +} + diff --git a/jdk/test/sun/security/krb5/auto/Context.java b/jdk/test/sun/security/krb5/auto/Context.java index 2439aa24037..b8ce532be19 100644 --- a/jdk/test/sun/security/krb5/auto/Context.java +++ b/jdk/test/sun/security/krb5/auto/Context.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2008-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,7 @@ */ import com.sun.security.auth.module.Krb5LoginModule; +import java.security.Key; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Arrays; @@ -38,6 +39,8 @@ import org.ietf.jgss.GSSManager; import org.ietf.jgss.GSSName; import org.ietf.jgss.MessageProp; import org.ietf.jgss.Oid; +import com.sun.security.jgss.ExtendedGSSContext; +import com.sun.security.jgss.InquireType; /** * Context of a JGSS subject, encapsulating Subject and GSSContext. @@ -276,6 +279,17 @@ public class Context { } } } + if (x != null && x instanceof ExtendedGSSContext) { + if (x.isEstablished()) { + ExtendedGSSContext ex = (ExtendedGSSContext)x; + Key k = (Key)ex.inquireSecContext( + InquireType.KRB5_GET_SESSION_KEY); + if (k == null) { + throw new Exception("Session key cannot be null"); + } + System.out.println("Session key is: " + k); + } + } } /** From be3a1f1294df8c38d5c26c8377e897d8eb1325bb Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 11 Aug 2009 12:20:32 +0800 Subject: [PATCH 58/70] 6821190: more InquireType values for ExtendedGSSContext Reviewed-by: valeriep --- .../security/jgss/AuthorizationDataEntry.java | 68 +++++++++++++++++++ .../sun/security/jgss/ExtendedGSSContext.java | 12 ++++ .../com/sun/security/jgss/InquireType.java | 20 +++++- .../jgss/krb5/InitSecContextToken.java | 24 ++++++- .../sun/security/jgss/krb5/Krb5Context.java | 43 +++++++++--- .../sun/security/krb5/Credentials.java | 22 +++++- .../classes/sun/security/krb5/KrbApReq.java | 7 +- .../krb5/internal/AuthorizationData.java | 8 +++ .../sun/security/tools/PolicyTool.java | 5 +- jdk/test/sun/security/krb5/auto/Context.java | 18 +++++ 10 files changed, 210 insertions(+), 17 deletions(-) create mode 100644 jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java diff --git a/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java b/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java new file mode 100644 index 00000000000..0386792a7c2 --- /dev/null +++ b/jdk/src/share/classes/com/sun/security/jgss/AuthorizationDataEntry.java @@ -0,0 +1,68 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.security.jgss; + +/** + * Kerberos 5 AuthorizationData entry. + */ +final public class AuthorizationDataEntry { + + private final int type; + private final byte[] data; + + /** + * Create an AuthorizationDataEntry object. + * @param type the ad-type + * @param data the ad-data, a copy of the data will be saved + * inside the object. + */ + public AuthorizationDataEntry(int type, byte[] data) { + this.type = type; + this.data = data.clone(); + } + + /** + * Get the ad-type field. + * @return ad-type + */ + public int getType() { + return type; + } + + /** + * Get a copy of the ad-data field. + * @return ad-data + */ + public byte[] getData() { + return data.clone(); + } + + public String toString() { + return "AuthorizationDataEntry: type="+type+", data=" + + data.length + " bytes:\n" + + new sun.misc.HexDumpEncoder().encode(data); + } +} diff --git a/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java index ed1ab747136..dc7a3556d7d 100644 --- a/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java +++ b/jdk/src/share/classes/com/sun/security/jgss/ExtendedGSSContext.java @@ -39,6 +39,11 @@ public interface ExtendedGSSContext extends GSSContext { * For each supported attribute type, the type for the output are * defined below. *

      + *
    1. {@code KRB5_GET_TKT_FLAGS}: + * the returned object is a boolean array for the service ticket flags, + * which is long enough to contain all true bits. This means if + * the user wants to get the n'th bit but the length of the + * returned array is less than n, it is regarded as false. *
    2. {@code KRB5_GET_SESSION_KEY}: * the returned object is an instance of {@link java.security.Key}, * which has the following properties: @@ -48,6 +53,13 @@ public interface ExtendedGSSContext extends GSSContext { *
    3. Format: "RAW" *
    4. Encoded form: the raw key bytes, not in any ASN.1 encoding * + *
    5. {@code KRB5_GET_AUTHZ_DATA}: + * the returned object is an array of + * {@link com.sun.security.jgss.AuthorizationDataEntry}, or null if the + * optional field is missing in the service ticket. + *
    6. {@code KRB5_GET_AUTHTIME}: + * the returned object is a String object in the standard KerberosTime + * format defined in RFC 4120 5.2.3 *
    * * If there is a security manager, an {@link InquireSecContextPermission} diff --git a/jdk/src/share/classes/com/sun/security/jgss/InquireType.java b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java index 2b1d8172e72..b9ea04098b5 100644 --- a/jdk/src/share/classes/com/sun/security/jgss/InquireType.java +++ b/jdk/src/share/classes/com/sun/security/jgss/InquireType.java @@ -32,7 +32,23 @@ package com.sun.security.jgss; public enum InquireType { /** * Attribute type for retrieving the session key of an - * established security context. + * established Kerberos 5 security context. */ - KRB5_GET_SESSION_KEY + KRB5_GET_SESSION_KEY, + /** + * Attribute type for retrieving the service ticket flags of an + * established Kerberos 5 security context. + */ + KRB5_GET_TKT_FLAGS, + /** + * Attribute type for retrieving the authorization data in the + * service ticket of an established Kerberos 5 security context. + * Only supported on the acceptor side. + */ + KRB5_GET_AUTHZ_DATA, + /** + * Attribute type for retrieving the authtime in the service ticket + * of an established Kerberos 5 security context. + */ + KRB5_GET_AUTHTIME } diff --git a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java index 6706e8e4a4c..5f88068ccec 100644 --- a/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java +++ b/jdk/src/share/classes/sun/security/jgss/krb5/InitSecContextToken.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,12 +25,14 @@ package sun.security.jgss.krb5; +import com.sun.security.jgss.AuthorizationDataEntry; import org.ietf.jgss.*; import java.io.InputStream; -import java.io.OutputStream; import java.io.IOException; import sun.security.krb5.*; import java.net.InetAddress; +import sun.security.krb5.internal.AuthorizationData; +import sun.security.krb5.internal.KerberosTime; class InitSecContextToken extends InitialToken { @@ -59,6 +61,9 @@ class InitSecContextToken extends InitialToken { Checksum checksum = gssChecksum.getChecksum(); + context.setTktFlags(serviceTicket.getFlags()); + context.setAuthTime( + new KerberosTime(serviceTicket.getAuthTime()).toString()); apReq = new KrbApReq(serviceTicket, mutualRequired, useSubkey, @@ -143,6 +148,21 @@ class InitSecContextToken extends InitialToken { // Use the same sequence number as the peer // (Behaviour exhibited by the Windows SSPI server) context.resetMySequenceNumber(peerSeqNumber); + context.setAuthTime( + new KerberosTime(apReq.getCreds().getAuthTime()).toString()); + context.setTktFlags(apReq.getCreds().getFlags()); + AuthorizationData ad = apReq.getCreds().getAuthzData(); + if (ad == null) { + context.setAuthzData(null); + } else { + AuthorizationDataEntry[] authzData = + new AuthorizationDataEntry[ad.count()]; + for (int i=0; i>> KrbApReq: authenticate succeed."); } diff --git a/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java b/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java index 269edec71a1..13c89dec7d8 100644 --- a/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java +++ b/jdk/src/share/classes/sun/security/krb5/internal/AuthorizationData.java @@ -174,4 +174,12 @@ public class AuthorizationData implements Cloneable { } return retVal; } + + public int count() { + return entry.length; + } + + public AuthorizationDataEntry item(int i) { + return (AuthorizationDataEntry)entry[i].clone(); + } } diff --git a/jdk/src/share/classes/sun/security/tools/PolicyTool.java b/jdk/src/share/classes/sun/security/tools/PolicyTool.java index afc3a9b8988..ce54ba61ca9 100644 --- a/jdk/src/share/classes/sun/security/tools/PolicyTool.java +++ b/jdk/src/share/classes/sun/security/tools/PolicyTool.java @@ -3962,7 +3962,10 @@ class InqSecContextPerm extends Perm { super("InquireSecContextPermission", "com.sun.security.jgss.InquireSecContextPermission", new String[] { - "KRB5_GET_SESSION_KEY" + "KRB5_GET_SESSION_KEY", + "KRB5_GET_TKT_FLAGS", + "KRB5_GET_AUTHZ_DATA", + "KRB5_GET_AUTHTIME" }, null); } diff --git a/jdk/test/sun/security/krb5/auto/Context.java b/jdk/test/sun/security/krb5/auto/Context.java index b8ce532be19..140623f8310 100644 --- a/jdk/test/sun/security/krb5/auto/Context.java +++ b/jdk/test/sun/security/krb5/auto/Context.java @@ -41,6 +41,7 @@ import org.ietf.jgss.MessageProp; import org.ietf.jgss.Oid; import com.sun.security.jgss.ExtendedGSSContext; import com.sun.security.jgss.InquireType; +import com.sun.security.jgss.AuthorizationDataEntry; /** * Context of a JGSS subject, encapsulating Subject and GSSContext. @@ -288,6 +289,23 @@ public class Context { throw new Exception("Session key cannot be null"); } System.out.println("Session key is: " + k); + boolean[] flags = (boolean[])ex.inquireSecContext( + InquireType.KRB5_GET_TKT_FLAGS); + if (flags == null) { + throw new Exception("Ticket flags cannot be null"); + } + System.out.println("Ticket flags is: " + Arrays.toString(flags)); + String authTime = (String)ex.inquireSecContext( + InquireType.KRB5_GET_AUTHTIME); + if (authTime == null) { + throw new Exception("Auth time cannot be null"); + } + System.out.println("AuthTime is: " + authTime); + if (!x.isInitiator()) { + AuthorizationDataEntry[] ad = (AuthorizationDataEntry[])ex.inquireSecContext( + InquireType.KRB5_GET_AUTHZ_DATA); + System.out.println("AuthzData is: " + Arrays.toString(ad)); + } } } } From aa514761f5d1ad1d0346ea6530c58abe4914a31d Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 11 Aug 2009 15:36:52 +0800 Subject: [PATCH 59/70] 6868867: Test: sun/security/tools/keytool/standard.sh fails under windows/cygwin Reviewed-by: wetmore --- .../classes/sun/security/tools/KeyTool.java | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/jdk/src/share/classes/sun/security/tools/KeyTool.java b/jdk/src/share/classes/sun/security/tools/KeyTool.java index 892e86447e9..8f9e86ee063 100644 --- a/jdk/src/share/classes/sun/security/tools/KeyTool.java +++ b/jdk/src/share/classes/sun/security/tools/KeyTool.java @@ -880,41 +880,41 @@ public final class KeyTool { // might not work properly, since -gencert is slow // and there's no data in the pipe at the beginning. ByteArrayOutputStream bout = new ByteArrayOutputStream(); - byte[] b = new byte[4096]; - while (true) { - int len = inStream.read(b); - if (len < 0) break; - bout.write(b, 0, len); - } - inStream = new ByteArrayInputStream(bout.toByteArray()); try { - String importAlias = (alias!=null)?alias:keyAlias; - if (keyStore.entryInstanceOf(importAlias, KeyStore.PrivateKeyEntry.class)) { - kssave = installReply(importAlias, inStream); - if (kssave) { - System.err.println(rb.getString - ("Certificate reply was installed in keystore")); - } else { - System.err.println(rb.getString - ("Certificate reply was not installed in keystore")); - } - } else if (!keyStore.containsAlias(importAlias) || - keyStore.entryInstanceOf(importAlias, - KeyStore.TrustedCertificateEntry.class)) { - kssave = addTrustedCert(importAlias, inStream); - if (kssave) { - System.err.println(rb.getString - ("Certificate was added to keystore")); - } else { - System.err.println(rb.getString - ("Certificate was not added to keystore")); - } + byte[] b = new byte[4096]; + while (true) { + int len = inStream.read(b); + if (len < 0) break; + bout.write(b, 0, len); } } finally { if (inStream != System.in) { inStream.close(); } } + inStream = new ByteArrayInputStream(bout.toByteArray()); + String importAlias = (alias!=null)?alias:keyAlias; + if (keyStore.entryInstanceOf(importAlias, KeyStore.PrivateKeyEntry.class)) { + kssave = installReply(importAlias, inStream); + if (kssave) { + System.err.println(rb.getString + ("Certificate reply was installed in keystore")); + } else { + System.err.println(rb.getString + ("Certificate reply was not installed in keystore")); + } + } else if (!keyStore.containsAlias(importAlias) || + keyStore.entryInstanceOf(importAlias, + KeyStore.TrustedCertificateEntry.class)) { + kssave = addTrustedCert(importAlias, inStream); + if (kssave) { + System.err.println(rb.getString + ("Certificate was added to keystore")); + } else { + System.err.println(rb.getString + ("Certificate was not added to keystore")); + } + } } else if (command == IMPORTKEYSTORE) { doImportKeyStore(); kssave = true; From 3db64bc897b13ee0225f79c700626a0c0be987af Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Tue, 11 Aug 2009 18:27:01 +0800 Subject: [PATCH 60/70] 6585239: Regression: 2 DNS tests fail with JDK 5.0u13 b01 and pass with 5.0u12fcs Reviewed-by: vinnie --- jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java index 3b30bb96a6e..4375af2db55 100644 --- a/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java +++ b/jdk/src/share/classes/com/sun/jndi/dns/DnsContext.java @@ -972,14 +972,11 @@ class NameClassPairEnumeration implements NamingEnumeration { } /* - * ctx will be closed when no longer needed by the enumeration. + * ctx will be set to null when no longer needed by the enumeration. */ - public void close () { + public void close() { nodes = null; - if (ctx != null) { - ctx.close(); - ctx = null; - } + ctx = null; } public boolean hasMore() { From 90b1aee14250684e2bf4941dbb515613b6da2f90 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 11 Aug 2009 12:37:02 +0100 Subject: [PATCH 61/70] 4516760: (so) Intermittent SocketException: Transport endpoint is not connected (lnx) Reviewed-by: sherman --- jdk/src/solaris/native/sun/nio/ch/Net.c | 2 +- .../nio/channels/SocketChannel/Shutdown.java | 69 +++++++++++++++---- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/jdk/src/solaris/native/sun/nio/ch/Net.c b/jdk/src/solaris/native/sun/nio/ch/Net.c index 14ef8d14305..79031de6b59 100644 --- a/jdk/src/solaris/native/sun/nio/ch/Net.c +++ b/jdk/src/solaris/native/sun/nio/ch/Net.c @@ -541,7 +541,7 @@ Java_sun_nio_ch_Net_shutdown(JNIEnv *env, jclass cl, jobject fdo, jint jhow) { int how = (jhow == sun_nio_ch_Net_SHUT_RD) ? SHUT_RD : (jhow == sun_nio_ch_Net_SHUT_WR) ? SHUT_WR : SHUT_RDWR; - if (shutdown(fdval(env, fdo), how) < 0) + if ((shutdown(fdval(env, fdo), how) < 0) && (errno != ENOTCONN)) handleSocketError(env, errno); } diff --git a/jdk/test/java/nio/channels/SocketChannel/Shutdown.java b/jdk/test/java/nio/channels/SocketChannel/Shutdown.java index 16bd7a011ad..c2e579304f0 100644 --- a/jdk/test/java/nio/channels/SocketChannel/Shutdown.java +++ b/jdk/test/java/nio/channels/SocketChannel/Shutdown.java @@ -1,5 +1,5 @@ /* - * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,26 +22,65 @@ */ /* @test - * @bug 4618960 - * @summary Test isInputShutdown - * @library .. + * @bug 4618960 4516760 + * @summary Test shutdownXXX and isInputShutdown */ +import java.io.IOException; import java.net.*; -import java.nio.*; +import java.nio.ByteBuffer; import java.nio.channels.*; public class Shutdown { - public static void main(String args[]) throws Exception { - InetSocketAddress sa = new InetSocketAddress( - InetAddress.getByName(TestUtil.HOST), 23); - SocketChannel sc = SocketChannel.open(sa); - boolean before = sc.socket().isInputShutdown(); - sc.socket().shutdownInput(); - boolean after = sc.socket().isInputShutdown(); - sc.close(); - if (before || !after) - throw new Exception("Test failed"); + /** + * Accept a connection, and close it immediately causing a hard reset. + */ + static void acceptAndReset(ServerSocketChannel ssc) throws IOException { + SocketChannel peer = ssc.accept(); + try { + peer.setOption(StandardSocketOption.SO_LINGER, 0); + peer.configureBlocking(false); + peer.write(ByteBuffer.wrap(new byte[128*1024])); + } finally { + peer.close(); + } + } + + public static void main(String[] args) throws Exception { + ServerSocketChannel ssc = ServerSocketChannel.open() + .bind(new InetSocketAddress(0)); + try { + InetAddress lh = InetAddress.getLocalHost(); + int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort(); + SocketAddress remote = new InetSocketAddress(lh, port); + + // Test SocketChannel shutdownXXX + SocketChannel sc; + sc = SocketChannel.open(remote); + try { + acceptAndReset(ssc); + sc.shutdownInput(); + sc.shutdownOutput(); + } finally { + sc.close(); + } + + // Test Socket adapter shutdownXXX and isShutdownInput + sc = SocketChannel.open(remote); + try { + acceptAndReset(ssc); + boolean before = sc.socket().isInputShutdown(); + sc.socket().shutdownInput(); + boolean after = sc.socket().isInputShutdown(); + if (before || !after) + throw new RuntimeException("Before and after test failed"); + sc.socket().shutdownOutput(); + } finally { + sc.close(); + } + } finally { + ssc.close(); + } } } From c583b690e31a11739b3fcbab219762f7296e8f93 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 11 Aug 2009 12:38:43 +0100 Subject: [PATCH 62/70] 6867781: (file) Examples in javadoc use newFileAttributeView instead of getFileAttributeView Reviewed-by: sherman --- .../classes/java/nio/file/attribute/AclFileAttributeView.java | 2 +- .../classes/java/nio/file/attribute/PosixFileAttributeView.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java index 4127a78e942..13583381cbb 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/AclFileAttributeView.java @@ -75,7 +75,7 @@ import java.io.IOException; * .lookupPrincipalByName("joe"); * * // get view - * AclFileAttributeView view = file.newFileAttributeView(AclFileAttributeView.class); + * AclFileAttributeView view = file.getFileAttributeView(AclFileAttributeView.class); * * // create ACE to give "joe" read access * AclEntry entry = AclEntry.newBuilder() diff --git a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java index aeec36a941a..2dfb2c92eac 100644 --- a/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java +++ b/jdk/src/share/classes/java/nio/file/attribute/PosixFileAttributeView.java @@ -61,7 +61,7 @@ import java.io.IOException; * Suppose we need to print out the owner and access permissions of a file: *
      *     FileRef file = ...
    - *     PosixFileAttributes attrs = file.newFileAttributeView(PosixFileAttributeView.class)
    + *     PosixFileAttributes attrs = file.getFileAttributeView(PosixFileAttributeView.class)
      *         .readAttributes();
      *     System.out.format("%s %s%n",
      *         attrs.owner().getName(),
    
    From a3af9140c99c387a7c94ddf479ea1f3466f90664 Mon Sep 17 00:00:00 2001
    From: Alan Bateman 
    Date: Tue, 11 Aug 2009 12:49:16 +0100
    Subject: [PATCH 63/70] 6865748: (file) SimpleFileVisitor methods ignore null
     arguments
    
    Reviewed-by: sherman
    ---
     .../java/nio/file/SimpleFileVisitor.java      | 16 +++++++++++
     jdk/test/java/nio/file/Files/Misc.java        | 27 ++++++++++++++++++-
     2 files changed, 42 insertions(+), 1 deletion(-)
    
    diff --git a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java
    index 36852392327..761773513ed 100644
    --- a/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java
    +++ b/jdk/src/share/classes/java/nio/file/SimpleFileVisitor.java
    @@ -47,6 +47,14 @@ public class SimpleFileVisitor implements FileVisitor {
         protected SimpleFileVisitor() {
         }
     
    +    /**
    +     * Throws NullPointerException if obj is null.
    +     */
    +    private static void checkNotNull(Object obj) {
    +        if (obj == null)
    +            throw new NullPointerException();
    +    }
    +
         /**
          * Invoked for a directory before entries in the directory are visited.
          *
    @@ -55,6 +63,7 @@ public class SimpleFileVisitor implements FileVisitor {
          */
         @Override
         public FileVisitResult preVisitDirectory(T dir) {
    +        checkNotNull(dir);
             return FileVisitResult.CONTINUE;
         }
     
    @@ -70,6 +79,8 @@ public class SimpleFileVisitor implements FileVisitor {
          */
         @Override
         public FileVisitResult preVisitDirectoryFailed(T dir, IOException exc) {
    +        checkNotNull(dir);
    +        checkNotNull(exc);
             throw new IOError(exc);
         }
     
    @@ -81,6 +92,8 @@ public class SimpleFileVisitor implements FileVisitor {
          */
         @Override
         public FileVisitResult visitFile(T file, BasicFileAttributes attrs) {
    +        checkNotNull(file);
    +        checkNotNull(attrs);
             return FileVisitResult.CONTINUE;
         }
     
    @@ -96,6 +109,8 @@ public class SimpleFileVisitor implements FileVisitor {
          */
         @Override
         public FileVisitResult visitFileFailed(T file, IOException exc) {
    +        checkNotNull(file);
    +        checkNotNull(exc);
             throw new IOError(exc);
         }
     
    @@ -114,6 +129,7 @@ public class SimpleFileVisitor implements FileVisitor {
          */
         @Override
         public FileVisitResult postVisitDirectory(T dir, IOException exc) {
    +        checkNotNull(dir);
             if (exc != null)
                 throw new IOError(exc);
             return FileVisitResult.CONTINUE;
    diff --git a/jdk/test/java/nio/file/Files/Misc.java b/jdk/test/java/nio/file/Files/Misc.java
    index cd7e17a4bb8..a262274c436 100644
    --- a/jdk/test/java/nio/file/Files/Misc.java
    +++ b/jdk/test/java/nio/file/Files/Misc.java
    @@ -22,13 +22,14 @@
      */
     
     /* @test
    - * @bug 4313887 6838333
    + * @bug 4313887 6838333 6865748
      * @summary Unit test for java.nio.file.Files for miscellenous cases not
      *   covered by other tests
      * @library ..
      */
     
     import java.nio.file.*;
    +import java.nio.file.attribute.Attributes;
     import java.io.IOException;
     import java.util.*;
     
    @@ -113,5 +114,29 @@ public class Misc {
                 npeExpected();
             } catch (NullPointerException e) {
             }
    +
    +        SimpleFileVisitor visitor = new SimpleFileVisitor() { };
    +        boolean ranTheGauntlet = false;
    +        try { visitor.preVisitDirectory(null);
    +        } catch (NullPointerException x0) {
    +        try { visitor.preVisitDirectoryFailed(null, new IOException());
    +        } catch (NullPointerException x1) {
    +        try { visitor.preVisitDirectoryFailed(dir, null);
    +        } catch (NullPointerException x2) {
    +        try { visitor.visitFile(null, Attributes.readBasicFileAttributes(Paths.get(".")));
    +        } catch (NullPointerException x3) {
    +        try {  visitor.visitFile(dir, null);
    +        } catch (NullPointerException x4) {
    +        try { visitor.visitFileFailed(null, new IOException());
    +        } catch (NullPointerException x5) {
    +        try { visitor.visitFileFailed(dir, null);
    +        } catch (NullPointerException x6) {
    +        try { visitor.postVisitDirectory(null, new IOException());
    +        } catch (NullPointerException x7) {
    +            // if we get here then all visit* methods threw NPE as expected
    +            ranTheGauntlet = true;
    +        }}}}}}}}
    +        if (!ranTheGauntlet)
    +            throw new RuntimeException("A visit method did not throw NPE");
         }
     }
    
    From 59d983ade01766714e16106623884ec7129c47cd Mon Sep 17 00:00:00 2001
    From: Vinnie Ryan 
    Date: Tue, 11 Aug 2009 16:52:26 +0100
    Subject: [PATCH 64/70] 6840752: Provide out-of-the-box support for ECC
     algorithms
    
    Reviewed-by: alanb, mullan, wetmore
    ---
     jdk/make/sun/security/Makefile                |    4 +-
     jdk/make/sun/security/ec/FILES_c.gmk          |   54 +
     jdk/make/sun/security/ec/Makefile             |  319 ++
     jdk/make/sun/security/ec/mapfile-vers         |   37 +
     jdk/make/sun/security/other/Makefile          |    3 +-
     .../sun/security/ec/ECDHKeyAgreement.java     |  189 +
     .../sun/security/ec/ECDSASignature.java       |  447 ++
     .../sun/security/ec/ECKeyPairGenerator.java   |  191 +
     .../share/classes/sun/security/ec/SunEC.java  |   65 +
     .../classes/sun/security/ec/SunECEntries.java |  109 +
     jdk/src/share/lib/security/java.security      |   13 +-
     .../share/lib/security/java.security-solaris  |   13 +-
     .../share/lib/security/java.security-windows  |   15 +-
     .../share/native/sun/security/ec/ECC_JNI.cpp  |  418 ++
     jdk/src/share/native/sun/security/ec/ec.c     | 1099 ++++
     jdk/src/share/native/sun/security/ec/ec.h     |   72 +
     jdk/src/share/native/sun/security/ec/ec2.h    |  146 +
     .../share/native/sun/security/ec/ec2_163.c    |  281 +
     .../share/native/sun/security/ec/ec2_193.c    |  298 +
     .../share/native/sun/security/ec/ec2_233.c    |  321 ++
     .../share/native/sun/security/ec/ec2_aff.c    |  368 ++
     .../share/native/sun/security/ec/ec2_mont.c   |  296 +
     jdk/src/share/native/sun/security/ec/ec_naf.c |  123 +
     .../share/native/sun/security/ec/ecc_impl.h   |  278 +
     .../share/native/sun/security/ec/ecdecode.c   |  632 +++
     .../share/native/sun/security/ec/ecl-curve.h  |  710 +++
     .../share/native/sun/security/ec/ecl-exp.h    |  216 +
     .../share/native/sun/security/ec/ecl-priv.h   |  304 +
     jdk/src/share/native/sun/security/ec/ecl.c    |  475 ++
     jdk/src/share/native/sun/security/ec/ecl.h    |  111 +
     .../share/native/sun/security/ec/ecl_curve.c  |  216 +
     jdk/src/share/native/sun/security/ec/ecl_gf.c | 1062 ++++
     .../share/native/sun/security/ec/ecl_mult.c   |  378 ++
     jdk/src/share/native/sun/security/ec/ecp.h    |  160 +
     .../share/native/sun/security/ec/ecp_192.c    |  538 ++
     .../share/native/sun/security/ec/ecp_224.c    |  394 ++
     .../share/native/sun/security/ec/ecp_256.c    |  451 ++
     .../share/native/sun/security/ec/ecp_384.c    |  315 ++
     .../share/native/sun/security/ec/ecp_521.c    |  192 +
     .../share/native/sun/security/ec/ecp_aff.c    |  379 ++
     .../share/native/sun/security/ec/ecp_jac.c    |  575 ++
     jdk/src/share/native/sun/security/ec/ecp_jm.c |  353 ++
     .../share/native/sun/security/ec/ecp_mont.c   |  223 +
     jdk/src/share/native/sun/security/ec/logtab.h |   82 +
     .../native/sun/security/ec/mp_gf2m-priv.h     |  122 +
     .../share/native/sun/security/ec/mp_gf2m.c    |  624 +++
     .../share/native/sun/security/ec/mp_gf2m.h    |   83 +
     .../share/native/sun/security/ec/mpi-config.h |  130 +
     .../share/native/sun/security/ec/mpi-priv.h   |  340 ++
     jdk/src/share/native/sun/security/ec/mpi.c    | 4886 +++++++++++++++++
     jdk/src/share/native/sun/security/ec/mpi.h    |  409 ++
     .../share/native/sun/security/ec/mplogic.c    |  242 +
     .../share/native/sun/security/ec/mplogic.h    |  105 +
     .../share/native/sun/security/ec/mpmontg.c    |  199 +
     .../share/native/sun/security/ec/mpprime.h    |   89 +
     jdk/src/share/native/sun/security/ec/oid.c    |  473 ++
     .../share/native/sun/security/ec/secitem.c    |  199 +
     .../share/native/sun/security/ec/secoidt.h    |  103 +
     jdk/test/sun/security/ec/TestEC.java          |   66 +
     jdk/test/sun/security/ec/p12passwords.txt     |   18 +
     .../ec/pkcs12/secp256r1server-secp384r1ca.p12 |  Bin 0 -> 1273 bytes
     .../ec/pkcs12/sect193r1server-rsa1024ca.p12   |  Bin 0 -> 1252 bytes
     62 files changed, 20990 insertions(+), 23 deletions(-)
     create mode 100644 jdk/make/sun/security/ec/FILES_c.gmk
     create mode 100644 jdk/make/sun/security/ec/Makefile
     create mode 100644 jdk/make/sun/security/ec/mapfile-vers
     create mode 100644 jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
     create mode 100644 jdk/src/share/classes/sun/security/ec/ECDSASignature.java
     create mode 100644 jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
     create mode 100644 jdk/src/share/classes/sun/security/ec/SunEC.java
     create mode 100644 jdk/src/share/classes/sun/security/ec/SunECEntries.java
     create mode 100644 jdk/src/share/native/sun/security/ec/ECC_JNI.cpp
     create mode 100644 jdk/src/share/native/sun/security/ec/ec.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ec.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ec2.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ec2_163.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ec2_193.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ec2_233.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ec2_aff.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ec2_mont.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ec_naf.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecc_impl.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ecdecode.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl-curve.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl-exp.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl-priv.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl_curve.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl_gf.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecl_mult.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp.h
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_192.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_224.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_256.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_384.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_521.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_aff.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_jac.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_jm.c
     create mode 100644 jdk/src/share/native/sun/security/ec/ecp_mont.c
     create mode 100644 jdk/src/share/native/sun/security/ec/logtab.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mp_gf2m-priv.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mp_gf2m.c
     create mode 100644 jdk/src/share/native/sun/security/ec/mp_gf2m.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mpi-config.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mpi-priv.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mpi.c
     create mode 100644 jdk/src/share/native/sun/security/ec/mpi.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mplogic.c
     create mode 100644 jdk/src/share/native/sun/security/ec/mplogic.h
     create mode 100644 jdk/src/share/native/sun/security/ec/mpmontg.c
     create mode 100644 jdk/src/share/native/sun/security/ec/mpprime.h
     create mode 100644 jdk/src/share/native/sun/security/ec/oid.c
     create mode 100644 jdk/src/share/native/sun/security/ec/secitem.c
     create mode 100644 jdk/src/share/native/sun/security/ec/secoidt.h
     create mode 100644 jdk/test/sun/security/ec/TestEC.java
     create mode 100644 jdk/test/sun/security/ec/p12passwords.txt
     create mode 100644 jdk/test/sun/security/ec/pkcs12/secp256r1server-secp384r1ca.p12
     create mode 100644 jdk/test/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12
    
    diff --git a/jdk/make/sun/security/Makefile b/jdk/make/sun/security/Makefile
    index 13394fc2100..2b7cc6b2ab3 100644
    --- a/jdk/make/sun/security/Makefile
    +++ b/jdk/make/sun/security/Makefile
    @@ -1,5 +1,5 @@
     #
    -# Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
    +# Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -60,7 +60,7 @@ ifeq ($(PLATFORM), windows)
       endif
     endif
     
    -SUBDIRS = other action util tools jgss krb5 smartcardio $(PKCS11) \
    +SUBDIRS = ec other action util tools jgss krb5 smartcardio $(PKCS11) \
               $(JGSS_WRAPPER) $(MSCAPI)
     
     all build clean clobber::
    diff --git a/jdk/make/sun/security/ec/FILES_c.gmk b/jdk/make/sun/security/ec/FILES_c.gmk
    new file mode 100644
    index 00000000000..8a1bd099b38
    --- /dev/null
    +++ b/jdk/make/sun/security/ec/FILES_c.gmk
    @@ -0,0 +1,54 @@
    +#
    +# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    +#
    +# This code is free software; you can redistribute it and/or modify it
    +# under the terms of the GNU General Public License version 2 only, as
    +# published by the Free Software Foundation.  Sun designates this
    +# particular file as subject to the "Classpath" exception as provided
    +# by Sun in the LICENSE file that accompanied this code.
    +#
    +# This code is distributed in the hope that it will be useful, but WITHOUT
    +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    +# version 2 for more details (a copy is included in the LICENSE file that
    +# accompanied this code).
    +#
    +# You should have received a copy of the GNU General Public License version
    +# 2 along with this work; if not, write to the Free Software Foundation,
    +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    +#
    +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    +# CA 95054 USA or visit www.sun.com if you need additional information or
    +# have any questions.
    +#
    +
    +FILES_c = \
    +	ec.c \
    +	ec2_163.c \
    +	ec2_193.c \
    +	ec2_233.c \
    +	ec2_aff.c \
    +	ec2_mont.c \
    +	ecdecode.c \
    +	ecl.c \
    +	ecl_curve.c \
    +	ecl_gf.c \
    +	ecl_mult.c \
    +	ec_naf.c \
    +	ecp_192.c \
    +	ecp_224.c \
    +	ecp_256.c \
    +	ecp_384.c \
    +	ecp_521.c \
    +	ecp_aff.c \
    +	ecp_jac.c \
    +	ecp_jm.c \
    +	ecp_mont.c \
    +	mp_gf2m.c \
    +	mpi.c \
    +	mplogic.c \
    +	mpmontg.c \
    +	oid.c \
    +	secitem.c
    +
    diff --git a/jdk/make/sun/security/ec/Makefile b/jdk/make/sun/security/ec/Makefile
    new file mode 100644
    index 00000000000..297a2deab08
    --- /dev/null
    +++ b/jdk/make/sun/security/ec/Makefile
    @@ -0,0 +1,319 @@
    +#
    +# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    +#
    +# This code is free software; you can redistribute it and/or modify it
    +# under the terms of the GNU General Public License version 2 only, as
    +# published by the Free Software Foundation.  Sun designates this
    +# particular file as subject to the "Classpath" exception as provided
    +# by Sun in the LICENSE file that accompanied this code.
    +#
    +# This code is distributed in the hope that it will be useful, but WITHOUT
    +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    +# version 2 for more details (a copy is included in the LICENSE file that
    +# accompanied this code).
    +#
    +# You should have received a copy of the GNU General Public License version
    +# 2 along with this work; if not, write to the Free Software Foundation,
    +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    +#
    +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    +# CA 95054 USA or visit www.sun.com if you need additional information or
    +# have any questions.
    +#
    +
    +#
    +# Makefile for building sunec.jar and sunecc native library.
    +#
    +# This file was derived from make/com/sun/crypto/provider/Makefile.
    +#
    +
    +#
    +# (The terms "OpenJDK" and "JDK" below refer to OpenJDK and Sun JDK builds
    +# respectively.)
    +#
    +# JCE builds are very different between OpenJDK and JDK.  The OpenJDK JCE
    +# jar files do not require signing, but those for JDK do.  If an unsigned
    +# jar file is installed into JDK, things will break when the crypto
    +# routines are called.
    +#
    +# This Makefile does the "real" build of the JCE files.  For OpenJDK,
    +# the jar files built here are installed directly into the OpenJDK.
    +#
    +# For JDK, the binaries use pre-built/pre-signed binary files stored in
    +# the closed workspace that are not shipped in the OpenJDK workspaces.
    +# We still build the JDK files here to verify the files compile, and in
    +# preparation for possible signing.  Developers working on JCE in JDK
    +# must sign the JCE files before testing.  The JCE signing key is kept
    +# separate from the JDK workspace to prevent its disclosure.
    +#
    +# SPECIAL NOTE TO JCE/JDK developers:  The source files must eventually
    +# be built, signed, and then the resulting jar files MUST BE CHECKED
    +# INTO THE CLOSED PART OF THE WORKSPACE*.  This separate step *MUST NOT
    +# BE FORGOTTEN*, otherwise a bug fixed in the source code will not be
    +# reflected in the shipped binaries.  The "release" target should be
    +# used to generate the required files.
    +#
    +# There are a number of targets to help both JDK/OpenJDK developers.
    +#
    +# Main Targets (JDK/OPENJDK):
    +#
    +#     all/clobber/clean		The usual, plus the native libraries.
    +#				    If OpenJDK, installs sunec.jar.
    +#				    If JDK, installs prebuilt
    +#				    sunec.jar.
    +#
    +#     jar			Builds/installs sunec.jar
    +#				    If OpenJDK, does not sign.
    +#				    If JDK, tries to sign.
    +#
    +# Other lesser-used Targets (JDK/OPENJDK):
    +#
    +#     build-jar			Builds sunec.jar
    +#				    (does not sign/install)
    +#
    +#     install-jar		Alias for "jar" above.
    +#
    +# Other targets (JDK only):
    +#
    +#     sign			Alias for sign-jar
    +#	  sign-jar		Builds/signs sunec.jar (no install)
    +#
    +#     release			Builds all targets in preparation
    +#				for workspace integration.
    +#
    +#     install-prebuilt		Installs the pre-built jar files
    +#
    +# This makefile was written to support parallel target execution.
    +#
    +
    +BUILDDIR = ../../..
    +PACKAGE = sun.security.ec
    +PRODUCT = sun
    +
    +#
    +# The following is for when we need to do postprocessing
    +# (signing) against a read-only build.  If the OUTPUTDIR
    +# isn't writable, the build currently crashes out.
    +#
    +ifndef OPENJDK
    +  ifdef ALT_JCE_BUILD_DIR
    +    # =====================================================
    +    # Where to place the output, in case we're building from a read-only
    +    # build area.  (e.g. a release engineering build.)
    +    JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
    +    IGNORE_WRITABLE_OUTPUTDIR_TEST=true
    +  else
    +    JCE_BUILD_DIR=${TEMPDIR}
    +  endif
    +endif
    +
    +include $(BUILDDIR)/common/Defs.gmk
    +
    +#
    +# Location for the newly built classfiles.
    +#
    +CLASSDESTDIR = $(TEMPDIR)/classes
    +
    +#
    +# Java files
    +#
    +AUTO_FILES_JAVA_DIRS = $(PKGDIR)
    +
    +include $(BUILDDIR)/common/Classes.gmk
    +
    +#
    +# Some licensees do not get the native ECC sources, but we still need to
    +# be able to build "all" for them.  Check here to see if the sources are
    +# available.  If not, then skip them.
    +#
    +
    +NATIVE_ECC_AVAILABLE := $(shell \
    +    if [ -d $(SHARE_SRC)/native/$(PKGDIR) ] ; then \
    +	$(ECHO) true; \
    +    else \
    +	$(ECHO) false; \
    +    fi)
    +
    +ifeq ($(NATIVE_ECC_AVAILABLE), true)
    +
    +  LIBRARY = sunecc
    +
    +  #
    +  # Java files that define native methods
    +  #
    +  FILES_export = \
    +      $(PKGDIR)/ECDHKeyAgreement.java \
    +      $(PKGDIR)/ECDSASignature.java \
    +      $(PKGDIR)/ECKeyPairGenerator.java
    +
    +  JAVAHFLAGS += -classpath $(CLASSDESTDIR)
    +
    +  #
    +  # C and C++ files
    +  #
    +  include FILES_c.gmk
    +
    +  FILES_cpp = ECC_JNI.cpp
    +
    +  CPLUSPLUSLIBRARY=true
    +
    +  FILES_m = mapfile-vers
    +
    +  #
    +  # Find native code
    +  #
    +  vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR)
    +
    +  vpath %.c $(SHARE_SRC)/native/$(PKGDIR)
    +
    +  #
    +  # Find include files
    +  #
    +  OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)
    +
    +  #
    +  # Compiler flags
    +  #
    +  OTHER_CFLAGS += -DMP_API_COMPATIBLE -DNSS_ECC_MORE_THAN_SUITE_B
    +
    +  #
    +  # Libraries to link
    +  #
    +  ifeq ($(PLATFORM), windows)
    +    OTHER_LDLIBS += $(JVMLIB)
    +  else
    +    OTHER_LDLIBS = -ldl $(JVMLIB) $(LIBCXX)
    +  endif
    +
    +  include $(BUILDDIR)/common/Mapfile-vers.gmk
    +
    +  include $(BUILDDIR)/common/Library.gmk
    +
    +endif # NATIVE_ECC_AVAILABLE
    +
    +#
    +# We use a variety of subdirectories in the $(TEMPDIR) depending on what
    +# part of the build we're doing.  Both OPENJDK/JDK builds are initially
    +# done in the unsigned area.  When files are signed in JDK,
    +# they will be placed in the appropriate area.
    +#
    +UNSIGNED_DIR = $(TEMPDIR)/unsigned
    +
    +include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
    +
    +#
    +# Rules
    +#
    +
    +ifdef OPENJDK
    +all: build-jar install-jar
    +else
    +all: build-jar install-prebuilt
    +	$(build-warning)
    +endif
    +
    +
    +# =====================================================
    +# Build the unsigned sunec.jar file.
    +#
    +
    +JAR_DESTFILE = $(EXTDIR)/sunec.jar
    +
    +#
    +# Since the -C option to jar is used below, each directory entry must be
    +# preceded with the appropriate directory to "cd" into.
    +#
    +JAR_DIRS = $(patsubst %, -C $(CLASSDESTDIR) %, $(AUTO_FILES_JAVA_DIRS))
    +
    +build-jar: $(UNSIGNED_DIR)/sunec.jar
    +
    +#
    +# Build sunec.jar.
    +#
    +$(UNSIGNED_DIR)/sunec.jar: build
    +	$(prep-target)
    +	$(BOOT_JAR_CMD) cf $@ $(JAR_DIRS) \
    +	    $(BOOT_JAR_JFLAGS)
    +	@$(java-vm-cleanup)
    +
    +
    +ifndef OPENJDK
    +# =====================================================
    +# Sign the provider jar file.  Not needed for OpenJDK.
    +#
    +
    +SIGNED_DIR = $(JCE_BUILD_DIR)/signed
    +
    +sign: sign-jar
    +
    +sign-jar: $(SIGNED_DIR)/sunec.jar
    +
    +ifndef ALT_JCE_BUILD_DIR
    +$(SIGNED_DIR)/sunec.jar: $(UNSIGNED_DIR)/sunec.jar
    +else
    +#
    +# We have to remove the build dependency, otherwise, we'll try to rebuild it
    +# which we can't do on a read-only filesystem.
    +#
    +$(SIGNED_DIR)/sunec.jar:
    +	@if [ ! -r $(UNSIGNED_DIR)/sunec.jar ] ; then \
    +	    $(ECHO) "Couldn't find $(UNSIGNED_DIR)/sunec.jar"; \
    +	    exit 1; \
    +	fi
    +endif
    +	$(call sign-file, $(UNSIGNED_DIR)/sunec.jar)
    +
    +
    +# =====================================================
    +# Create the Release Engineering files.  Signed builds, etc.
    +#
    +
    +release: $(SIGNED_DIR)/sunec.jar
    +	$(RM) $(JCE_BUILD_DIR)/release/sunec.jar
    +	$(MKDIR) -p $(JCE_BUILD_DIR)/release
    +	$(CP) $(SIGNED_DIR)/sunec.jar $(JCE_BUILD_DIR)/release
    +	$(release-warning)
    +
    +endif # OPENJDK
    +
    +
    +# =====================================================
    +# Install routines.
    +#
    +
    +#
    +# Install sunec.jar, depending on which type is requested.
    +#
    +install-jar jar: $(JAR_DESTFILE)
    +ifndef OPENJDK
    +	$(release-warning)
    +endif
    +
    +ifdef OPENJDK
    +$(JAR_DESTFILE): $(UNSIGNED_DIR)/sunec.jar
    +else
    +$(JAR_DESTFILE): $(SIGNED_DIR)/sunec.jar
    +endif
    +	$(install-file)
    +
    +ifndef OPENJDK
    +install-prebuilt:
    +	@$(ECHO) "\n>>>Installing prebuilt SunEC provider..."
    +	$(RM) $(JAR_DESTFILE)
    +	$(CP) $(PREBUILT_DIR)/ec/sunec.jar $(JAR_DESTFILE)
    +endif
    +
    +
    +# =====================================================
    +# Support routines.
    +#
    +
    +clobber clean::
    +	$(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
    +
    +.PHONY: build-jar jar install-jar
    +ifndef OPENJDK
    +.PHONY: sign sign-jar release install-prebuilt
    +endif
    diff --git a/jdk/make/sun/security/ec/mapfile-vers b/jdk/make/sun/security/ec/mapfile-vers
    new file mode 100644
    index 00000000000..2bda0206608
    --- /dev/null
    +++ b/jdk/make/sun/security/ec/mapfile-vers
    @@ -0,0 +1,37 @@
    +#
    +# Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    +#
    +# This code is free software; you can redistribute it and/or modify it
    +# under the terms of the GNU General Public License version 2 only, as
    +# published by the Free Software Foundation.  Sun designates this
    +# particular file as subject to the "Classpath" exception as provided
    +# by Sun in the LICENSE file that accompanied this code.
    +#
    +# This code is distributed in the hope that it will be useful, but WITHOUT
    +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    +# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    +# version 2 for more details (a copy is included in the LICENSE file that
    +# accompanied this code).
    +#
    +# You should have received a copy of the GNU General Public License version
    +# 2 along with this work; if not, write to the Free Software Foundation,
    +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    +#
    +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    +# CA 95054 USA or visit www.sun.com if you need additional information or
    +# have any questions.
    +#
    +
    +# Define public interface.
    +
    +SUNWprivate_1.1 {
    +        global:
    +                Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair;
    +                Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes;
    +		Java_sun_security_ec_ECDSASignature_signDigest;
    +		Java_sun_security_ec_ECDSASignature_verifySignedDigest;
    +		Java_sun_security_ec_ECDHKeyAgreement_deriveKey;
    +        local:
    +                *;
    +};
    diff --git a/jdk/make/sun/security/other/Makefile b/jdk/make/sun/security/other/Makefile
    index 8fea7ce903f..3f120fa473f 100644
    --- a/jdk/make/sun/security/other/Makefile
    +++ b/jdk/make/sun/security/other/Makefile
    @@ -1,5 +1,5 @@
     #
    -# Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
    +# Copyright 1996-2009 Sun Microsystems, Inc.  All Rights Reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -33,7 +33,6 @@ include $(BUILDDIR)/common/Defs.gmk
     #
     AUTO_FILES_JAVA_DIRS = \
         sun/security/acl \
    -    sun/security/ec \
         sun/security/jca \
         sun/security/pkcs \
         sun/security/pkcs12 \
    diff --git a/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java b/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
    new file mode 100644
    index 00000000000..8a61a7b1193
    --- /dev/null
    +++ b/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
    @@ -0,0 +1,189 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Sun designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Sun in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +package sun.security.ec;
    +
    +import java.security.*;
    +import java.security.interfaces.*;
    +import java.security.spec.*;
    +
    +import javax.crypto.*;
    +import javax.crypto.spec.*;
    +
    +/**
    + * KeyAgreement implementation for ECDH.
    + *
    + * @since   1.7
    + */
    +public final class ECDHKeyAgreement extends KeyAgreementSpi {
    +
    +    // flag indicating whether the native ECC implementation is present
    +    private static boolean implementationPresent = true;
    +    static {
    +        try {
    +            AccessController.doPrivileged(new PrivilegedAction() {
    +                public Void run() {
    +                    System.loadLibrary("sunecc");
    +                    return null;
    +                }
    +            });
    +        } catch (UnsatisfiedLinkError e) {
    +            implementationPresent = false;
    +        }
    +    }
    +
    +    // private key, if initialized
    +    private ECPrivateKey privateKey;
    +
    +    // encoded public point, non-null between doPhase() & generateSecret() only
    +    private byte[] publicValue;
    +
    +    // length of the secret to be derived
    +    private int secretLen;
    +
    +    /**
    +     * Constructs a new ECDHKeyAgreement.
    +     *
    +     * @exception ProviderException if the native ECC library is unavailable.
    +     */
    +    public ECDHKeyAgreement() {
    +        if (!implementationPresent) {
    +            throw new ProviderException("ECDH implementation is not available");
    +        }
    +    }
    +
    +    // see JCE spec
    +    protected void engineInit(Key key, SecureRandom random)
    +            throws InvalidKeyException {
    +        if (!(key instanceof PrivateKey)) {
    +            throw new InvalidKeyException
    +                        ("Key must be instance of PrivateKey");
    +        }
    +        privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
    +        publicValue = null;
    +    }
    +
    +    // see JCE spec
    +    protected void engineInit(Key key, AlgorithmParameterSpec params,
    +            SecureRandom random) throws InvalidKeyException,
    +            InvalidAlgorithmParameterException {
    +        if (params != null) {
    +            throw new InvalidAlgorithmParameterException
    +                        ("Parameters not supported");
    +        }
    +        engineInit(key, random);
    +    }
    +
    +    // see JCE spec
    +    protected Key engineDoPhase(Key key, boolean lastPhase)
    +            throws InvalidKeyException, IllegalStateException {
    +        if (privateKey == null) {
    +            throw new IllegalStateException("Not initialized");
    +        }
    +        if (publicValue != null) {
    +            throw new IllegalStateException("Phase already executed");
    +        }
    +        if (!lastPhase) {
    +            throw new IllegalStateException
    +                ("Only two party agreement supported, lastPhase must be true");
    +        }
    +        if (!(key instanceof ECPublicKey)) {
    +            throw new InvalidKeyException
    +                ("Key must be a PublicKey with algorithm EC");
    +        }
    +
    +        ECPublicKey ecKey = (ECPublicKey)key;
    +        ECParameterSpec params = ecKey.getParams();
    +
    +        if (ecKey instanceof ECPublicKeyImpl) {
    +            publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue();
    +        } else { // instanceof ECPublicKey
    +            publicValue =
    +                ECParameters.encodePoint(ecKey.getW(), params.getCurve());
    +        }
    +        int keyLenBits = params.getCurve().getField().getFieldSize();
    +        secretLen = (keyLenBits + 7) >> 3;
    +
    +        return null;
    +    }
    +
    +    // see JCE spec
    +    protected byte[] engineGenerateSecret() throws IllegalStateException {
    +        if ((privateKey == null) || (publicValue == null)) {
    +            throw new IllegalStateException("Not initialized correctly");
    +        }
    +
    +        byte[] s = privateKey.getS().toByteArray();
    +        byte[] encodedParams =
    +            ECParameters.encodeParameters(privateKey.getParams()); // DER OID
    +
    +        try {
    +
    +            return deriveKey(s, publicValue, encodedParams);
    +
    +        } catch (GeneralSecurityException e) {
    +            throw new ProviderException("Could not derive key", e);
    +        }
    +
    +    }
    +
    +    // see JCE spec
    +    protected int engineGenerateSecret(byte[] sharedSecret, int
    +            offset) throws IllegalStateException, ShortBufferException {
    +        if (offset + secretLen > sharedSecret.length) {
    +            throw new ShortBufferException("Need " + secretLen
    +                + " bytes, only " + (sharedSecret.length - offset) + " available");
    +        }
    +        byte[] secret = engineGenerateSecret();
    +        System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
    +        return secret.length;
    +    }
    +
    +    // see JCE spec
    +    protected SecretKey engineGenerateSecret(String algorithm)
    +            throws IllegalStateException, NoSuchAlgorithmException,
    +            InvalidKeyException {
    +        if (algorithm == null) {
    +            throw new NoSuchAlgorithmException("Algorithm must not be null");
    +        }
    +        if (!(algorithm.equals("TlsPremasterSecret"))) {
    +            throw new NoSuchAlgorithmException
    +                ("Only supported for algorithm TlsPremasterSecret");
    +        }
    +        return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
    +    }
    +
    +    /**
    +     * Generates a secret key using the public and private keys.
    +     *
    +     * @param s the private key's S value.
    +     * @param w the public key's W point (in uncompressed form).
    +     * @param encodedParams the curve's DER encoded object identifier.
    +     *
    +     * @return byte[] the secret key.
    +     */
    +    private static native byte[] deriveKey(byte[] s, byte[] w,
    +        byte[] encodedParams) throws GeneralSecurityException;
    +}
    diff --git a/jdk/src/share/classes/sun/security/ec/ECDSASignature.java b/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
    new file mode 100644
    index 00000000000..b2bf8936c15
    --- /dev/null
    +++ b/jdk/src/share/classes/sun/security/ec/ECDSASignature.java
    @@ -0,0 +1,447 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Sun designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Sun in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +package sun.security.ec;
    +
    +import java.io.IOException;
    +import java.nio.ByteBuffer;
    +import java.math.BigInteger;
    +import java.util.Arrays;
    +
    +import java.security.*;
    +import java.security.interfaces.*;
    +import java.security.spec.*;
    +
    +import sun.security.jca.JCAUtil;
    +import sun.security.util.*;
    +import sun.security.x509.AlgorithmId;
    +
    +/**
    + * ECDSA signature implementation. This class currently supports the
    + * following algorithm names:
    + *
    + *   . "NONEwithECDSA"
    + *   . "SHA1withECDSA"
    + *   . "SHA256withECDSA"
    + *   . "SHA384withECDSA"
    + *   . "SHA512withECDSA"
    + *
    + * @since   1.7
    + */
    +abstract class ECDSASignature extends SignatureSpi {
    +
    +    // flag indicating whether the native ECC implementation is present
    +    private static boolean implementationPresent = true;
    +    static {
    +        try {
    +            AccessController.doPrivileged(new PrivilegedAction() {
    +                public Void run() {
    +                    System.loadLibrary("sunecc");
    +                    return null;
    +                }
    +            });
    +        } catch (UnsatisfiedLinkError e) {
    +            implementationPresent = false;
    +        }
    +    }
    +
    +    // message digest implementation we use
    +    private final MessageDigest messageDigest;
    +
    +    // supplied entropy
    +    private SecureRandom random;
    +
    +    // flag indicating whether the digest has been reset
    +    private boolean needsReset;
    +
    +    // private key, if initialized for signing
    +    private ECPrivateKey privateKey;
    +
    +    // public key, if initialized for verifying
    +    private ECPublicKey publicKey;
    +
    +    /**
    +     * Constructs a new ECDSASignature. Used by Raw subclass.
    +     *
    +     * @exception ProviderException if the native ECC library is unavailable.
    +     */
    +    ECDSASignature() {
    +        if (!implementationPresent) {
    +            throw new
    +                ProviderException("ECDSA implementation is not available");
    +        }
    +        messageDigest = null;
    +    }
    +
    +    /**
    +     * Constructs a new ECDSASignature. Used by subclasses.
    +     *
    +     * @exception ProviderException if the native ECC library is unavailable.
    +     */
    +    ECDSASignature(String digestName) {
    +        if (!implementationPresent) {
    +            throw new
    +                ProviderException("ECDSA implementation is not available");
    +        }
    +
    +        try {
    +            messageDigest = MessageDigest.getInstance(digestName);
    +        } catch (NoSuchAlgorithmException e) {
    +            throw new ProviderException(e);
    +        }
    +        needsReset = false;
    +    }
    +
    +    // Nested class for NONEwithECDSA signatures
    +    public static final class Raw extends ECDSASignature {
    +
    +        // the longest supported digest is 512 bits (SHA-512)
    +        private static final int RAW_ECDSA_MAX = 64;
    +
    +        private final byte[] precomputedDigest;
    +        private int offset = 0;
    +
    +        public Raw() {
    +            precomputedDigest = new byte[RAW_ECDSA_MAX];
    +        }
    +
    +        // Stores the precomputed message digest value.
    +        @Override
    +        protected void engineUpdate(byte b) throws SignatureException {
    +            if (offset >= precomputedDigest.length) {
    +                offset = RAW_ECDSA_MAX + 1;
    +                return;
    +            }
    +            precomputedDigest[offset++] = b;
    +        }
    +
    +        // Stores the precomputed message digest value.
    +        @Override
    +        protected void engineUpdate(byte[] b, int off, int len)
    +                throws SignatureException {
    +            if (offset >= precomputedDigest.length) {
    +                offset = RAW_ECDSA_MAX + 1;
    +                return;
    +            }
    +            System.arraycopy(b, off, precomputedDigest, offset, len);
    +            offset += len;
    +        }
    +
    +        // Stores the precomputed message digest value.
    +        @Override
    +        protected void engineUpdate(ByteBuffer byteBuffer) {
    +            int len = byteBuffer.remaining();
    +            if (len <= 0) {
    +                return;
    +            }
    +            if (offset + len >= precomputedDigest.length) {
    +                offset = RAW_ECDSA_MAX + 1;
    +                return;
    +            }
    +            byteBuffer.get(precomputedDigest, offset, len);
    +            offset += len;
    +        }
    +
    +        @Override
    +        protected void resetDigest(){
    +            offset = 0;
    +        }
    +
    +        // Returns the precomputed message digest value.
    +        @Override
    +        protected byte[] getDigestValue() throws SignatureException {
    +            if (offset > RAW_ECDSA_MAX) {
    +                throw new SignatureException("Message digest is too long");
    +
    +            }
    +            byte[] result = new byte[offset];
    +            System.arraycopy(precomputedDigest, 0, result, 0, offset);
    +            offset = 0;
    +
    +            return result;
    +        }
    +    }
    +
    +    // Nested class for SHA1withECDSA signatures
    +    public static final class SHA1 extends ECDSASignature {
    +        public SHA1() {
    +            super("SHA1");
    +        }
    +    }
    +
    +    // Nested class for SHA256withECDSA signatures
    +    public static final class SHA256 extends ECDSASignature {
    +        public SHA256() {
    +            super("SHA-256");
    +        }
    +    }
    +
    +    // Nested class for SHA384withECDSA signatures
    +    public static final class SHA384 extends ECDSASignature {
    +        public SHA384() {
    +            super("SHA-384");
    +        }
    +    }
    +
    +    // Nested class for SHA512withECDSA signatures
    +    public static final class SHA512 extends ECDSASignature {
    +        public SHA512() {
    +            super("SHA-512");
    +        }
    +    }
    +
    +    // initialize for verification. See JCA doc
    +    @Override
    +    protected void engineInitVerify(PublicKey publicKey)
    +            throws InvalidKeyException {
    +        this.publicKey = (ECPublicKey) ECKeyFactory.toECKey(publicKey);
    +
    +        // Should check that the supplied key is appropriate for signature
    +        // algorithm (e.g. P-256 for SHA256withECDSA)
    +        this.privateKey = null;
    +        resetDigest();
    +    }
    +
    +    // initialize for signing. See JCA doc
    +    @Override
    +    protected void engineInitSign(PrivateKey privateKey)
    +            throws InvalidKeyException {
    +        engineInitSign(privateKey, null);
    +    }
    +
    +    // initialize for signing. See JCA doc
    +    @Override
    +    protected void engineInitSign(PrivateKey privateKey, SecureRandom random)
    +            throws InvalidKeyException {
    +        this.privateKey = (ECPrivateKey) ECKeyFactory.toECKey(privateKey);
    +
    +        // Should check that the supplied key is appropriate for signature
    +        // algorithm (e.g. P-256 for SHA256withECDSA)
    +        this.publicKey = null;
    +        this.random = random;
    +        resetDigest();
    +    }
    +
    +    /**
    +     * Resets the message digest if needed.
    +     */
    +    protected void resetDigest() {
    +        if (needsReset) {
    +            if (messageDigest != null) {
    +                messageDigest.reset();
    +            }
    +            needsReset = false;
    +        }
    +    }
    +
    +    /**
    +     * Returns the message digest value.
    +     */
    +    protected byte[] getDigestValue() throws SignatureException {
    +        needsReset = false;
    +        return messageDigest.digest();
    +    }
    +
    +    // update the signature with the plaintext data. See JCA doc
    +    @Override
    +    protected void engineUpdate(byte b) throws SignatureException {
    +        messageDigest.update(b);
    +        needsReset = true;
    +    }
    +
    +    // update the signature with the plaintext data. See JCA doc
    +    @Override
    +    protected void engineUpdate(byte[] b, int off, int len)
    +            throws SignatureException {
    +        messageDigest.update(b, off, len);
    +        needsReset = true;
    +    }
    +
    +    // update the signature with the plaintext data. See JCA doc
    +    @Override
    +    protected void engineUpdate(ByteBuffer byteBuffer) {
    +        int len = byteBuffer.remaining();
    +        if (len <= 0) {
    +            return;
    +        }
    +
    +        messageDigest.update(byteBuffer);
    +        needsReset = true;
    +    }
    +
    +    // sign the data and return the signature. See JCA doc
    +    @Override
    +    protected byte[] engineSign() throws SignatureException {
    +        byte[] s = privateKey.getS().toByteArray();
    +        ECParameterSpec params = privateKey.getParams();
    +        byte[] encodedParams = ECParameters.encodeParameters(params); // DER OID
    +        int keySize = params.getCurve().getField().getFieldSize();
    +
    +        // seed is twice the key size (in bytes)
    +        byte[] seed = new byte[((keySize + 7) >> 3) * 2];
    +        if (random == null) {
    +            random = JCAUtil.getSecureRandom();
    +        }
    +        random.nextBytes(seed);
    +
    +        try {
    +
    +            return encodeSignature(
    +                signDigest(getDigestValue(), s, encodedParams, seed));
    +
    +        } catch (GeneralSecurityException e) {
    +            throw new SignatureException("Could not sign data", e);
    +        }
    +    }
    +
    +    // verify the data and return the result. See JCA doc
    +    @Override
    +    protected boolean engineVerify(byte[] signature) throws SignatureException {
    +
    +        byte[] w;
    +        ECParameterSpec params = publicKey.getParams();
    +        byte[] encodedParams = ECParameters.encodeParameters(params); // DER OID
    +
    +        if (publicKey instanceof ECPublicKeyImpl) {
    +            w = ((ECPublicKeyImpl)publicKey).getEncodedPublicValue();
    +        } else { // instanceof ECPublicKey
    +            w = ECParameters.encodePoint(publicKey.getW(), params.getCurve());
    +        }
    +
    +        try {
    +
    +            return verifySignedDigest(
    +                decodeSignature(signature), getDigestValue(), w, encodedParams);
    +
    +        } catch (GeneralSecurityException e) {
    +            throw new SignatureException("Could not verify signature", e);
    +        }
    +    }
    +
    +    // set parameter, not supported. See JCA doc
    +    @Override
    +    protected void engineSetParameter(String param, Object value)
    +            throws InvalidParameterException {
    +        throw new UnsupportedOperationException("setParameter() not supported");
    +    }
    +
    +    // get parameter, not supported. See JCA doc
    +    @Override
    +    protected Object engineGetParameter(String param)
    +            throws InvalidParameterException {
    +        throw new UnsupportedOperationException("getParameter() not supported");
    +    }
    +
    +    // Convert the concatenation of R and S into their DER encoding
    +    private byte[] encodeSignature(byte[] signature) throws SignatureException {
    +        try {
    +
    +            int n = signature.length >> 1;
    +            byte[] bytes = new byte[n];
    +            System.arraycopy(signature, 0, bytes, 0, n);
    +            BigInteger r = new BigInteger(1, bytes);
    +            System.arraycopy(signature, n, bytes, 0, n);
    +            BigInteger s = new BigInteger(1, bytes);
    +
    +            DerOutputStream out = new DerOutputStream(signature.length + 10);
    +            out.putInteger(r);
    +            out.putInteger(s);
    +            DerValue result =
    +                new DerValue(DerValue.tag_Sequence, out.toByteArray());
    +
    +            return result.toByteArray();
    +
    +        } catch (Exception e) {
    +            throw new SignatureException("Could not encode signature", e);
    +        }
    +    }
    +
    +    // Convert the DER encoding of R and S into a concatenation of R and S
    +    private byte[] decodeSignature(byte[] signature) throws SignatureException {
    +
    +        try {
    +            DerInputStream in = new DerInputStream(signature);
    +            DerValue[] values = in.getSequence(2);
    +            BigInteger r = values[0].getPositiveBigInteger();
    +            BigInteger s = values[1].getPositiveBigInteger();
    +            // trim leading zeroes
    +            byte[] rBytes = trimZeroes(r.toByteArray());
    +            byte[] sBytes = trimZeroes(s.toByteArray());
    +            int k = Math.max(rBytes.length, sBytes.length);
    +            // r and s each occupy half the array
    +            byte[] result = new byte[k << 1];
    +            System.arraycopy(rBytes, 0, result, k - rBytes.length,
    +                rBytes.length);
    +            System.arraycopy(sBytes, 0, result, result.length - sBytes.length,
    +                sBytes.length);
    +            return result;
    +
    +        } catch (Exception e) {
    +            throw new SignatureException("Could not decode signature", e);
    +        }
    +    }
    +
    +    // trim leading (most significant) zeroes from the result
    +    private static byte[] trimZeroes(byte[] b) {
    +        int i = 0;
    +        while ((i < b.length - 1) && (b[i] == 0)) {
    +            i++;
    +        }
    +        if (i == 0) {
    +            return b;
    +        }
    +        byte[] t = new byte[b.length - i];
    +        System.arraycopy(b, i, t, 0, t.length);
    +        return t;
    +    }
    +
    +    /**
    +     * Signs the digest using the private key.
    +     *
    +     * @param digest the digest to be signed.
    +     * @param s the private key's S value.
    +     * @param encodedParams the curve's DER encoded object identifier.
    +     * @param seed the random seed.
    +     *
    +     * @return byte[] the signature.
    +     */
    +    private static native byte[] signDigest(byte[] digest, byte[] s,
    +        byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
    +
    +    /**
    +     * Verifies the signed digest using the public key.
    +     *
    +     * @param signedDigest the signature to be verified. It is encoded
    +     *        as a concatenation of the key's R and S values.
    +     * @param digest the digest to be used.
    +     * @param w the public key's W point (in uncompressed form).
    +     * @param encodedParams the curve's DER encoded object identifier.
    +     *
    +     * @return boolean true if the signature is successfully verified.
    +     */
    +    private static native boolean verifySignedDigest(byte[] signature,
    +        byte[] digest, byte[] w, byte[] encodedParams)
    +            throws GeneralSecurityException;
    +}
    diff --git a/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java b/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
    new file mode 100644
    index 00000000000..af98de60b8b
    --- /dev/null
    +++ b/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java
    @@ -0,0 +1,191 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Sun designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Sun in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +package sun.security.ec;
    +
    +import java.math.BigInteger;
    +import java.security.*;
    +import java.security.spec.AlgorithmParameterSpec;
    +import java.security.spec.ECGenParameterSpec;
    +import java.security.spec.ECParameterSpec;
    +import java.security.spec.ECPoint;
    +
    +import sun.security.ec.NamedCurve;
    +import sun.security.ec.ECParameters;
    +import sun.security.ec.ECPrivateKeyImpl;
    +import sun.security.ec.ECPublicKeyImpl;
    +import sun.security.jca.JCAUtil;
    +
    +/**
    + * EC keypair generator.
    + * Standard algorithm, minimum key length is 112 bits, maximum is 571 bits.
    + *
    + * @since 1.7
    + */
    +public final class ECKeyPairGenerator extends KeyPairGeneratorSpi {
    +
    +    // flag indicating whether the native ECC implementation is present
    +    private static boolean implementationPresent = true;
    +    static {
    +        try {
    +            AccessController.doPrivileged(new PrivilegedAction() {
    +                public Void run() {
    +                    System.loadLibrary("sunecc");
    +                    return null;
    +                }
    +            });
    +        } catch (UnsatisfiedLinkError e) {
    +            implementationPresent = false;
    +        }
    +    }
    +    private static final int KEY_SIZE_MIN = 112; // min bits (see ecc_impl.h)
    +    private static final int KEY_SIZE_MAX = 571; // max bits (see ecc_impl.h)
    +    private static final int KEY_SIZE_DEFAULT = 256;
    +
    +    // used to seed the keypair generator
    +    private SecureRandom random;
    +
    +    // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX
    +    private int keySize;
    +
    +    // parameters specified via init, if any
    +    private AlgorithmParameterSpec params = null;
    +
    +    /**
    +     * Constructs a new ECKeyPairGenerator.
    +     *
    +     * @exception ProviderException if the native ECC library is unavailable.
    +     */
    +    public ECKeyPairGenerator() {
    +        if (!implementationPresent) {
    +            throw new ProviderException("EC implementation is not available");
    +        }
    +        // initialize to default in case the app does not call initialize()
    +        initialize(KEY_SIZE_DEFAULT, null);
    +    }
    +
    +    // initialize the generator. See JCA doc
    +    @Override
    +    public void initialize(int keySize, SecureRandom random) {
    +
    +        checkKeySize(keySize);
    +        this.params = NamedCurve.getECParameterSpec(keySize);
    +        if (params == null) {
    +            throw new InvalidParameterException(
    +                "No EC parameters available for key size " + keySize + " bits");
    +        }
    +        this.random = random;
    +    }
    +
    +    // second initialize method. See JCA doc
    +    @Override
    +    public void initialize(AlgorithmParameterSpec params, SecureRandom random)
    +            throws InvalidAlgorithmParameterException {
    +
    +        if (params instanceof ECParameterSpec) {
    +            this.params = ECParameters.getNamedCurve((ECParameterSpec)params);
    +            if (this.params == null) {
    +                throw new InvalidAlgorithmParameterException(
    +                    "Unsupported curve: " + params);
    +            }
    +        } else if (params instanceof ECGenParameterSpec) {
    +            String name = ((ECGenParameterSpec)params).getName();
    +            this.params = NamedCurve.getECParameterSpec(name);
    +            if (this.params == null) {
    +                throw new InvalidAlgorithmParameterException(
    +                    "Unknown curve name: " + name);
    +            }
    +        } else {
    +            throw new InvalidAlgorithmParameterException(
    +                "ECParameterSpec or ECGenParameterSpec required for EC");
    +        }
    +        this.keySize =
    +            ((ECParameterSpec)this.params).getCurve().getField().getFieldSize();
    +        this.random = random;
    +    }
    +
    +    // generate the keypair. See JCA doc
    +    @Override
    +    public KeyPair generateKeyPair() {
    +
    +        byte[] encodedParams =
    +            ECParameters.encodeParameters((ECParameterSpec)params);
    +
    +        // seed is twice the key size (in bytes)
    +        byte[] seed = new byte[2 * ((keySize + 7) >> 3)];
    +        if (random == null) {
    +            random = JCAUtil.getSecureRandom();
    +        }
    +        random.nextBytes(seed);
    +
    +        long[] handles = generateECKeyPair(keySize, encodedParams, seed);
    +
    +        // The 'params' object supplied above is equivalent to the native one
    +        // so there is no need to fetch it.
    +
    +        // handles[0] points to the native private key
    +        BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
    +
    +        try {
    +            PrivateKey privateKey =
    +                new ECPrivateKeyImpl(s, (ECParameterSpec)params);
    +
    +            // handles[1] points to the native public key
    +            ECPoint w = ECParameters.decodePoint(getEncodedBytes(handles[1]),
    +                ((ECParameterSpec)params).getCurve());
    +            PublicKey publicKey =
    +                new ECPublicKeyImpl(w, (ECParameterSpec)params);
    +
    +            return new KeyPair(publicKey, privateKey);
    +
    +        } catch (Exception e) {
    +            throw new ProviderException(e);
    +        }
    +    }
    +
    +    private void checkKeySize(int keySize) throws InvalidParameterException {
    +        if (keySize < KEY_SIZE_MIN) {
    +            throw new InvalidParameterException
    +                ("Key size must be at least " + KEY_SIZE_MIN + " bits");
    +        }
    +        if (keySize > KEY_SIZE_MAX) {
    +            throw new InvalidParameterException
    +                ("Key size must be at most " + KEY_SIZE_MAX + " bits");
    +        }
    +        this.keySize = keySize;
    +    }
    +
    +    /*
    +     * Generates the keypair and returns a 2-element array of handles.
    +     * The first handle points to the private key, the second to the public key.
    +     */
    +    private static native long[] generateECKeyPair(int keySize,
    +        byte[] encodedParams, byte[] seed);
    +
    +    /*
    +     * Extracts the encoded key data using the supplied handle.
    +     */
    +    private static native byte[] getEncodedBytes(long handle);
    +}
    diff --git a/jdk/src/share/classes/sun/security/ec/SunEC.java b/jdk/src/share/classes/sun/security/ec/SunEC.java
    new file mode 100644
    index 00000000000..49223ca37b2
    --- /dev/null
    +++ b/jdk/src/share/classes/sun/security/ec/SunEC.java
    @@ -0,0 +1,65 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Sun designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Sun in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +package sun.security.ec;
    +
    +import java.util.*;
    +import java.security.*;
    +import sun.security.action.PutAllAction;
    +
    +/**
    + * Provider class for the Elliptic Curve provider.
    + * Supports EC keypair and parameter generation, ECDSA signing and
    + * ECDH key agreement.
    + *
    + * IMPLEMENTATION NOTE:
    + * The Java classes in this provider access a native ECC implementation
    + * via JNI to a C++ wrapper class which in turn calls C functions.
    + * The Java classes are packaged into the signed sunec.jar in the JRE
    + * extensions directory and the C++ and C functions are packaged into
    + * libsunecc.so or sunecc.dll in the JRE native libraries directory.
    + *
    + * @since   1.7
    + */
    +public final class SunEC extends Provider {
    +
    +    private static final long serialVersionUID = -2279741672933606418L;
    +
    +    public SunEC() {
    +        super("SunEC", 1.7d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)");
    +
    +        // if there is no security manager installed, put directly into
    +        // the provider. Otherwise, create a temporary map and use a
    +        // doPrivileged() call at the end to transfer the contents
    +        if (System.getSecurityManager() == null) {
    +            SunECEntries.putEntries(this);
    +        } else {
    +            Map map = new HashMap();
    +            SunECEntries.putEntries(map);
    +            AccessController.doPrivileged(new PutAllAction(this, map));
    +        }
    +    }
    +
    +}
    diff --git a/jdk/src/share/classes/sun/security/ec/SunECEntries.java b/jdk/src/share/classes/sun/security/ec/SunECEntries.java
    new file mode 100644
    index 00000000000..759d3007e85
    --- /dev/null
    +++ b/jdk/src/share/classes/sun/security/ec/SunECEntries.java
    @@ -0,0 +1,109 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Sun designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Sun in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +package sun.security.ec;
    +
    +import java.util.Map;
    +
    +/**
    + * Defines the entries of the SunEC provider.
    + *
    + * @since 1.7
    + */
    +final class SunECEntries {
    +
    +    private SunECEntries() {
    +        // empty
    +    }
    +
    +    static void putEntries(Map map) {
    +
    +        /*
    +         * Signature engines
    +         */
    +        map.put("Signature.NONEwithECDSA",
    +            "sun.security.ec.ECDSASignature$Raw");
    +        map.put("Signature.SHA1withECDSA",
    +            "sun.security.ec.ECDSASignature$SHA1");
    +        map.put("Signature.SHA256withECDSA",
    +            "sun.security.ec.ECDSASignature$SHA256");
    +        map.put("Signature.SHA384withECDSA",
    +            "sun.security.ec.ECDSASignature$SHA384");
    +        map.put("Signature.SHA512withECDSA",
    +            "sun.security.ec.ECDSASignature$SHA512");
    +
    +        String ecKeyClasses = "java.security.interfaces.ECPublicKey" +
    +                "|java.security.interfaces.ECPrivateKey";
    +        map.put("Signature.NONEwithECDSA SupportedKeyClasses", ecKeyClasses);
    +        map.put("Signature.SHA1withECDSA SupportedKeyClasses", ecKeyClasses);
    +        map.put("Signature.SHA256withECDSA SupportedKeyClasses", ecKeyClasses);
    +        map.put("Signature.SHA384withECDSA SupportedKeyClasses", ecKeyClasses);
    +        map.put("Signature.SHA512withECDSA SupportedKeyClasses", ecKeyClasses);
    +
    +        /*
    +         *  Key Pair Generator engine
    +         */
    +        map.put("KeyPairGenerator.EC", "sun.security.ec.ECKeyPairGenerator");
    +        map.put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC");
    +
    +        /*
    +         *  Key Factory engine
    +         */
    +        map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory");
    +        map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC");
    +
    +        /*
    +         * Algorithm Parameter engine
    +         */
    +        map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters");
    +        map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC");
    +
    +        /*
    +         * Key Agreement engine
    +         */
    +        map.put("KeyAgreement.ECDH", "sun.security.ec.ECDHKeyAgreement");
    +        map.put("KeyAgreement.ECDH SupportedKeyClasses", ecKeyClasses);
    +
    +        /*
    +         * Key sizes
    +         */
    +        map.put("Signature.SHA1withECDSA KeySize", "256");
    +        map.put("KeyPairGenerator.EC KeySize", "256");
    +        map.put("AlgorithmParameterGenerator.ECDSA KeySize", "256");
    +
    +        /*
    +         * Implementation type: software or hardware
    +         */
    +        map.put("Signature.NONEwithECDSA ImplementedIn", "Software");
    +        map.put("Signature.SHA1withECDSA ImplementedIn", "Software");
    +        map.put("Signature.SHA256withECDSA ImplementedIn", "Software");
    +        map.put("Signature.SHA384withECDSA ImplementedIn", "Software");
    +        map.put("Signature.SHA512withECDSA ImplementedIn", "Software");
    +        map.put("KeyPairGenerator.EC ImplementedIn", "Software");
    +        map.put("KeyFactory.EC ImplementedIn", "Software");
    +        map.put("KeyAgreement.ECDH ImplementedIn", "Software");
    +        map.put("AlgorithmParameters.EC ImplementedIn", "Software");
    +    }
    +}
    diff --git a/jdk/src/share/lib/security/java.security b/jdk/src/share/lib/security/java.security
    index c2a07506c15..b975f25e1e5 100644
    --- a/jdk/src/share/lib/security/java.security
    +++ b/jdk/src/share/lib/security/java.security
    @@ -45,12 +45,13 @@
     #
     security.provider.1=sun.security.provider.Sun
     security.provider.2=sun.security.rsa.SunRsaSign
    -security.provider.3=com.sun.net.ssl.internal.ssl.Provider
    -security.provider.4=com.sun.crypto.provider.SunJCE
    -security.provider.5=sun.security.jgss.SunProvider
    -security.provider.6=com.sun.security.sasl.Provider
    -security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    -security.provider.8=sun.security.smartcardio.SunPCSC
    +security.provider.3=sun.security.ec.SunEC
    +security.provider.4=com.sun.net.ssl.internal.ssl.Provider
    +security.provider.5=com.sun.crypto.provider.SunJCE
    +security.provider.6=sun.security.jgss.SunProvider
    +security.provider.7=com.sun.security.sasl.Provider
    +security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    +security.provider.9=sun.security.smartcardio.SunPCSC
     
     #
     # Select the source of seed data for SecureRandom. By default an
    diff --git a/jdk/src/share/lib/security/java.security-solaris b/jdk/src/share/lib/security/java.security-solaris
    index 05dfcb17728..1e447b7c24d 100644
    --- a/jdk/src/share/lib/security/java.security-solaris
    +++ b/jdk/src/share/lib/security/java.security-solaris
    @@ -46,12 +46,13 @@
     security.provider.1=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-solaris.cfg
     security.provider.2=sun.security.provider.Sun
     security.provider.3=sun.security.rsa.SunRsaSign
    -security.provider.4=com.sun.net.ssl.internal.ssl.Provider
    -security.provider.5=com.sun.crypto.provider.SunJCE
    -security.provider.6=sun.security.jgss.SunProvider
    -security.provider.7=com.sun.security.sasl.Provider
    -security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    -security.provider.9=sun.security.smartcardio.SunPCSC
    +security.provider.4=sun.security.ec.SunEC
    +security.provider.5=com.sun.net.ssl.internal.ssl.Provider
    +security.provider.6=com.sun.crypto.provider.SunJCE
    +security.provider.7=sun.security.jgss.SunProvider
    +security.provider.8=com.sun.security.sasl.Provider
    +security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    +security.provider.10=sun.security.smartcardio.SunPCSC
     
     #
     # Select the source of seed data for SecureRandom. By default an
    diff --git a/jdk/src/share/lib/security/java.security-windows b/jdk/src/share/lib/security/java.security-windows
    index 062b85b63c3..c94c76b7ffb 100644
    --- a/jdk/src/share/lib/security/java.security-windows
    +++ b/jdk/src/share/lib/security/java.security-windows
    @@ -45,13 +45,14 @@
     #
     security.provider.1=sun.security.provider.Sun
     security.provider.2=sun.security.rsa.SunRsaSign
    -security.provider.3=com.sun.net.ssl.internal.ssl.Provider
    -security.provider.4=com.sun.crypto.provider.SunJCE
    -security.provider.5=sun.security.jgss.SunProvider
    -security.provider.6=com.sun.security.sasl.Provider
    -security.provider.7=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    -security.provider.8=sun.security.smartcardio.SunPCSC
    -security.provider.9=sun.security.mscapi.SunMSCAPI
    +security.provider.3=sun.security.ec.SunEC
    +security.provider.4=com.sun.net.ssl.internal.ssl.Provider
    +security.provider.5=com.sun.crypto.provider.SunJCE
    +security.provider.6=sun.security.jgss.SunProvider
    +security.provider.7=com.sun.security.sasl.Provider
    +security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI
    +security.provider.9=sun.security.smartcardio.SunPCSC
    +security.provider.10=sun.security.mscapi.SunMSCAPI
     
     #
     # Select the source of seed data for SecureRandom. By default an
    diff --git a/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp
    new file mode 100644
    index 00000000000..fb227e82cac
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp
    @@ -0,0 +1,418 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.  Sun designates this
    + * particular file as subject to the "Classpath" exception as provided
    + * by Sun in the LICENSE file that accompanied this code.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +#include 
    +#include "ecc_impl.h"
    +
    +#define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
    +#define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
    +        "java/security/InvalidAlgorithmParameterException"
    +#define INVALID_PARAMETER_EXCEPTION \
    +        "java/security/InvalidParameterException"
    +#define KEY_EXCEPTION   "java/security/KeyException"
    +
    +extern "C" {
    +
    +/*
    + * Throws an arbitrary Java exception.
    + */
    +void ThrowException(JNIEnv *env, char *exceptionName)
    +{
    +    jclass exceptionClazz = env->FindClass(exceptionName);
    +    env->ThrowNew(exceptionClazz, NULL);
    +}
    +
    +/*
    + * Deep free of the ECParams struct
    + */
    +void FreeECParams(ECParams *ecparams, jboolean freeStruct)
    +{
    +    // Use B_FALSE to free the SECItem->data element, but not the SECItem itself
    +    // Use B_TRUE to free both
    +
    +    SECITEM_FreeItem(&ecparams->fieldID.u.prime, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->curve.a, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->curve.b, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->curve.seed, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->base, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->order, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE);
    +    SECITEM_FreeItem(&ecparams->curveOID, B_FALSE);
    +    if (freeStruct)
    +        free(ecparams);
    +}
    +
    +/*
    + * Class:     sun_security_ec_ECKeyPairGenerator
    + * Method:    generateECKeyPair
    + * Signature: (I[B[B)[J
    + */
    +JNIEXPORT jlongArray
    +JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
    +  (JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
    +{
    +    ECPrivateKey *privKey;      /* contains both public and private values */
    +    ECParams *ecparams = NULL;
    +    SECKEYECParams params_item;
    +    jint jSeedLength;
    +    jbyte* pSeedBuffer = NULL;
    +    jlongArray result = NULL;
    +    jlong* resultElements = NULL;
    +
    +    // Initialize the ECParams struct
    +    params_item.len = env->GetArrayLength(encodedParams);
    +    params_item.data =
    +        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    +
    +    // Fill a new ECParams using the supplied OID
    +    if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
    +        /* bad curve OID */
    +        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
    +        goto cleanup;
    +    }
    +
    +    // Copy seed from Java to native buffer
    +    jSeedLength = env->GetArrayLength(seed);
    +    pSeedBuffer = new jbyte[jSeedLength];
    +    env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
    +
    +    // Generate the new keypair (using the supplied seed)
    +    if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,
    +        jSeedLength, 0) != SECSuccess) {
    +        ThrowException(env, KEY_EXCEPTION);
    +        goto cleanup;
    +    }
    +
    +    jboolean isCopy;
    +    result = env->NewLongArray(2);
    +    resultElements = env->GetLongArrayElements(result, &isCopy);
    +
    +    resultElements[0] = (jlong) &(privKey->privateValue); // private big integer
    +    resultElements[1] = (jlong) &(privKey->publicValue); // encoded ec point
    +
    +    // If the array is a copy then we must write back our changes
    +    if (isCopy == JNI_TRUE) {
    +        env->ReleaseLongArrayElements(result, resultElements, 0);
    +    }
    +
    +cleanup:
    +    {
    +        if (params_item.data)
    +            env->ReleaseByteArrayElements(encodedParams,
    +                (jbyte *) params_item.data, JNI_ABORT);
    +
    +        if (ecparams)
    +            FreeECParams(ecparams, true);
    +
    +        if (privKey) {
    +            FreeECParams(&privKey->ecParams, false);
    +            SECITEM_FreeItem(&privKey->version, B_FALSE);
    +            // Don't free privKey->privateValue and privKey->publicValue
    +        }
    +
    +        if (pSeedBuffer)
    +            delete [] pSeedBuffer;
    +    }
    +
    +    return result;
    +}
    +
    +/*
    + * Class:     sun_security_ec_ECKeyPairGenerator
    + * Method:    getEncodedBytes
    + * Signature: (J)[B
    + */
    +JNIEXPORT jbyteArray
    +JNICALL Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes
    +  (JNIEnv *env, jclass clazz, jlong hSECItem)
    +{
    +    SECItem *s = (SECItem *)hSECItem;
    +    jbyteArray jEncodedBytes = env->NewByteArray(s->len);
    +
    +    // Copy bytes from a native SECItem buffer to Java byte array
    +    env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);
    +
    +    // Use B_FALSE to free only the SECItem->data
    +    SECITEM_FreeItem(s, B_FALSE);
    +
    +    return jEncodedBytes;
    +}
    +
    +/*
    + * Class:     sun_security_ec_ECDSASignature
    + * Method:    signDigest
    + * Signature: ([B[B[B[B)[B
    + */
    +JNIEXPORT jbyteArray
    +JNICALL Java_sun_security_ec_ECDSASignature_signDigest
    +  (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed)
    +{
    +    jbyte* pDigestBuffer = NULL;
    +    jint jDigestLength = env->GetArrayLength(digest);
    +    jbyteArray jSignedDigest = NULL;
    +
    +    SECItem signature_item;
    +    jbyte* pSignedDigestBuffer = NULL;
    +    jbyteArray temp;
    +
    +    jint jSeedLength = env->GetArrayLength(seed);
    +    jbyte* pSeedBuffer = NULL;
    +
    +    // Copy digest from Java to native buffer
    +    pDigestBuffer = new jbyte[jDigestLength];
    +    env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
    +    SECItem digest_item;
    +    digest_item.data = (unsigned char *) pDigestBuffer;
    +    digest_item.len = jDigestLength;
    +
    +    ECPrivateKey privKey;
    +
    +    // Initialize the ECParams struct
    +    ECParams *ecparams = NULL;
    +    SECKEYECParams params_item;
    +    params_item.len = env->GetArrayLength(encodedParams);
    +    params_item.data =
    +        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    +
    +    // Fill a new ECParams using the supplied OID
    +    if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
    +        /* bad curve OID */
    +        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
    +        goto cleanup;
    +    }
    +
    +    // Extract private key data
    +    privKey.ecParams = *ecparams; // struct assignment
    +    privKey.privateValue.len = env->GetArrayLength(privateKey);
    +    privKey.privateValue.data =
    +        (unsigned char *) env->GetByteArrayElements(privateKey, 0);
    +
    +    // Prepare a buffer for the signature (twice the key length)
    +    pSignedDigestBuffer = new jbyte[ecparams->order.len * 2];
    +    signature_item.data = (unsigned char *) pSignedDigestBuffer;
    +    signature_item.len = ecparams->order.len * 2;
    +
    +    // Copy seed from Java to native buffer
    +    pSeedBuffer = new jbyte[jSeedLength];
    +    env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
    +
    +    // Sign the digest (using the supplied seed)
    +    if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
    +        (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) {
    +        ThrowException(env, KEY_EXCEPTION);
    +        goto cleanup;
    +    }
    +
    +    // Create new byte array
    +    temp = env->NewByteArray(signature_item.len);
    +
    +    // Copy data from native buffer
    +    env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer);
    +    jSignedDigest = temp;
    +
    +cleanup:
    +    {
    +        if (params_item.data)
    +            env->ReleaseByteArrayElements(encodedParams,
    +                (jbyte *) params_item.data, JNI_ABORT);
    +
    +        if (pDigestBuffer)
    +            delete [] pDigestBuffer;
    +
    +        if (pSignedDigestBuffer)
    +            delete [] pSignedDigestBuffer;
    +
    +        if (pSeedBuffer)
    +            delete [] pSeedBuffer;
    +
    +        if (ecparams)
    +            FreeECParams(ecparams, true);
    +    }
    +
    +    return jSignedDigest;
    +}
    +
    +/*
    + * Class:     sun_security_ec_ECDSASignature
    + * Method:    verifySignedDigest
    + * Signature: ([B[B[B[B)Z
    + */
    +JNIEXPORT jboolean
    +JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
    +  (JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)
    +{
    +    jboolean isValid = false;
    +
    +    // Copy signedDigest from Java to native buffer
    +    jbyte* pSignedDigestBuffer = NULL;
    +    jint jSignedDigestLength = env->GetArrayLength(signedDigest);
    +    pSignedDigestBuffer = new jbyte[jSignedDigestLength];
    +    env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength,
    +        pSignedDigestBuffer);
    +    SECItem signature_item;
    +    signature_item.data = (unsigned char *) pSignedDigestBuffer;
    +    signature_item.len = jSignedDigestLength;
    +
    +    // Copy digest from Java to native buffer
    +    jbyte* pDigestBuffer = NULL;
    +    jint jDigestLength = env->GetArrayLength(digest);
    +    pDigestBuffer = new jbyte[jDigestLength];
    +    env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
    +    SECItem digest_item;
    +    digest_item.data = (unsigned char *) pDigestBuffer;
    +    digest_item.len = jDigestLength;
    +
    +    // Extract public key data
    +    ECPublicKey pubKey;
    +    pubKey.publicValue.data = NULL;
    +    ECParams *ecparams = NULL;
    +    SECKEYECParams params_item;
    +
    +    // Initialize the ECParams struct
    +    params_item.len = env->GetArrayLength(encodedParams);
    +    params_item.data =
    +        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    +
    +    // Fill a new ECParams using the supplied OID
    +    if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
    +        /* bad curve OID */
    +        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
    +        goto cleanup;
    +    }
    +    pubKey.ecParams = *ecparams; // struct assignment
    +    pubKey.publicValue.len = env->GetArrayLength(publicKey);
    +    pubKey.publicValue.data =
    +        (unsigned char *) env->GetByteArrayElements(publicKey, 0);
    +
    +    if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)
    +            != SECSuccess) {
    +        goto cleanup;
    +    }
    +
    +    isValid = true;
    +
    +cleanup:
    +    {
    +        if (params_item.data)
    +            env->ReleaseByteArrayElements(encodedParams,
    +                (jbyte *) params_item.data, JNI_ABORT);
    +
    +        if (pubKey.publicValue.data)
    +            env->ReleaseByteArrayElements(publicKey,
    +                (jbyte *) pubKey.publicValue.data, JNI_ABORT);
    +
    +        if (ecparams)
    +            FreeECParams(ecparams, true);
    +
    +        if (pSignedDigestBuffer)
    +            delete [] pSignedDigestBuffer;
    +
    +        if (pDigestBuffer)
    +            delete [] pDigestBuffer;
    +    }
    +
    +    return isValid;
    +}
    +
    +/*
    + * Class:     sun_security_ec_ECDHKeyAgreement
    + * Method:    deriveKey
    + * Signature: ([B[B[B)[B
    + */
    +JNIEXPORT jbyteArray
    +JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
    +  (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)
    +{
    +    jbyteArray jSecret = NULL;
    +
    +    // Extract private key value
    +    SECItem privateValue_item;
    +    privateValue_item.len = env->GetArrayLength(privateKey);
    +    privateValue_item.data =
    +            (unsigned char *) env->GetByteArrayElements(privateKey, 0);
    +
    +    // Extract public key value
    +    SECItem publicValue_item;
    +    publicValue_item.len = env->GetArrayLength(publicKey);
    +    publicValue_item.data =
    +        (unsigned char *) env->GetByteArrayElements(publicKey, 0);
    +
    +    // Initialize the ECParams struct
    +    ECParams *ecparams = NULL;
    +    SECKEYECParams params_item;
    +    params_item.len = env->GetArrayLength(encodedParams);
    +    params_item.data =
    +        (unsigned char *) env->GetByteArrayElements(encodedParams, 0);
    +
    +    // Fill a new ECParams using the supplied OID
    +    if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {
    +        /* bad curve OID */
    +        ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
    +        goto cleanup;
    +    }
    +
    +    // Prepare a buffer for the secret
    +    SECItem secret_item;
    +    secret_item.data = NULL;
    +    secret_item.len = ecparams->order.len * 2;
    +
    +    if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,
    +        &secret_item, 0) != SECSuccess) {
    +        ThrowException(env, ILLEGAL_STATE_EXCEPTION);
    +        goto cleanup;
    +    }
    +
    +    // Create new byte array
    +    jSecret = env->NewByteArray(secret_item.len);
    +
    +    // Copy bytes from the SECItem buffer to a Java byte array
    +    env->SetByteArrayRegion(jSecret, 0, secret_item.len,
    +        (jbyte *)secret_item.data);
    +
    +    // Free the SECItem data buffer
    +    SECITEM_FreeItem(&secret_item, B_FALSE);
    +
    +cleanup:
    +    {
    +        if (privateValue_item.data)
    +            env->ReleaseByteArrayElements(privateKey,
    +                (jbyte *) privateValue_item.data, JNI_ABORT);
    +
    +        if (publicValue_item.data)
    +            env->ReleaseByteArrayElements(publicKey,
    +                (jbyte *) publicValue_item.data, JNI_ABORT);
    +
    +        if (params_item.data)
    +            env->ReleaseByteArrayElements(encodedParams,
    +                (jbyte *) params_item.data, JNI_ABORT);
    +
    +        if (ecparams)
    +            FreeECParams(ecparams, true);
    +    }
    +
    +    return jSecret;
    +}
    +
    +} /* extern "C" */
    diff --git a/jdk/src/share/native/sun/security/ec/ec.c b/jdk/src/share/native/sun/security/ec/ec.c
    new file mode 100644
    index 00000000000..d77f110af64
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec.c
    @@ -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  and
    + *   Douglas Stebila , Sun Microsystems Laboratories
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#ifndef _KERNEL
    +#include 
    +#include 
    +
    +#ifndef _WIN32
    +#include 
    +#endif /* _WIN32 */
    +
    +#endif
    +#include "ecl-exp.h"
    +#include "mpi.h"
    +#include "ecc_impl.h"
    +
    +#ifdef _KERNEL
    +#define PORT_ZFree(p, l)                bzero((p), (l)); kmem_free((p), (l))
    +#else
    +#ifndef _WIN32
    +#define PORT_ZFree(p, l)                bzero((p), (l)); free((p))
    +#else
    +#define PORT_ZFree(p, l)                memset((p), 0, (l)); free((p))
    +#endif /* _WIN32 */
    +#endif
    +
    +/*
    + * Returns true if pointP is the point at infinity, false otherwise
    + */
    +PRBool
    +ec_point_at_infinity(SECItem *pointP)
    +{
    +    unsigned int i;
    +
    +    for (i = 1; i < pointP->len; i++) {
    +        if (pointP->data[i] != 0x00) return PR_FALSE;
    +    }
    +
    +    return PR_TRUE;
    +}
    +
    +/*
    + * Computes scalar point multiplication pointQ = k1 * G + k2 * pointP for
    + * the curve whose parameters are encoded in params with base point G.
    + */
    +SECStatus
    +ec_points_mul(const ECParams *params, const mp_int *k1, const mp_int *k2,
    +             const SECItem *pointP, SECItem *pointQ, int kmflag)
    +{
    +    mp_int Px, Py, Qx, Qy;
    +    mp_int Gx, Gy, order, irreducible, a, b;
    +#if 0 /* currently don't support non-named curves */
    +    unsigned int irr_arr[5];
    +#endif
    +    ECGroup *group = NULL;
    +    SECStatus rv = SECFailure;
    +    mp_err err = MP_OKAY;
    +    int len;
    +
    +#if EC_DEBUG
    +    int i;
    +    char mpstr[256];
    +
    +    printf("ec_points_mul: params [len=%d]:", params->DEREncoding.len);
    +    for (i = 0; i < params->DEREncoding.len; i++)
    +            printf("%02x:", params->DEREncoding.data[i]);
    +    printf("\n");
    +
    +        if (k1 != NULL) {
    +                mp_tohex(k1, mpstr);
    +                printf("ec_points_mul: scalar k1: %s\n", mpstr);
    +                mp_todecimal(k1, mpstr);
    +                printf("ec_points_mul: scalar k1: %s (dec)\n", mpstr);
    +        }
    +
    +        if (k2 != NULL) {
    +                mp_tohex(k2, mpstr);
    +                printf("ec_points_mul: scalar k2: %s\n", mpstr);
    +                mp_todecimal(k2, mpstr);
    +                printf("ec_points_mul: scalar k2: %s (dec)\n", mpstr);
    +        }
    +
    +        if (pointP != NULL) {
    +                printf("ec_points_mul: pointP [len=%d]:", pointP->len);
    +                for (i = 0; i < pointP->len; i++)
    +                        printf("%02x:", pointP->data[i]);
    +                printf("\n");
    +        }
    +#endif
    +
    +        /* NOTE: We only support uncompressed points for now */
    +        len = (params->fieldID.size + 7) >> 3;
    +        if (pointP != NULL) {
    +                if ((pointP->data[0] != EC_POINT_FORM_UNCOMPRESSED) ||
    +                        (pointP->len != (2 * len + 1))) {
    +                        return SECFailure;
    +                };
    +        }
    +
    +        MP_DIGITS(&Px) = 0;
    +        MP_DIGITS(&Py) = 0;
    +        MP_DIGITS(&Qx) = 0;
    +        MP_DIGITS(&Qy) = 0;
    +        MP_DIGITS(&Gx) = 0;
    +        MP_DIGITS(&Gy) = 0;
    +        MP_DIGITS(&order) = 0;
    +        MP_DIGITS(&irreducible) = 0;
    +        MP_DIGITS(&a) = 0;
    +        MP_DIGITS(&b) = 0;
    +        CHECK_MPI_OK( mp_init(&Px, kmflag) );
    +        CHECK_MPI_OK( mp_init(&Py, kmflag) );
    +        CHECK_MPI_OK( mp_init(&Qx, kmflag) );
    +        CHECK_MPI_OK( mp_init(&Qy, kmflag) );
    +        CHECK_MPI_OK( mp_init(&Gx, kmflag) );
    +        CHECK_MPI_OK( mp_init(&Gy, kmflag) );
    +        CHECK_MPI_OK( mp_init(&order, kmflag) );
    +        CHECK_MPI_OK( mp_init(&irreducible, kmflag) );
    +        CHECK_MPI_OK( mp_init(&a, kmflag) );
    +        CHECK_MPI_OK( mp_init(&b, kmflag) );
    +
    +        if ((k2 != NULL) && (pointP != NULL)) {
    +                /* Initialize Px and Py */
    +                CHECK_MPI_OK( mp_read_unsigned_octets(&Px, pointP->data + 1, (mp_size) len) );
    +                CHECK_MPI_OK( mp_read_unsigned_octets(&Py, pointP->data + 1 + len, (mp_size) len) );
    +        }
    +
    +        /* construct from named params, if possible */
    +        if (params->name != ECCurve_noName) {
    +                group = ECGroup_fromName(params->name, kmflag);
    +        }
    +
    +#if 0 /* currently don't support non-named curves */
    +        if (group == NULL) {
    +                /* Set up mp_ints containing the curve coefficients */
    +                CHECK_MPI_OK( mp_read_unsigned_octets(&Gx, params->base.data + 1,
    +                                                                                  (mp_size) len) );
    +                CHECK_MPI_OK( mp_read_unsigned_octets(&Gy, params->base.data + 1 + len,
    +                                                                                  (mp_size) len) );
    +                SECITEM_TO_MPINT( params->order, &order );
    +                SECITEM_TO_MPINT( params->curve.a, &a );
    +                SECITEM_TO_MPINT( params->curve.b, &b );
    +                if (params->fieldID.type == ec_field_GFp) {
    +                        SECITEM_TO_MPINT( params->fieldID.u.prime, &irreducible );
    +                        group = ECGroup_consGFp(&irreducible, &a, &b, &Gx, &Gy, &order, params->cofactor);
    +                } else {
    +                        SECITEM_TO_MPINT( params->fieldID.u.poly, &irreducible );
    +                        irr_arr[0] = params->fieldID.size;
    +                        irr_arr[1] = params->fieldID.k1;
    +                        irr_arr[2] = params->fieldID.k2;
    +                        irr_arr[3] = params->fieldID.k3;
    +                        irr_arr[4] = 0;
    +                        group = ECGroup_consGF2m(&irreducible, irr_arr, &a, &b, &Gx, &Gy, &order, params->cofactor);
    +                }
    +        }
    +#endif
    +        if (group == NULL)
    +                goto cleanup;
    +
    +        if ((k2 != NULL) && (pointP != NULL)) {
    +                CHECK_MPI_OK( ECPoints_mul(group, k1, k2, &Px, &Py, &Qx, &Qy) );
    +        } else {
    +                CHECK_MPI_OK( ECPoints_mul(group, k1, NULL, NULL, NULL, &Qx, &Qy) );
    +    }
    +
    +    /* Construct the SECItem representation of point Q */
    +    pointQ->data[0] = EC_POINT_FORM_UNCOMPRESSED;
    +    CHECK_MPI_OK( mp_to_fixlen_octets(&Qx, pointQ->data + 1,
    +                                      (mp_size) len) );
    +    CHECK_MPI_OK( mp_to_fixlen_octets(&Qy, pointQ->data + 1 + len,
    +                                      (mp_size) len) );
    +
    +    rv = SECSuccess;
    +
    +#if EC_DEBUG
    +    printf("ec_points_mul: pointQ [len=%d]:", pointQ->len);
    +    for (i = 0; i < pointQ->len; i++)
    +            printf("%02x:", pointQ->data[i]);
    +    printf("\n");
    +#endif
    +
    +cleanup:
    +    ECGroup_free(group);
    +    mp_clear(&Px);
    +    mp_clear(&Py);
    +    mp_clear(&Qx);
    +    mp_clear(&Qy);
    +    mp_clear(&Gx);
    +    mp_clear(&Gy);
    +    mp_clear(&order);
    +    mp_clear(&irreducible);
    +    mp_clear(&a);
    +    mp_clear(&b);
    +    if (err) {
    +        MP_TO_SEC_ERROR(err);
    +        rv = SECFailure;
    +    }
    +
    +    return rv;
    +}
    +
    +/* Generates a new EC key pair. The private key is a supplied
    + * value and the public key is the result of performing a scalar
    + * point multiplication of that value with the curve's base point.
    + */
    +SECStatus
    +ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
    +    const unsigned char *privKeyBytes, int privKeyLen, int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    PRArenaPool *arena;
    +    ECPrivateKey *key;
    +    mp_int k;
    +    mp_err err = MP_OKAY;
    +    int len;
    +
    +#if EC_DEBUG
    +    printf("ec_NewKey called\n");
    +#endif
    +
    +#ifndef _WIN32
    +int printf();
    +#endif /* _WIN32 */
    +
    +    if (!ecParams || !privKey || !privKeyBytes || (privKeyLen < 0)) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        return SECFailure;
    +    }
    +
    +    /* Initialize an arena for the EC key. */
    +    if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE)))
    +        return SECFailure;
    +
    +    key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey),
    +        kmflag);
    +    if (!key) {
    +        PORT_FreeArena(arena, PR_TRUE);
    +        return SECFailure;
    +    }
    +
    +    /* Set the version number (SEC 1 section C.4 says it should be 1) */
    +    SECITEM_AllocItem(arena, &key->version, 1, kmflag);
    +    key->version.data[0] = 1;
    +
    +    /* Copy all of the fields from the ECParams argument to the
    +     * ECParams structure within the private key.
    +     */
    +    key->ecParams.arena = arena;
    +    key->ecParams.type = ecParams->type;
    +    key->ecParams.fieldID.size = ecParams->fieldID.size;
    +    key->ecParams.fieldID.type = ecParams->fieldID.type;
    +    if (ecParams->fieldID.type == ec_field_GFp) {
    +        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime,
    +            &ecParams->fieldID.u.prime, kmflag));
    +    } else {
    +        CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.poly,
    +            &ecParams->fieldID.u.poly, kmflag));
    +    }
    +    key->ecParams.fieldID.k1 = ecParams->fieldID.k1;
    +    key->ecParams.fieldID.k2 = ecParams->fieldID.k2;
    +    key->ecParams.fieldID.k3 = ecParams->fieldID.k3;
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a,
    +        &ecParams->curve.a, kmflag));
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b,
    +        &ecParams->curve.b, kmflag));
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed,
    +        &ecParams->curve.seed, kmflag));
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base,
    +        &ecParams->base, kmflag));
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order,
    +        &ecParams->order, kmflag));
    +    key->ecParams.cofactor = ecParams->cofactor;
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding,
    +        &ecParams->DEREncoding, kmflag));
    +    key->ecParams.name = ecParams->name;
    +    CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID,
    +        &ecParams->curveOID, kmflag));
    +
    +    len = (ecParams->fieldID.size + 7) >> 3;
    +    SECITEM_AllocItem(arena, &key->publicValue, 2*len + 1, kmflag);
    +    len = ecParams->order.len;
    +    SECITEM_AllocItem(arena, &key->privateValue, len, kmflag);
    +
    +    /* Copy private key */
    +    if (privKeyLen >= len) {
    +        memcpy(key->privateValue.data, privKeyBytes, len);
    +    } else {
    +        memset(key->privateValue.data, 0, (len - privKeyLen));
    +        memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen);
    +    }
    +
    +    /* Compute corresponding public key */
    +    MP_DIGITS(&k) = 0;
    +    CHECK_MPI_OK( mp_init(&k, kmflag) );
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&k, key->privateValue.data,
    +        (mp_size) len) );
    +
    +    rv = ec_points_mul(ecParams, &k, NULL, NULL, &(key->publicValue), kmflag);
    +    if (rv != SECSuccess) goto cleanup;
    +    *privKey = key;
    +
    +cleanup:
    +    mp_clear(&k);
    +    if (rv)
    +        PORT_FreeArena(arena, PR_TRUE);
    +
    +#if EC_DEBUG
    +    printf("ec_NewKey returning %s\n",
    +        (rv == SECSuccess) ? "success" : "failure");
    +#endif
    +
    +    return rv;
    +
    +}
    +
    +/* Generates a new EC key pair. The private key is a supplied
    + * random value (in seed) and the public key is the result of
    + * performing a scalar point multiplication of that value with
    + * the curve's base point.
    + */
    +SECStatus
    +EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
    +    const unsigned char *seed, int seedlen, int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    rv = ec_NewKey(ecParams, privKey, seed, seedlen, kmflag);
    +    return rv;
    +}
    +
    +/* Generate a random private key using the algorithm A.4.1 of ANSI X9.62,
    + * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the
    + * random number generator.
    + *
    + * Parameters
    + * - order: a buffer that holds the curve's group order
    + * - len: the length in octets of the order buffer
    + * - random: a buffer of 2 * len random bytes
    + * - randomlen: the length in octets of the random buffer
    + *
    + * Return Value
    + * Returns a buffer of len octets that holds the private key. The caller
    + * is responsible for freeing the buffer with PORT_ZFree.
    + */
    +static unsigned char *
    +ec_GenerateRandomPrivateKey(const unsigned char *order, int len,
    +    const unsigned char *random, int randomlen, int kmflag)
    +{
    +    SECStatus rv = SECSuccess;
    +    mp_err err;
    +    unsigned char *privKeyBytes = NULL;
    +    mp_int privKeyVal, order_1, one;
    +
    +    MP_DIGITS(&privKeyVal) = 0;
    +    MP_DIGITS(&order_1) = 0;
    +    MP_DIGITS(&one) = 0;
    +    CHECK_MPI_OK( mp_init(&privKeyVal, kmflag) );
    +    CHECK_MPI_OK( mp_init(&order_1, kmflag) );
    +    CHECK_MPI_OK( mp_init(&one, kmflag) );
    +
    +    /*
    +     * Reduces the 2*len buffer of random bytes modulo the group order.
    +     */
    +    if ((privKeyBytes = PORT_Alloc(2*len, kmflag)) == NULL) goto cleanup;
    +    if (randomlen != 2 * len) {
    +        goto cleanup;
    +    }
    +    /* No need to generate - random bytes are now supplied */
    +    /* CHECK_SEC_OK( RNG_GenerateGlobalRandomBytes(privKeyBytes, 2*len) );*/
    +    memcpy(privKeyBytes, random, randomlen);
    +
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&privKeyVal, privKeyBytes, 2*len) );
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&order_1, order, len) );
    +    CHECK_MPI_OK( mp_set_int(&one, 1) );
    +    CHECK_MPI_OK( mp_sub(&order_1, &one, &order_1) );
    +    CHECK_MPI_OK( mp_mod(&privKeyVal, &order_1, &privKeyVal) );
    +    CHECK_MPI_OK( mp_add(&privKeyVal, &one, &privKeyVal) );
    +    CHECK_MPI_OK( mp_to_fixlen_octets(&privKeyVal, privKeyBytes, len) );
    +    memset(privKeyBytes+len, 0, len);
    +cleanup:
    +    mp_clear(&privKeyVal);
    +    mp_clear(&order_1);
    +    mp_clear(&one);
    +    if (err < MP_OKAY) {
    +        MP_TO_SEC_ERROR(err);
    +        rv = SECFailure;
    +    }
    +    if (rv != SECSuccess && privKeyBytes) {
    +#ifdef _KERNEL
    +        kmem_free(privKeyBytes, 2*len);
    +#else
    +        free(privKeyBytes);
    +#endif
    +        privKeyBytes = NULL;
    +    }
    +    return privKeyBytes;
    +}
    +
    +/* Generates a new EC key pair. The private key is a random value and
    + * the public key is the result of performing a scalar point multiplication
    + * of that value with the curve's base point.
    + */
    +SECStatus
    +EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey,
    +    const unsigned char* random, int randomlen, int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    int len;
    +    unsigned char *privKeyBytes = NULL;
    +
    +    if (!ecParams) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        return SECFailure;
    +    }
    +
    +    len = ecParams->order.len;
    +    privKeyBytes = ec_GenerateRandomPrivateKey(ecParams->order.data, len,
    +        random, randomlen, kmflag);
    +    if (privKeyBytes == NULL) goto cleanup;
    +    /* generate public key */
    +    CHECK_SEC_OK( ec_NewKey(ecParams, privKey, privKeyBytes, len, kmflag) );
    +
    +cleanup:
    +    if (privKeyBytes) {
    +        PORT_ZFree(privKeyBytes, len * 2);
    +    }
    +#if EC_DEBUG
    +    printf("EC_NewKey returning %s\n",
    +        (rv == SECSuccess) ? "success" : "failure");
    +#endif
    +
    +    return rv;
    +}
    +
    +/* Validates an EC public key as described in Section 5.2.2 of
    + * X9.62. The ECDH primitive when used without the cofactor does
    + * not address small subgroup attacks, which may occur when the
    + * public key is not valid. These attacks can be prevented by
    + * validating the public key before using ECDH.
    + */
    +SECStatus
    +EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue, int kmflag)
    +{
    +    mp_int Px, Py;
    +    ECGroup *group = NULL;
    +    SECStatus rv = SECFailure;
    +    mp_err err = MP_OKAY;
    +    int len;
    +
    +    if (!ecParams || !publicValue) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        return SECFailure;
    +    }
    +
    +    /* NOTE: We only support uncompressed points for now */
    +    len = (ecParams->fieldID.size + 7) >> 3;
    +    if (publicValue->data[0] != EC_POINT_FORM_UNCOMPRESSED) {
    +        PORT_SetError(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM);
    +        return SECFailure;
    +    } else if (publicValue->len != (2 * len + 1)) {
    +        PORT_SetError(SEC_ERROR_BAD_KEY);
    +        return SECFailure;
    +    }
    +
    +    MP_DIGITS(&Px) = 0;
    +    MP_DIGITS(&Py) = 0;
    +    CHECK_MPI_OK( mp_init(&Px, kmflag) );
    +    CHECK_MPI_OK( mp_init(&Py, kmflag) );
    +
    +    /* Initialize Px and Py */
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&Px, publicValue->data + 1, (mp_size) len) );
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&Py, publicValue->data + 1 + len, (mp_size) len) );
    +
    +    /* construct from named params */
    +    group = ECGroup_fromName(ecParams->name, kmflag);
    +    if (group == NULL) {
    +        /*
    +         * ECGroup_fromName fails if ecParams->name is not a valid
    +         * ECCurveName value, or if we run out of memory, or perhaps
    +         * for other reasons.  Unfortunately if ecParams->name is a
    +         * valid ECCurveName value, we don't know what the right error
    +         * code should be because ECGroup_fromName doesn't return an
    +         * error code to the caller.  Set err to MP_UNDEF because
    +         * that's what ECGroup_fromName uses internally.
    +         */
    +        if ((ecParams->name <= ECCurve_noName) ||
    +            (ecParams->name >= ECCurve_pastLastCurve)) {
    +            err = MP_BADARG;
    +        } else {
    +            err = MP_UNDEF;
    +        }
    +        goto cleanup;
    +    }
    +
    +    /* validate public point */
    +    if ((err = ECPoint_validate(group, &Px, &Py)) < MP_YES) {
    +        if (err == MP_NO) {
    +            PORT_SetError(SEC_ERROR_BAD_KEY);
    +            rv = SECFailure;
    +            err = MP_OKAY;  /* don't change the error code */
    +        }
    +        goto cleanup;
    +    }
    +
    +    rv = SECSuccess;
    +
    +cleanup:
    +    ECGroup_free(group);
    +    mp_clear(&Px);
    +    mp_clear(&Py);
    +    if (err) {
    +        MP_TO_SEC_ERROR(err);
    +        rv = SECFailure;
    +    }
    +    return rv;
    +}
    +
    +/*
    +** Performs an ECDH key derivation by computing the scalar point
    +** multiplication of privateValue and publicValue (with or without the
    +** cofactor) and returns the x-coordinate of the resulting elliptic
    +** curve point in derived secret.  If successful, derivedSecret->data
    +** is set to the address of the newly allocated buffer containing the
    +** derived secret, and derivedSecret->len is the size of the secret
    +** produced. It is the caller's responsibility to free the allocated
    +** buffer containing the derived secret.
    +*/
    +SECStatus
    +ECDH_Derive(SECItem  *publicValue,
    +            ECParams *ecParams,
    +            SECItem  *privateValue,
    +            PRBool    withCofactor,
    +            SECItem  *derivedSecret,
    +            int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    unsigned int len = 0;
    +    SECItem pointQ = {siBuffer, NULL, 0};
    +    mp_int k; /* to hold the private value */
    +    mp_int cofactor;
    +    mp_err err = MP_OKAY;
    +#if EC_DEBUG
    +    int i;
    +#endif
    +
    +    if (!publicValue || !ecParams || !privateValue ||
    +        !derivedSecret) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        return SECFailure;
    +    }
    +
    +    memset(derivedSecret, 0, sizeof *derivedSecret);
    +    len = (ecParams->fieldID.size + 7) >> 3;
    +    pointQ.len = 2*len + 1;
    +    if ((pointQ.data = PORT_Alloc(2*len + 1, kmflag)) == NULL) goto cleanup;
    +
    +    MP_DIGITS(&k) = 0;
    +    CHECK_MPI_OK( mp_init(&k, kmflag) );
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&k, privateValue->data,
    +                                          (mp_size) privateValue->len) );
    +
    +    if (withCofactor && (ecParams->cofactor != 1)) {
    +            /* multiply k with the cofactor */
    +            MP_DIGITS(&cofactor) = 0;
    +            CHECK_MPI_OK( mp_init(&cofactor, kmflag) );
    +            mp_set(&cofactor, ecParams->cofactor);
    +            CHECK_MPI_OK( mp_mul(&k, &cofactor, &k) );
    +    }
    +
    +    /* Multiply our private key and peer's public point */
    +    if ((ec_points_mul(ecParams, NULL, &k, publicValue, &pointQ, kmflag) != SECSuccess) ||
    +        ec_point_at_infinity(&pointQ))
    +        goto cleanup;
    +
    +    /* Allocate memory for the derived secret and copy
    +     * the x co-ordinate of pointQ into it.
    +     */
    +    SECITEM_AllocItem(NULL, derivedSecret, len, kmflag);
    +    memcpy(derivedSecret->data, pointQ.data + 1, len);
    +
    +    rv = SECSuccess;
    +
    +#if EC_DEBUG
    +    printf("derived_secret:\n");
    +    for (i = 0; i < derivedSecret->len; i++)
    +        printf("%02x:", derivedSecret->data[i]);
    +    printf("\n");
    +#endif
    +
    +cleanup:
    +    mp_clear(&k);
    +
    +    if (pointQ.data) {
    +        PORT_ZFree(pointQ.data, 2*len + 1);
    +    }
    +
    +    return rv;
    +}
    +
    +/* Computes the ECDSA signature (a concatenation of two values r and s)
    + * on the digest using the given key and the random value kb (used in
    + * computing s).
    + */
    +SECStatus
    +ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature,
    +    const SECItem *digest, const unsigned char *kb, const int kblen, int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    mp_int x1;
    +    mp_int d, k;     /* private key, random integer */
    +    mp_int r, s;     /* tuple (r, s) is the signature */
    +    mp_int n;
    +    mp_err err = MP_OKAY;
    +    ECParams *ecParams = NULL;
    +    SECItem kGpoint = { siBuffer, NULL, 0};
    +    int flen = 0;    /* length in bytes of the field size */
    +    unsigned olen;   /* length in bytes of the base point order */
    +
    +#if EC_DEBUG
    +    char mpstr[256];
    +#endif
    +
    +    /* Initialize MPI integers. */
    +    /* must happen before the first potential call to cleanup */
    +    MP_DIGITS(&x1) = 0;
    +    MP_DIGITS(&d) = 0;
    +    MP_DIGITS(&k) = 0;
    +    MP_DIGITS(&r) = 0;
    +    MP_DIGITS(&s) = 0;
    +    MP_DIGITS(&n) = 0;
    +
    +    /* Check args */
    +    if (!key || !signature || !digest || !kb || (kblen < 0)) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        goto cleanup;
    +    }
    +
    +    ecParams = &(key->ecParams);
    +    flen = (ecParams->fieldID.size + 7) >> 3;
    +    olen = ecParams->order.len;
    +    if (signature->data == NULL) {
    +        /* a call to get the signature length only */
    +        goto finish;
    +    }
    +    if (signature->len < 2*olen) {
    +        PORT_SetError(SEC_ERROR_OUTPUT_LEN);
    +        rv = SECBufferTooSmall;
    +        goto cleanup;
    +    }
    +
    +
    +    CHECK_MPI_OK( mp_init(&x1, kmflag) );
    +    CHECK_MPI_OK( mp_init(&d, kmflag) );
    +    CHECK_MPI_OK( mp_init(&k, kmflag) );
    +    CHECK_MPI_OK( mp_init(&r, kmflag) );
    +    CHECK_MPI_OK( mp_init(&s, kmflag) );
    +    CHECK_MPI_OK( mp_init(&n, kmflag) );
    +
    +    SECITEM_TO_MPINT( ecParams->order, &n );
    +    SECITEM_TO_MPINT( key->privateValue, &d );
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&k, kb, kblen) );
    +    /* Make sure k is in the interval [1, n-1] */
    +    if ((mp_cmp_z(&k) <= 0) || (mp_cmp(&k, &n) >= 0)) {
    +#if EC_DEBUG
    +        printf("k is outside [1, n-1]\n");
    +        mp_tohex(&k, mpstr);
    +        printf("k : %s \n", mpstr);
    +        mp_tohex(&n, mpstr);
    +        printf("n : %s \n", mpstr);
    +#endif
    +        PORT_SetError(SEC_ERROR_NEED_RANDOM);
    +        goto cleanup;
    +    }
    +
    +    /*
    +    ** ANSI X9.62, Section 5.3.2, Step 2
    +    **
    +    ** Compute kG
    +    */
    +    kGpoint.len = 2*flen + 1;
    +    kGpoint.data = PORT_Alloc(2*flen + 1, kmflag);
    +    if ((kGpoint.data == NULL) ||
    +        (ec_points_mul(ecParams, &k, NULL, NULL, &kGpoint, kmflag)
    +            != SECSuccess))
    +        goto cleanup;
    +
    +    /*
    +    ** ANSI X9.62, Section 5.3.3, Step 1
    +    **
    +    ** Extract the x co-ordinate of kG into x1
    +    */
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, kGpoint.data + 1,
    +                                          (mp_size) flen) );
    +
    +    /*
    +    ** ANSI X9.62, Section 5.3.3, Step 2
    +    **
    +    ** r = x1 mod n  NOTE: n is the order of the curve
    +    */
    +    CHECK_MPI_OK( mp_mod(&x1, &n, &r) );
    +
    +    /*
    +    ** ANSI X9.62, Section 5.3.3, Step 3
    +    **
    +    ** verify r != 0
    +    */
    +    if (mp_cmp_z(&r) == 0) {
    +        PORT_SetError(SEC_ERROR_NEED_RANDOM);
    +        goto cleanup;
    +    }
    +
    +    /*
    +    ** ANSI X9.62, Section 5.3.3, Step 4
    +    **
    +    ** s = (k**-1 * (HASH(M) + d*r)) mod n
    +    */
    +    SECITEM_TO_MPINT(*digest, &s);        /* s = HASH(M)     */
    +
    +    /* In the definition of EC signing, digests are truncated
    +     * to the length of n in bits.
    +     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    +    if (digest->len*8 > ecParams->fieldID.size) {
    +        mpl_rsh(&s,&s,digest->len*8 - ecParams->fieldID.size);
    +    }
    +
    +#if EC_DEBUG
    +    mp_todecimal(&n, mpstr);
    +    printf("n : %s (dec)\n", mpstr);
    +    mp_todecimal(&d, mpstr);
    +    printf("d : %s (dec)\n", mpstr);
    +    mp_tohex(&x1, mpstr);
    +    printf("x1: %s\n", mpstr);
    +    mp_todecimal(&s, mpstr);
    +    printf("digest: %s (decimal)\n", mpstr);
    +    mp_todecimal(&r, mpstr);
    +    printf("r : %s (dec)\n", mpstr);
    +    mp_tohex(&r, mpstr);
    +    printf("r : %s\n", mpstr);
    +#endif
    +
    +    CHECK_MPI_OK( mp_invmod(&k, &n, &k) );      /* k = k**-1 mod n */
    +    CHECK_MPI_OK( mp_mulmod(&d, &r, &n, &d) );  /* d = d * r mod n */
    +    CHECK_MPI_OK( mp_addmod(&s, &d, &n, &s) );  /* s = s + d mod n */
    +    CHECK_MPI_OK( mp_mulmod(&s, &k, &n, &s) );  /* s = s * k mod n */
    +
    +#if EC_DEBUG
    +    mp_todecimal(&s, mpstr);
    +    printf("s : %s (dec)\n", mpstr);
    +    mp_tohex(&s, mpstr);
    +    printf("s : %s\n", mpstr);
    +#endif
    +
    +    /*
    +    ** ANSI X9.62, Section 5.3.3, Step 5
    +    **
    +    ** verify s != 0
    +    */
    +    if (mp_cmp_z(&s) == 0) {
    +        PORT_SetError(SEC_ERROR_NEED_RANDOM);
    +        goto cleanup;
    +    }
    +
    +   /*
    +    **
    +    ** Signature is tuple (r, s)
    +    */
    +    CHECK_MPI_OK( mp_to_fixlen_octets(&r, signature->data, olen) );
    +    CHECK_MPI_OK( mp_to_fixlen_octets(&s, signature->data + olen, olen) );
    +finish:
    +    signature->len = 2*olen;
    +
    +    rv = SECSuccess;
    +    err = MP_OKAY;
    +cleanup:
    +    mp_clear(&x1);
    +    mp_clear(&d);
    +    mp_clear(&k);
    +    mp_clear(&r);
    +    mp_clear(&s);
    +    mp_clear(&n);
    +
    +    if (kGpoint.data) {
    +        PORT_ZFree(kGpoint.data, 2*flen + 1);
    +    }
    +
    +    if (err) {
    +        MP_TO_SEC_ERROR(err);
    +        rv = SECFailure;
    +    }
    +
    +#if EC_DEBUG
    +    printf("ECDSA signing with seed %s\n",
    +        (rv == SECSuccess) ? "succeeded" : "failed");
    +#endif
    +
    +   return rv;
    +}
    +
    +/*
    +** Computes the ECDSA signature on the digest using the given key
    +** and a random seed.
    +*/
    +SECStatus
    +ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest,
    +    const unsigned char* random, int randomLen, int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    int len;
    +    unsigned char *kBytes= NULL;
    +
    +    if (!key) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        return SECFailure;
    +    }
    +
    +    /* Generate random value k */
    +    len = key->ecParams.order.len;
    +    kBytes = ec_GenerateRandomPrivateKey(key->ecParams.order.data, len,
    +        random, randomLen, kmflag);
    +    if (kBytes == NULL) goto cleanup;
    +
    +    /* Generate ECDSA signature with the specified k value */
    +    rv = ECDSA_SignDigestWithSeed(key, signature, digest, kBytes, len, kmflag);
    +
    +cleanup:
    +    if (kBytes) {
    +        PORT_ZFree(kBytes, len * 2);
    +    }
    +
    +#if EC_DEBUG
    +    printf("ECDSA signing %s\n",
    +        (rv == SECSuccess) ? "succeeded" : "failed");
    +#endif
    +
    +    return rv;
    +}
    +
    +/*
    +** Checks the signature on the given digest using the key provided.
    +*/
    +SECStatus
    +ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
    +                 const SECItem *digest, int kmflag)
    +{
    +    SECStatus rv = SECFailure;
    +    mp_int r_, s_;           /* tuple (r', s') is received signature) */
    +    mp_int c, u1, u2, v;     /* intermediate values used in verification */
    +    mp_int x1;
    +    mp_int n;
    +    mp_err err = MP_OKAY;
    +    ECParams *ecParams = NULL;
    +    SECItem pointC = { siBuffer, NULL, 0 };
    +    int slen;       /* length in bytes of a half signature (r or s) */
    +    int flen;       /* length in bytes of the field size */
    +    unsigned olen;  /* length in bytes of the base point order */
    +
    +#if EC_DEBUG
    +    char mpstr[256];
    +    printf("ECDSA verification called\n");
    +#endif
    +
    +    /* Initialize MPI integers. */
    +    /* must happen before the first potential call to cleanup */
    +    MP_DIGITS(&r_) = 0;
    +    MP_DIGITS(&s_) = 0;
    +    MP_DIGITS(&c) = 0;
    +    MP_DIGITS(&u1) = 0;
    +    MP_DIGITS(&u2) = 0;
    +    MP_DIGITS(&x1) = 0;
    +    MP_DIGITS(&v)  = 0;
    +    MP_DIGITS(&n)  = 0;
    +
    +    /* Check args */
    +    if (!key || !signature || !digest) {
    +        PORT_SetError(SEC_ERROR_INVALID_ARGS);
    +        goto cleanup;
    +    }
    +
    +    ecParams = &(key->ecParams);
    +    flen = (ecParams->fieldID.size + 7) >> 3;
    +    olen = ecParams->order.len;
    +    if (signature->len == 0 || signature->len%2 != 0 ||
    +        signature->len > 2*olen) {
    +        PORT_SetError(SEC_ERROR_INPUT_LEN);
    +        goto cleanup;
    +    }
    +    slen = signature->len/2;
    +
    +    SECITEM_AllocItem(NULL, &pointC, 2*flen + 1, kmflag);
    +    if (pointC.data == NULL)
    +        goto cleanup;
    +
    +    CHECK_MPI_OK( mp_init(&r_, kmflag) );
    +    CHECK_MPI_OK( mp_init(&s_, kmflag) );
    +    CHECK_MPI_OK( mp_init(&c, kmflag)  );
    +    CHECK_MPI_OK( mp_init(&u1, kmflag) );
    +    CHECK_MPI_OK( mp_init(&u2, kmflag) );
    +    CHECK_MPI_OK( mp_init(&x1, kmflag)  );
    +    CHECK_MPI_OK( mp_init(&v, kmflag)  );
    +    CHECK_MPI_OK( mp_init(&n, kmflag)  );
    +
    +    /*
    +    ** Convert received signature (r', s') into MPI integers.
    +    */
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&r_, signature->data, slen) );
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&s_, signature->data + slen, slen) );
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.2, Steps 1 and 2
    +    **
    +    ** Verify that 0 < r' < n and 0 < s' < n
    +    */
    +    SECITEM_TO_MPINT(ecParams->order, &n);
    +    if (mp_cmp_z(&r_) <= 0 || mp_cmp_z(&s_) <= 0 ||
    +        mp_cmp(&r_, &n) >= 0 || mp_cmp(&s_, &n) >= 0) {
    +        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    +        goto cleanup; /* will return rv == SECFailure */
    +    }
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.2, Step 3
    +    **
    +    ** c = (s')**-1 mod n
    +    */
    +    CHECK_MPI_OK( mp_invmod(&s_, &n, &c) );      /* c = (s')**-1 mod n */
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.2, Step 4
    +    **
    +    ** u1 = ((HASH(M')) * c) mod n
    +    */
    +    SECITEM_TO_MPINT(*digest, &u1);                  /* u1 = HASH(M)     */
    +
    +    /* In the definition of EC signing, digests are truncated
    +     * to the length of n in bits.
    +     * (see SEC 1 "Elliptic Curve Digit Signature Algorithm" section 4.1.*/
    +    if (digest->len*8 > ecParams->fieldID.size) {  /* u1 = HASH(M')     */
    +        mpl_rsh(&u1,&u1,digest->len*8- ecParams->fieldID.size);
    +    }
    +
    +#if EC_DEBUG
    +    mp_todecimal(&r_, mpstr);
    +    printf("r_: %s (dec)\n", mpstr);
    +    mp_todecimal(&s_, mpstr);
    +    printf("s_: %s (dec)\n", mpstr);
    +    mp_todecimal(&c, mpstr);
    +    printf("c : %s (dec)\n", mpstr);
    +    mp_todecimal(&u1, mpstr);
    +    printf("digest: %s (dec)\n", mpstr);
    +#endif
    +
    +    CHECK_MPI_OK( mp_mulmod(&u1, &c, &n, &u1) );  /* u1 = u1 * c mod n */
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.2, Step 4
    +    **
    +    ** u2 = ((r') * c) mod n
    +    */
    +    CHECK_MPI_OK( mp_mulmod(&r_, &c, &n, &u2) );
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.3, Step 1
    +    **
    +    ** Compute u1*G + u2*Q
    +    ** Here, A = u1.G     B = u2.Q    and   C = A + B
    +    ** If the result, C, is the point at infinity, reject the signature
    +    */
    +    if (ec_points_mul(ecParams, &u1, &u2, &key->publicValue, &pointC, kmflag)
    +        != SECSuccess) {
    +        rv = SECFailure;
    +        goto cleanup;
    +    }
    +    if (ec_point_at_infinity(&pointC)) {
    +        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    +        rv = SECFailure;
    +        goto cleanup;
    +    }
    +
    +    CHECK_MPI_OK( mp_read_unsigned_octets(&x1, pointC.data + 1, flen) );
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.4, Step 2
    +    **
    +    ** v = x1 mod n
    +    */
    +    CHECK_MPI_OK( mp_mod(&x1, &n, &v) );
    +
    +#if EC_DEBUG
    +    mp_todecimal(&r_, mpstr);
    +    printf("r_: %s (dec)\n", mpstr);
    +    mp_todecimal(&v, mpstr);
    +    printf("v : %s (dec)\n", mpstr);
    +#endif
    +
    +    /*
    +    ** ANSI X9.62, Section 5.4.4, Step 3
    +    **
    +    ** Verification:  v == r'
    +    */
    +    if (mp_cmp(&v, &r_)) {
    +        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
    +        rv = SECFailure; /* Signature failed to verify. */
    +    } else {
    +        rv = SECSuccess; /* Signature verified. */
    +    }
    +
    +#if EC_DEBUG
    +    mp_todecimal(&u1, mpstr);
    +    printf("u1: %s (dec)\n", mpstr);
    +    mp_todecimal(&u2, mpstr);
    +    printf("u2: %s (dec)\n", mpstr);
    +    mp_tohex(&x1, mpstr);
    +    printf("x1: %s\n", mpstr);
    +    mp_todecimal(&v, mpstr);
    +    printf("v : %s (dec)\n", mpstr);
    +#endif
    +
    +cleanup:
    +    mp_clear(&r_);
    +    mp_clear(&s_);
    +    mp_clear(&c);
    +    mp_clear(&u1);
    +    mp_clear(&u2);
    +    mp_clear(&x1);
    +    mp_clear(&v);
    +    mp_clear(&n);
    +
    +    if (pointC.data) SECITEM_FreeItem(&pointC, PR_FALSE);
    +    if (err) {
    +        MP_TO_SEC_ERROR(err);
    +        rv = SECFailure;
    +    }
    +
    +#if EC_DEBUG
    +    printf("ECDSA verification %s\n",
    +        (rv == SECSuccess) ? "succeeded" : "failed");
    +#endif
    +
    +    return rv;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ec.h b/jdk/src/share/native/sun/security/ec/ec.h
    new file mode 100644
    index 00000000000..d472670913b
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec.h
    @@ -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 , 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_ */
    diff --git a/jdk/src/share/native/sun/security/ec/ec2.h b/jdk/src/share/native/sun/security/ec/ec2.h
    new file mode 100644
    index 00000000000..c1b2d7965e5
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec2.h
    @@ -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 , 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 */
    diff --git a/jdk/src/share/native/sun/security/ec/ec2_163.c b/jdk/src/share/native/sun/security/ec/ec2_163.c
    new file mode 100644
    index 00000000000..ecdb5121063
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec2_163.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila , Sun Microsystems Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ec2_193.c b/jdk/src/share/native/sun/security/ec/ec2_193.c
    new file mode 100644
    index 00000000000..f6187d35612
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec2_193.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila , Sun Microsystems Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ec2_233.c b/jdk/src/share/native/sun/security/ec/ec2_233.c
    new file mode 100644
    index 00000000000..2b29c46ea76
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec2_233.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila , Sun Microsystems Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ec2_aff.c b/jdk/src/share/native/sun/security/ec/ec2_aff.c
    new file mode 100644
    index 00000000000..bb52cbc97f9
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec2_aff.c
    @@ -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 , 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ec2_mont.c b/jdk/src/share/native/sun/security/ec/ec2_mont.c
    new file mode 100644
    index 00000000000..5cef20f5303
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec2_mont.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila , Sun Microsystems Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ec_naf.c b/jdk/src/share/native/sun/security/ec/ec_naf.c
    new file mode 100644
    index 00000000000..1d110904d29
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ec_naf.c
    @@ -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 , 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;
    +
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecc_impl.h b/jdk/src/share/native/sun/security/ec/ecc_impl.h
    new file mode 100644
    index 00000000000..702ab1daeb7
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecc_impl.h
    @@ -0,0 +1,278 @@
    +/* *********************************************************************
    + *
    + * Sun elects to have this file available under and governed by the
    + * Mozilla Public License Version 1.1 ("MPL") (see
    + * http://www.mozilla.org/MPL/ for full license text). For the avoidance
    + * of doubt and subject to the following, Sun also elects to allow
    + * licensees to use this file under the MPL, the GNU General Public
    + * License version 2 only or the Lesser General Public License version
    + * 2.1 only. Any references to the "GNU General Public License version 2
    + * or later" or "GPL" in the following shall be construed to mean the
    + * GNU General Public License version 2 only. Any references to the "GNU
    + * Lesser General Public License version 2.1 or later" or "LGPL" in the
    + * following shall be construed to mean the GNU Lesser General Public
    + * License version 2.1 only. However, the following notice accompanied
    + * the original version of this file:
    + *
    + * Version: MPL 1.1/GPL 2.0/LGPL 2.1
    + *
    + * The contents of this file are subject to the Mozilla Public License Version
    + * 1.1 (the "License"); you may not use this file except in compliance with
    + * the License. You may obtain a copy of the License at
    + * http://www.mozilla.org/MPL/
    + *
    + * Software distributed under the License is distributed on an "AS IS" basis,
    + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    + * for the specific language governing rights and limitations under the
    + * License.
    + *
    + * The Original Code is the Netscape security libraries.
    + *
    + * The Initial Developer of the Original Code is
    + * Netscape Communications Corporation.
    + * Portions created by the Initial Developer are Copyright (C) 1994-2000
    + * the Initial Developer. All Rights Reserved.
    + *
    + * Contributor(s):
    + *   Dr Vipul Gupta  and
    + *   Douglas Stebila , Sun Microsystems Laboratories
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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 
    +#endif  /* _KERNEL */
    +
    +#define EC_MAX_DIGEST_LEN 1024  /* max digest that can be signed */
    +#define EC_MAX_POINT_LEN 145    /* max len of DER encoded Q */
    +#define EC_MAX_VALUE_LEN 72     /* max len of ANSI X9.62 private value d */
    +#define EC_MAX_SIG_LEN 144      /* max signature len for supported curves */
    +#define EC_MIN_KEY_LEN  112     /* min key length in bits */
    +#define EC_MAX_KEY_LEN  571     /* max key length in bits */
    +#define EC_MAX_OID_LEN 10       /* max length of OID buffer */
    +
    +/*
    + * Various structures and definitions from NSS are here.
    + */
    +
    +#ifdef _KERNEL
    +#define PORT_ArenaAlloc(a, n, f)        kmem_alloc((n), (f))
    +#define PORT_ArenaZAlloc(a, n, f)       kmem_zalloc((n), (f))
    +#define PORT_ArenaGrow(a, b, c, d)      NULL
    +#define PORT_ZAlloc(n, f)               kmem_zalloc((n), (f))
    +#define PORT_Alloc(n, f)                kmem_alloc((n), (f))
    +#else
    +#define PORT_ArenaAlloc(a, n, f)        malloc((n))
    +#define PORT_ArenaZAlloc(a, n, f)       calloc(1, (n))
    +#define PORT_ArenaGrow(a, b, c, d)      NULL
    +#define PORT_ZAlloc(n, f)               calloc(1, (n))
    +#define PORT_Alloc(n, f)                malloc((n))
    +#endif
    +
    +#define PORT_NewArena(b)                (char *)12345
    +#define PORT_ArenaMark(a)               NULL
    +#define PORT_ArenaUnmark(a, b)
    +#define PORT_ArenaRelease(a, m)
    +#define PORT_FreeArena(a, b)
    +#define PORT_Strlen(s)                  strlen((s))
    +#define PORT_SetError(e)
    +
    +#define PRBool                          boolean_t
    +#define PR_TRUE                         B_TRUE
    +#define PR_FALSE                        B_FALSE
    +
    +#ifdef _KERNEL
    +#define PORT_Assert                     ASSERT
    +#define PORT_Memcpy(t, f, l)            bcopy((f), (t), (l))
    +#else
    +#define PORT_Assert                     assert
    +#define PORT_Memcpy(t, f, l)            memcpy((t), (f), (l))
    +#endif
    +
    +#define CHECK_OK(func) if (func == NULL) goto cleanup
    +#define CHECK_SEC_OK(func) if (SECSuccess != (rv = func)) goto cleanup
    +
    +typedef enum {
    +        siBuffer = 0,
    +        siClearDataBuffer = 1,
    +        siCipherDataBuffer = 2,
    +        siDERCertBuffer = 3,
    +        siEncodedCertBuffer = 4,
    +        siDERNameBuffer = 5,
    +        siEncodedNameBuffer = 6,
    +        siAsciiNameString = 7,
    +        siAsciiString = 8,
    +        siDEROID = 9,
    +        siUnsignedInteger = 10,
    +        siUTCTime = 11,
    +        siGeneralizedTime = 12
    +} SECItemType;
    +
    +typedef struct SECItemStr SECItem;
    +
    +struct SECItemStr {
    +        SECItemType type;
    +        unsigned char *data;
    +        unsigned int len;
    +};
    +
    +typedef SECItem SECKEYECParams;
    +
    +typedef enum { ec_params_explicit,
    +               ec_params_named
    +} ECParamsType;
    +
    +typedef enum { ec_field_GFp = 1,
    +               ec_field_GF2m
    +} ECFieldType;
    +
    +struct ECFieldIDStr {
    +    int         size;   /* field size in bits */
    +    ECFieldType type;
    +    union {
    +        SECItem  prime; /* prime p for (GFp) */
    +        SECItem  poly;  /* irreducible binary polynomial for (GF2m) */
    +    } u;
    +    int         k1;     /* first coefficient of pentanomial or
    +                         * the only coefficient of trinomial
    +                         */
    +    int         k2;     /* two remaining coefficients of pentanomial */
    +    int         k3;
    +};
    +typedef struct ECFieldIDStr ECFieldID;
    +
    +struct ECCurveStr {
    +        SECItem a;      /* contains octet stream encoding of
    +                         * field element (X9.62 section 4.3.3)
    +                         */
    +        SECItem b;
    +        SECItem seed;
    +};
    +typedef struct ECCurveStr ECCurve;
    +
    +typedef void PRArenaPool;
    +
    +struct ECParamsStr {
    +    PRArenaPool * arena;
    +    ECParamsType  type;
    +    ECFieldID     fieldID;
    +    ECCurve       curve;
    +    SECItem       base;
    +    SECItem       order;
    +    int           cofactor;
    +    SECItem       DEREncoding;
    +    ECCurveName   name;
    +    SECItem       curveOID;
    +};
    +typedef struct ECParamsStr ECParams;
    +
    +struct ECPublicKeyStr {
    +    ECParams ecParams;
    +    SECItem publicValue;   /* elliptic curve point encoded as
    +                            * octet stream.
    +                            */
    +};
    +typedef struct ECPublicKeyStr ECPublicKey;
    +
    +struct ECPrivateKeyStr {
    +    ECParams ecParams;
    +    SECItem publicValue;   /* encoded ec point */
    +    SECItem privateValue;  /* private big integer */
    +    SECItem version;       /* As per SEC 1, Appendix C, Section C.4 */
    +};
    +typedef struct ECPrivateKeyStr ECPrivateKey;
    +
    +typedef enum _SECStatus {
    +        SECBufferTooSmall = -3,
    +        SECWouldBlock = -2,
    +        SECFailure = -1,
    +        SECSuccess = 0
    +} SECStatus;
    +
    +#ifdef _KERNEL
    +#define RNG_GenerateGlobalRandomBytes(p,l) ecc_knzero_random_generator((p), (l))
    +#else
    +/*
    + This function is no longer required because the random bytes are now
    + supplied by the caller. Force a failure.
    +VR
    +#define RNG_GenerateGlobalRandomBytes(p,l) SECFailure
    +*/
    +#define RNG_GenerateGlobalRandomBytes(p,l) SECSuccess
    +#endif
    +#define CHECK_MPI_OK(func) if (MP_OKAY > (err = func)) goto cleanup
    +#define MP_TO_SEC_ERROR(err)
    +
    +#define SECITEM_TO_MPINT(it, mp)                                        \
    +        CHECK_MPI_OK(mp_read_unsigned_octets((mp), (it).data, (it).len))
    +
    +extern int ecc_knzero_random_generator(uint8_t *, size_t);
    +extern ulong_t soft_nzero_random_generator(uint8_t *, ulong_t);
    +
    +extern SECStatus EC_DecodeParams(const SECItem *, ECParams **, int);
    +extern SECItem * SECITEM_AllocItem(PRArenaPool *, SECItem *, unsigned int, int);
    +extern SECStatus SECITEM_CopyItem(PRArenaPool *, SECItem *, const SECItem *,
    +    int);
    +extern void SECITEM_FreeItem(SECItem *, boolean_t);
    +extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, const unsigned char* random, int randomlen, int);
    +extern SECStatus EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey,
    +    const unsigned char *seed, int seedlen, int kmflag);
    +extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *,
    +    const unsigned char* randon, int randomlen, int);
    +extern SECStatus ECDSA_SignDigestWithSeed(ECPrivateKey *, SECItem *,
    +    const SECItem *, const unsigned char *seed, int seedlen, int kmflag);
    +extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *,
    +    const SECItem *, int);
    +extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t,
    +    SECItem *, int);
    +
    +#ifdef  __cplusplus
    +}
    +#endif
    +
    +#endif /* _ECC_IMPL_H */
    diff --git a/jdk/src/share/native/sun/security/ec/ecdecode.c b/jdk/src/share/native/sun/security/ec/ecdecode.c
    new file mode 100644
    index 00000000000..d610f3b1b5a
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecdecode.c
    @@ -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  and
    + *   Douglas Stebila , Sun Microsystems Laboratories
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
    + * Use is subject to license terms.
    + */
    +
    +#pragma ident   "%Z%%M% %I%     %E% SMI"
    +
    +#include 
    +
    +#ifndef _WIN32
    +#ifndef __linux__
    +#include 
    +#endif /* __linux__ */
    +#include 
    +#endif /* _WIN32 */
    +
    +#ifdef _KERNEL
    +#include 
    +#else
    +#include 
    +#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, ¶ms->fieldID.u.prime,
    +            curveParams->irr, kmflag));
    +    } else {
    +        CHECK_OK(hexString2SECItem(NULL, ¶ms->fieldID.u.poly,
    +            curveParams->irr, kmflag));
    +    }
    +    CHECK_OK(hexString2SECItem(NULL, ¶ms->curve.a,
    +        curveParams->curvea, kmflag));
    +    CHECK_OK(hexString2SECItem(NULL, ¶ms->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, ¶ms->base, genenc, kmflag));
    +    CHECK_OK(hexString2SECItem(NULL, ¶ms->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;
    +    }
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecl-curve.h b/jdk/src/share/native/sun/security/ec/ecl-curve.h
    new file mode 100644
    index 00000000000..bb7f9a7d466
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl-curve.h
    @@ -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 , 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 
    +#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 */
    diff --git a/jdk/src/share/native/sun/security/ec/ecl-exp.h b/jdk/src/share/native/sun/security/ec/ecl-exp.h
    new file mode 100644
    index 00000000000..ce9a2cf803c
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl-exp.h
    @@ -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 , 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 */
    diff --git a/jdk/src/share/native/sun/security/ec/ecl-priv.h b/jdk/src/share/native/sun/security/ec/ecl-priv.h
    new file mode 100644
    index 00000000000..12caaf70577
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl-priv.h
    @@ -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  and
    + *   Douglas Stebila , Sun Microsystems Laboratories
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 */
    diff --git a/jdk/src/share/native/sun/security/ec/ecl.c b/jdk/src/share/native/sun/security/ec/ecl.c
    new file mode 100644
    index 00000000000..7089a6d0e9d
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl.c
    @@ -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 , 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 
    +#include 
    +#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
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecl.h b/jdk/src/share/native/sun/security/ec/ecl.h
    new file mode 100644
    index 00000000000..9dcdbc677ce
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl.h
    @@ -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 , 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 */
    diff --git a/jdk/src/share/native/sun/security/ec/ecl_curve.c b/jdk/src/share/native/sun/security/ec/ecl_curve.c
    new file mode 100644
    index 00000000000..d2d2d82291c
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl_curve.c
    @@ -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 , 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 
    +#include 
    +#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
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecl_gf.c b/jdk/src/share/native/sun/security/ec/ecl_gf.c
    new file mode 100644
    index 00000000000..a651fa84e7c
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl_gf.c
    @@ -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  and
    + *   Douglas Stebila , Sun Microsystems Laboratories
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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);
    +        }
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecl_mult.c b/jdk/src/share/native/sun/security/ec/ecl_mult.c
    new file mode 100644
    index 00000000000..c5a01fabad3
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecl_mult.c
    @@ -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 , 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp.h b/jdk/src/share/native/sun/security/ec/ecp.h
    new file mode 100644
    index 00000000000..5e045ba6320
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp.h
    @@ -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 , 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 */
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_192.c b/jdk/src/share/native/sun/security/ec/ecp_192.c
    new file mode 100644
    index 00000000000..f2c62a40e90
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_192.c
    @@ -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 , 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_224.c b/jdk/src/share/native/sun/security/ec/ecp_224.c
    new file mode 100644
    index 00000000000..1ea82fd78d7
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_224.c
    @@ -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 , 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_256.c b/jdk/src/share/native/sun/security/ec/ecp_256.c
    new file mode 100644
    index 00000000000..6f4de5be0ee
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_256.c
    @@ -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 
    + *
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_384.c b/jdk/src/share/native/sun/security/ec/ecp_384.c
    new file mode 100644
    index 00000000000..93b9259da6b
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_384.c
    @@ -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 
    + *
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_521.c b/jdk/src/share/native/sun/security/ec/ecp_521.c
    new file mode 100644
    index 00000000000..68dca16a774
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_521.c
    @@ -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 
    + *
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_aff.c b/jdk/src/share/native/sun/security/ec/ecp_aff.c
    new file mode 100644
    index 00000000000..f8d88d4dcbc
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_aff.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila , Sun Microsystems Laboratories.
    + *   Bodo Moeller ,
    + *   Nils Larsch , and
    + *   Lenka Fibikova , the OpenSSL Project
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_jac.c b/jdk/src/share/native/sun/security/ec/ecp_jac.c
    new file mode 100644
    index 00000000000..47c0e195dc1
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_jac.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila , Sun Microsystems Laboratories.
    + *   Bodo Moeller ,
    + *   Nils Larsch , and
    + *   Lenka Fibikova , the OpenSSL Project
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#endif
    +#ifdef ECL_DEBUG
    +#include 
    +#endif
    +
    +/* Converts a point P(px, py) from affine coordinates to Jacobian
    + * projective coordinates R(rx, ry, rz). Assumes input is already
    + * field-encoded using field_enc, and returns output that is still
    + * field-encoded. */
    +mp_err
    +ec_GFp_pt_aff2jac(const mp_int *px, const mp_int *py, mp_int *rx,
    +                                  mp_int *ry, mp_int *rz, const ECGroup *group)
    +{
    +        mp_err res = MP_OKAY;
    +
    +        if (ec_GFp_pt_is_inf_aff(px, py) == MP_YES) {
    +                MP_CHECKOK(ec_GFp_pt_set_inf_jac(rx, ry, rz));
    +        } else {
    +                MP_CHECKOK(mp_copy(px, rx));
    +                MP_CHECKOK(mp_copy(py, ry));
    +                MP_CHECKOK(mp_set_int(rz, 1));
    +                if (group->meth->field_enc) {
    +                        MP_CHECKOK(group->meth->field_enc(rz, rz, group->meth));
    +                }
    +        }
    +  CLEANUP:
    +        return res;
    +}
    +
    +/* Converts a point P(px, py, pz) from Jacobian projective coordinates to
    + * affine coordinates R(rx, ry).  P and R can share x and y coordinates.
    + * Assumes input is already field-encoded using field_enc, and returns
    + * output that is still field-encoded. */
    +mp_err
    +ec_GFp_pt_jac2aff(const mp_int *px, const mp_int *py, const mp_int *pz,
    +                                  mp_int *rx, mp_int *ry, const ECGroup *group)
    +{
    +        mp_err res = MP_OKAY;
    +        mp_int z1, z2, z3;
    +
    +        MP_DIGITS(&z1) = 0;
    +        MP_DIGITS(&z2) = 0;
    +        MP_DIGITS(&z3) = 0;
    +        MP_CHECKOK(mp_init(&z1, 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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_jm.c b/jdk/src/share/native/sun/security/ec/ecp_jm.c
    new file mode 100644
    index 00000000000..a5e38db21da
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_jm.c
    @@ -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 , 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 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/ecp_mont.c b/jdk/src/share/native/sun/security/ec/ecp_mont.c
    new file mode 100644
    index 00000000000..6b4dbb29e25
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/ecp_mont.c
    @@ -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 , 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 
    +#include 
    +#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;
    +        }
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/logtab.h b/jdk/src/share/native/sun/security/ec/logtab.h
    new file mode 100644
    index 00000000000..6efa0199560
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/logtab.h
    @@ -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 , 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 */
    diff --git a/jdk/src/share/native/sun/security/ec/mp_gf2m-priv.h b/jdk/src/share/native/sun/security/ec/mp_gf2m-priv.h
    new file mode 100644
    index 00000000000..7a4505807fc
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mp_gf2m-priv.h
    @@ -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  and
    + *   Douglas Stebila  of Sun Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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_ */
    diff --git a/jdk/src/share/native/sun/security/ec/mp_gf2m.c b/jdk/src/share/native/sun/security/ec/mp_gf2m.c
    new file mode 100644
    index 00000000000..74b64789c96
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mp_gf2m.c
    @@ -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  and
    + *   Douglas Stebila  of Sun Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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<> 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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/mp_gf2m.h b/jdk/src/share/native/sun/security/ec/mp_gf2m.h
    new file mode 100644
    index 00000000000..b09f3d34377
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mp_gf2m.h
    @@ -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  and
    + *   Douglas Stebila  of Sun Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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_ */
    diff --git a/jdk/src/share/native/sun/security/ec/mpi-config.h b/jdk/src/share/native/sun/security/ec/mpi-config.h
    new file mode 100644
    index 00000000000..3618677a90a
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mpi-config.h
    @@ -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 */
    diff --git a/jdk/src/share/native/sun/security/ec/mpi-priv.h b/jdk/src/share/native/sun/security/ec/mpi-priv.h
    new file mode 100644
    index 00000000000..b2b07ec3210
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mpi-priv.h
    @@ -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 
    +#include 
    +#include 
    +#endif /* _KERNEL */
    +
    +#if MP_DEBUG
    +#include 
    +
    +#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 
    +#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 */
    diff --git a/jdk/src/share/native/sun/security/ec/mpi.c b/jdk/src/share/native/sun/security/ec/mpi.c
    new file mode 100644
    index 00000000000..9f771882b01
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mpi.c
    @@ -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  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 
    +#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 a0 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(") = 0;
    +  /* Make room for the quotient */
    +  MP_CHECKOK( mp_init_size(", 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(", 1);
    +    DIGIT(", 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(", 0) = d;
    +    MP_CHECKOK( s_mp_norm(&rem, ", &norm) );
    +    if (norm)
    +      d <<= norm;
    +    MP_DIGIT(", 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(", 1) );
    +      DIGIT(", 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(");
    +  mp_exch(", mp);
    +CLEANUP:
    +  mp_clear(");
    +  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 a0 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 a0 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                                                  */
    diff --git a/jdk/src/share/native/sun/security/ec/mpi.h b/jdk/src/share/native/sun/security/ec/mpi.h
    new file mode 100644
    index 00000000000..5f70b763209
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mpi.h
    @@ -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 
    +#endif /* _WIN32 */
    +
    +#ifdef _KERNEL
    +#include 
    +#include 
    +#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 
    +#include 
    +#endif
    +
    +#ifndef _KERNEL
    +#include 
    +#endif
    +
    +#if defined(BSDI)
    +#undef ULLONG_MAX
    +#endif
    +
    +#if defined( macintosh )
    +#include 
    +#elif defined( _WIN32_WCE)
    +/* #include  What do we need here ?? */
    +#else
    +#include 
    +#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 
    +#define  ARGCHK(X,Y)  assert(X)
    +#endif
    +#else
    +#define  ARGCHK(X,Y)  /*  */
    +#endif
    +#endif /* defined MP_API_COMPATIBLE */
    +
    +#endif /* _MPI_H */
    diff --git a/jdk/src/share/native/sun/security/ec/mplogic.c b/jdk/src/share/native/sun/security/ec/mplogic.c
    new file mode 100644
    index 00000000000..6a5f00a1c36
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mplogic.c
    @@ -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                                                  */
    diff --git a/jdk/src/share/native/sun/security/ec/mplogic.h b/jdk/src/share/native/sun/security/ec/mplogic.h
    new file mode 100644
    index 00000000000..97ddb49c7ea
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mplogic.h
    @@ -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 */
    diff --git a/jdk/src/share/native/sun/security/ec/mpmontg.c b/jdk/src/share/native/sun/security/ec/mpmontg.c
    new file mode 100644
    index 00000000000..df17f427321
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mpmontg.c
    @@ -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 ,
    + *   Stephen Fung , and
    + *   Douglas Stebila  of Sun Laboratories.
    + *
    + * Alternatively, the contents of this file may be used under the terms of
    + * either the GNU General Public License Version 2 or later (the "GPL"), or
    + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    + * in which case the provisions of the GPL or the LGPL are applicable instead
    + * of those above. If you wish to allow use of your version of this file only
    + * under the terms of either the GPL or the LGPL, and not to allow others to
    + * use your version of this file under the terms of the MPL, indicate your
    + * decision by deleting the provisions above and replace them with the notice
    + * and other provisions required by the GPL or the LGPL. If you do not delete
    + * the provisions above, a recipient may use your version of this file under
    + * the terms of any one of the MPL, the GPL or the LGPL.
    + *
    + *********************************************************************** */
    +/*
    + * 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 
    +#include  /* 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
    diff --git a/jdk/src/share/native/sun/security/ec/mpprime.h b/jdk/src/share/native/sun/security/ec/mpprime.h
    new file mode 100644
    index 00000000000..78bcb18352a
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/mpprime.h
    @@ -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 */
    diff --git a/jdk/src/share/native/sun/security/ec/oid.c b/jdk/src/share/native/sun/security/ec/oid.c
    new file mode 100644
    index 00000000000..f3ced99bcb5
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/oid.c
    @@ -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 , 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 
    +
    +#ifndef _WIN32
    +#ifndef __linux__
    +#include 
    +#endif /* __linux__ */
    +#include 
    +#endif /* _WIN32 */
    +
    +#ifdef _KERNEL
    +#include 
    +#else
    +#include 
    +#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;
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/secitem.c b/jdk/src/share/native/sun/security/ec/secitem.c
    new file mode 100644
    index 00000000000..d9daacc8bc4
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/secitem.c
    @@ -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 
    +
    +#ifndef _WIN32
    +#ifndef __linux__
    +#include 
    +#endif /* __linux__ */
    +#include 
    +#endif /* _WIN32 */
    +
    +#ifdef _KERNEL
    +#include 
    +#else
    +#include 
    +
    +#ifndef _WIN32
    +#include 
    +#endif /* _WIN32 */
    +
    +#include 
    +#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
    +        }
    +    }
    +}
    diff --git a/jdk/src/share/native/sun/security/ec/secoidt.h b/jdk/src/share/native/sun/security/ec/secoidt.h
    new file mode 100644
    index 00000000000..0935388cdb8
    --- /dev/null
    +++ b/jdk/src/share/native/sun/security/ec/secoidt.h
    @@ -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 , 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_ */
    diff --git a/jdk/test/sun/security/ec/TestEC.java b/jdk/test/sun/security/ec/TestEC.java
    new file mode 100644
    index 00000000000..0f87692a01a
    --- /dev/null
    +++ b/jdk/test/sun/security/ec/TestEC.java
    @@ -0,0 +1,66 @@
    +/*
    + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
    + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    + *
    + * This code is free software; you can redistribute it and/or modify it
    + * under the terms of the GNU General Public License version 2 only, as
    + * published by the Free Software Foundation.
    + *
    + * This code is distributed in the hope that it will be useful, but WITHOUT
    + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    + * version 2 for more details (a copy is included in the LICENSE file that
    + * accompanied this code).
    + *
    + * You should have received a copy of the GNU General Public License version
    + * 2 along with this work; if not, write to the Free Software Foundation,
    + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    + *
    + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    + * CA 95054 USA or visit www.sun.com if you need additional information or
    + * have any questions.
    + */
    +
    +/**
    + * @test
    + * @bug 6840752
    + * @summary  Provide out-of-the-box support for ECC algorithms
    + * @library ../pkcs11
    + * @library ../pkcs11/ec
    + * @run main TestEC
    + */
    +
    +import java.security.Provider;
    +
    +/*
    + * Leverage the collection of EC tests used by PKCS11
    + *
    + * NOTE: the following files were copied here from the PKCS11 EC Test area
    + *       and must be kept in sync with the originals:
    + *
    + *           ../pkcs11/ec/p12passwords.txt
    + *           ../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12
    + *           ../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12
    + */
    +
    +public class TestEC {
    +
    +    public static void main(String[] args) throws Exception {
    +        Provider p = new sun.security.ec.SunEC();
    +        System.out.println("Running tests with " + p.getName() +
    +            " provider...\n");
    +
    +        long start = System.currentTimeMillis();
    +        new TestECDH().main(p);
    +        new TestECDSA().main(p);
    +        //new TestCurves().main(p);
    +        new TestKeyFactory().main(p);
    +        new TestECGenSpec().main(p);
    +        new ReadPKCS12().main(p);
    +        //new ReadCertificates().main(p);
    +        long stop = System.currentTimeMillis();
    +
    +        System.out.println("\nCompleted tests with " + p.getName() +
    +            " provider (" + (stop - start) + " ms).");
    +    }
    +}
    diff --git a/jdk/test/sun/security/ec/p12passwords.txt b/jdk/test/sun/security/ec/p12passwords.txt
    new file mode 100644
    index 00000000000..62f620cbdba
    --- /dev/null
    +++ b/jdk/test/sun/security/ec/p12passwords.txt
    @@ -0,0 +1,18 @@
    +# MS_ECC_Samples.zip
    +256-ecc.pfx ecc
    +256_2-ecc.pfx ecc
    +384-ecc.pfx ecc
    +521-ecc.pfx ecc
    +# MS_Client_certs.zip
    +eccclicert256.pfx 1
    +eccclicert384.pfx 1
    +eccclicert521.pfx 1
    +# NSS_ECC_PKCS12.zip
    +ECCp160.p12 ecc
    +ECCp192.p12 ecc
    +ECCp224.p12 ecc
    +ECCp256.p12 ecc
    +ECCp384.p12 ecc
    +ECCp521.p12 ecc
    +# All other files
    +* password
    diff --git a/jdk/test/sun/security/ec/pkcs12/secp256r1server-secp384r1ca.p12 b/jdk/test/sun/security/ec/pkcs12/secp256r1server-secp384r1ca.p12
    new file mode 100644
    index 0000000000000000000000000000000000000000..1a23788103d6806f2e5e95ca871e4a2426ae705f
    GIT binary patch
    literal 1273
    zcmXqLV)@F%$ZXKWvYU-ltIebBJ1-+Uf{wF9++VsK}*HWcjpIJkd*1GF{u|gMH~)tC_D|V;eW>
    zTF(}r6(=*}uZz9)r;-EGbKfgy>+&b>the!xvRqd#ck{j1haJIN;$NTERobaG@l(F2
    zXyYw;zhjH0v)`zDpD6K$TSBnERW|SSuO&>~;?qz3PCi;%BV^LOd+Ux>th|?QetcHF
    zWufw#l1&`fAABnR$|n|_lCG4Ybw4N}aBtH74?HfxjS|u`rB_*H2JL;=ByDS7df?x_
    zYq5P(^3@zIb)H>y*dw{wX2#A_8T%6X{uvs)_gWWh^5Dd>zD<(_3xi5tY1WyVgz3o6
    zSRBF>C~{^_*<6|Qx7@j}{TbGLaIzCJdGyD+?Rxav`x_VD)c&npM1Jy-GJ%
    zlHq)xEBqd{{};R8Gs^Z@P;8jBm8Ho^ZXOAp8V5Df1J~j4nRI!8q%qvHm_Z+%uZ=q*%e2>+Enfx!j
    z8>RK9t2UpN`%&83w#X{;mF=VK$>(3aNXfDml(JUZ%6cj5_}^>KK7T*GBw4xL=jrXa
    zy^|kL)BmJ)^WkJS?+MQ|R(El>6n+w4;(Xrc-y+*w_BFFpkEpLwOZ_{cG^zRL;+o|l+ILSr<#7r?6f$=Dxx4@WPREzN(!{n%CG-!1=))_--p
    zw`9ASiLtILpU|tDx;AYy`W}B@49rrDzDOBoK@+1LOB16NP}mHJjo7$h*@%mgX+h%_
    zgT{?0d5am8w{~kvMYFf^2!iq!OXGy_Wk&j;ec9%B#aSo(yqXi2di|u)T<5LlU&lB5
    zrWJ%QHIO@=qUZ9+hPmoxf2PIar-#f}ZB_I*kQ09Thw|r79?@re4@T$an(R7xIY?)^
    z!>xNo#o?C|x%%H!NxpC9zU5o-VzP2mo;=_7ht4&|J;EvXEvGfSsN3CJ!y(@}Ni5#w
    zZhy-YQK>CQdO5^byqRIC?QfW4pbYmSr>LPAi-^%JmF-6sCoZx1bdi5?Ip_R)51zj?
    za78E*F|?2~V<=`wWk_ZyU@&4ZWiVqXVlV`Y6fu+m#funp;qt}|77Qj}`DBJf149Ev
    z15P$pZ9ZluDOLs+kzKq=j(h#x7T(U<#Gp6nHSa3r`A1kd?%s0uuesQ21qw3&G^`!C
    
    literal 0
    HcmV?d00001
    
    diff --git a/jdk/test/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12 b/jdk/test/sun/security/ec/pkcs12/sect193r1server-rsa1024ca.p12
    new file mode 100644
    index 0000000000000000000000000000000000000000..ed4d861e4ca49cf3a574a67f52b8848306f69fe2
    GIT binary patch
    literal 1252
    zcmXqLVtK&C$ZXKWvW$&WtIebBJ1-+U
    zf*B7y*8H!PHP@--pWdg159{8oE>R6m)wk>WC-#}!CAi~)#Qe3%t3G7RHLhB6G3VBr
    zsam~pr$b~JoqaD@f3ww-*_7&(^@0CU%AUK9TNozJy;J
    zA7PNCc`xB|X#PBgLcL|dihD|5Imy2b+;5xJy86Q6Ko{;bcGD>-0XH9O>^{9?%CyrFNPi9h6tIuZC|cW?f$#JkV`Pc@HGT<*c7BJ*hBjd$%U
    zuH^Zo$i-^BSK(NAO@8O=yXTmHy%#FlW4PiRXYwm9MN98S+wG|)qOvB8J=a3}51jQ&
    zdUff@_AO$SR*pM;H~#v!$nV&rFUJk9HyUkYn3NqEIYl{LncUU=DVDG7Y{OL+$*Mz)HLGI&igYeIp}a+FUfw3f%!@%El>e5}w$GFM?9bMJwFcw4$72LN&vV>2*wAd==+ruV(-DRqiv#?1DNU!NVr)y=ohx{-$o~4PX}e
    z!=!n5PJPnx@ch@^k#p2SrY_I=mVbxMhx<|28nKOTF-A#q?_9f(v7lt;iR%Ji|4rQ3
    z_w>;R!wdsuxKB7m4aHbQ%(i78Tos*n{`+?GnHwY2G7II;tuSyzC=xL=kuzc_W=Lg7
    zW+-7WWUyo~W+(#EAdw=5GBBwNWEC?c0!0lNj2KLSDiaM14HOMH*;uvtn3<$l8CXPw
    m=X>2;aJj?&kK>Uw>3dZEw|#JxVBv_JE&b=r+-3_
    Date: Tue, 11 Aug 2009 20:02:43 -0600
    Subject: [PATCH 65/70] 6870298: 4/4 fix minor typos in
     java/lang/instrument/Instrumentation.java
    
    Fix typos in the JavaDoc.
    
    Reviewed-by: tbell
    ---
     .../java/lang/instrument/Instrumentation.java        | 12 ++++++------
     1 file changed, 6 insertions(+), 6 deletions(-)
    
    diff --git a/jdk/src/share/classes/java/lang/instrument/Instrumentation.java b/jdk/src/share/classes/java/lang/instrument/Instrumentation.java
    index e2b58b54872..4c2dc1ae976 100644
    --- a/jdk/src/share/classes/java/lang/instrument/Instrumentation.java
    +++ b/jdk/src/share/classes/java/lang/instrument/Instrumentation.java
    @@ -81,7 +81,7 @@ public interface Instrumentation {
          * an exception during execution, the JVM will still call the other registered
          * transformers in order. The same transformer may be added more than once,
          * but it is strongly discouraged -- avoid this by creating a new instance of
    -     * tranformer class.
    +     * transformer class.
          * 

    * This method is intended for use in instrumentation, as described in the * {@linkplain Instrumentation class specification}. @@ -183,7 +183,7 @@ public interface Instrumentation { *

    * * The order of transformation is described in the - * ({@link java.lang.instrument.ClassFileTransformer#transform transform} method. + * {@link java.lang.instrument.ClassFileTransformer#transform transform} method. * This same order is used in the automatic reapplication of retransformation * incapable transforms. *

    @@ -424,7 +424,7 @@ public interface Instrumentation { * classes or resources other than those to be defined by the bootstrap * class loader for the purpose of instrumentation. * Failure to observe this warning could result in unexpected - * behaviour that is difficult to diagnose. For example, suppose there is a + * behavior that is difficult to diagnose. For example, suppose there is a * loader L, and L's parent for delegation is the bootstrap class loader. * Furthermore, a method in class C, a class defined by L, makes reference to * a non-public accessor class C$1. If the JAR file contains a class C$1 then @@ -475,9 +475,9 @@ public interface Instrumentation { * classes or resources other than those to be defined by the system class * loader for the purpose of instrumentation. * Failure to observe this warning could result in unexpected - * behaviour that is difficult to diagnose (see + * behavior that is difficult to diagnose (see * {@link #appendToBootstrapClassLoaderSearch - * appendToBootstrapClassLoaderSearch}. + * appendToBootstrapClassLoaderSearch}). * *

    The system class loader supports adding a JAR file to be searched if * it implements a method named appendToClassPathForInstrumentation @@ -485,7 +485,7 @@ public interface Instrumentation { * method is not required to have public access. The name of * the JAR file is obtained by invoking the {@link java.util.zip.ZipFile#getName * getName()} method on the jarfile and this is provided as the - * parameter to the appendtoClassPathForInstrumentation method. + * parameter to the appendToClassPathForInstrumentation method. * *

    The Java Virtual Machine * Specification specifies that a subsequent attempt to resolve a symbolic From 0ce3618e919621a882754ff589854272417af5cf Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 13 Aug 2009 12:11:02 -0700 Subject: [PATCH 66/70] Added tag jdk7-b69 for changeset f6b28dd0120d --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 887ebba35be..00d9ea8d48a 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -43,3 +43,4 @@ e01380cd1de4ce048b87d059d238e5ab5e341947 jdk7-b65 6bad5e3fe50337d95b1416d744780d65bc570da6 jdk7-b66 c4523c6f82048f420bf0d57c4cd47976753b7d2c jdk7-b67 e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68 +82e6c820c51ac27882b77755d42efefdbf1dcda0 jdk7-b69 From 7918093df4afecc70ec4a85898ee16b6cf639245 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 13 Aug 2009 12:11:03 -0700 Subject: [PATCH 67/70] Added tag jdk7-b69 for changeset 3b0aa8182028 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index 28557923b83..7b5e9dd43b1 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -43,3 +43,4 @@ d20e45cd539f20405ff843652069cfd7550c5ab3 jdk7-b63 a821e059a961bcb02830280d51f6dd030425c066 jdk7-b66 a12ea7c7b497b4ba7830550095ef633bd6f43971 jdk7-b67 5182bcc9c60cac429d1f7988676cec7320752be3 jdk7-b68 +8120d308ec4e805c5588b8d9372844d781c4112d jdk7-b69 From 6c9a7e8afe725aac5c67fb9fefda5af4c40f1394 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 13 Aug 2009 12:11:07 -0700 Subject: [PATCH 68/70] Added tag jdk7-b69 for changeset 93c79b9962dd --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index a7ee64a37aa..3fcc28faf23 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -43,3 +43,4 @@ ba313800759b678979434d6da8ed3bf49eb8bea4 jdk7-b65 57c71ad0341b8b64ed20f81151eb7f06324f8894 jdk7-b66 18f526145aea355a9320b724373386fc2170f183 jdk7-b67 d07e68298d4e17ebf93d8299e43fcc3ded26472a jdk7-b68 +54fd4d9232969ea6cd3d236e5ad276183bb0d423 jdk7-b69 From 798e9abf97fbadc0a2f71808a8c8233850281d91 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 13 Aug 2009 12:11:12 -0700 Subject: [PATCH 69/70] Added tag jdk7-b69 for changeset 803bf611f5c9 --- jaxp/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 4391dbd2d7d..16b1650d547 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -43,3 +43,4 @@ a10eec7a1edf536f39b5828d8623054dbc62c2b7 jdk7-b64 22f9d5d5b5fe0f47048f41e6c6e54fee5edad0ec jdk7-b66 a033af8d824a408d3ac602205ecdefc128749e1e jdk7-b67 83b2a9331383f9db7a49350d4cb13b7635f6b861 jdk7-b68 +a4ab0d6ded63bed0fd1e5be55d38090e0ee5efb7 jdk7-b69 From 5fcd7752868a2b4b113a144a11a2039386670a19 Mon Sep 17 00:00:00 2001 From: Xiomara Jayasena Date: Thu, 13 Aug 2009 12:11:21 -0700 Subject: [PATCH 70/70] Added tag jdk7-b69 for changeset e0b23259a484 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index 1d2a3d286ba..a198de438f1 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -43,3 +43,4 @@ a50217eb3ee10b9f9547e0708e5c9625405083ef jdk7-b64 bd31b30a5b21f20e42965b1633f18a5c7946d398 jdk7-b66 a952aafd5181af953b0ef3010dbd2fcc28460e8a jdk7-b67 b23d905cb5d3b382295240d28ab0bfb266b4503c jdk7-b68 +226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69