diff --git a/.hgtags b/.hgtags index e7963e7c7abf663c3cce4ec484987792ce7dc058..1a27baa7cacebee57bcf880d40956730cf3894b2 100644 --- a/.hgtags +++ b/.hgtags @@ -46,3 +46,4 @@ b23d905cb5d3b382295240d28ab0bfb266b4503c jdk7-b68 226b20019b1f020c09ea97d137d98e011ce65d76 jdk7-b69 893bcca951b747ddcf6986362b877f0e1dbb835b jdk7-b70 b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71 +460639b036f327282832a4fe52b7aa45688afd50 jdk7-b72 diff --git a/make/java/java/FILES_java.gmk b/make/java/java/FILES_java.gmk index e8a2223f67a53e64f6f21a5fdc2fec1dc84639ba..2ad599cbe235749e97c5128835fc249191bce42c 100644 --- a/make/java/java/FILES_java.gmk +++ b/make/java/java/FILES_java.gmk @@ -454,6 +454,8 @@ JAVA_JAVA_java = \ sun/misc/JavaLangAccess.java \ sun/misc/JavaIOAccess.java \ sun/misc/JavaIOFileDescriptorAccess.java \ - sun/misc/JavaNioAccess.java + sun/misc/JavaNioAccess.java \ + sun/misc/Perf.java \ + sun/misc/PerfCounter.java FILES_java = $(JAVA_JAVA_java) diff --git a/make/java/logging/Makefile b/make/java/logging/Makefile index c6ed1879fecd64bf9d36d4fe0f2dc8061e5bef7e..444c1c63b5a76d35c182dd7667240ada67a58b8d 100644 --- a/make/java/logging/Makefile +++ b/make/java/logging/Makefile @@ -31,7 +31,7 @@ include $(BUILDDIR)/common/Defs.gmk # # Files to compile. # -AUTO_FILES_JAVA_DIRS = java/util/logging +AUTO_FILES_JAVA_DIRS = java/util/logging sun/util/logging # # Resources @@ -46,7 +46,6 @@ RESOURCE_BUNDLES_COMPILED_PROPERTIES = \ include $(BUILDDIR)/common/Classes.gmk properties: $(LIBDIR)/logging.properties - $(LIBDIR)/logging.properties: $(SHARE_SRC)/lib/logging.properties $(install-file) diff --git a/make/sun/net/FILES_java.gmk b/make/sun/net/FILES_java.gmk index 5082c3d370f152b5dca162ab8e1c724152a57ab6..19dd2d6d7f57330b1415b68dc8ff7160267ed218 100644 --- a/make/sun/net/FILES_java.gmk +++ b/make/sun/net/FILES_java.gmk @@ -86,9 +86,11 @@ FILES_java = \ sun/net/www/protocol/http/AuthCache.java \ sun/net/www/protocol/http/AuthCacheImpl.java \ sun/net/www/protocol/http/AuthCacheValue.java \ + sun/net/www/protocol/http/AuthScheme.java \ sun/net/www/protocol/http/BasicAuthentication.java \ sun/net/www/protocol/http/DigestAuthentication.java \ sun/net/www/protocol/http/NTLMAuthentication.java \ + sun/net/www/protocol/http/NTLMAuthenticationProxy.java \ sun/net/www/protocol/http/NegotiateAuthentication.java \ sun/net/www/protocol/http/NegotiatorImpl.java \ sun/net/www/protocol/http/NegotiateCallbackHandler.java \ @@ -123,8 +125,7 @@ FILES_java = \ sun/net/idn/UCharacterEnums.java \ sun/net/idn/UCharacterDirection.java \ sun/net/idn/StringPrepDataReader.java \ - sun/net/idn/StringPrep.java \ - sun/net/www/protocol/http/InMemoryCookieStore.java + sun/net/idn/StringPrep.java ifeq ($(PLATFORM), windows) FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java diff --git a/make/sun/security/Makefile b/make/sun/security/Makefile index 2b7cc6b2ab342719694df42a2015780f5c07fad8..92371cc60cbf5681f4434dbcb355ac8cafcc7117 100644 --- a/make/sun/security/Makefile +++ b/make/sun/security/Makefile @@ -60,8 +60,15 @@ ifeq ($(PLATFORM), windows) endif endif -SUBDIRS = ec other action util tools jgss krb5 smartcardio $(PKCS11) \ - $(JGSS_WRAPPER) $(MSCAPI) +# Build in-tree elliptic curve crypto provider only when +# DISABLE_INTREE_EC is not set +INTREE_EC = ec +ifdef DISABLE_INTREE_EC + INTREE_EC = +endif + +SUBDIRS = $(INTREE_EC) other action util tools jgss krb5 smartcardio \ + $(PKCS11) $(JGSS_WRAPPER) $(MSCAPI) all build clean clobber:: $(SUBDIRS-loop) diff --git a/make/sun/security/ec/Makefile b/make/sun/security/ec/Makefile index 297a2deab084778eb9f71507ecf69296fe50c012..53a3e3e9e51a16cd311deae0768090187ecb0219 100644 --- a/make/sun/security/ec/Makefile +++ b/make/sun/security/ec/Makefile @@ -24,7 +24,7 @@ # # -# Makefile for building sunec.jar and sunecc native library. +# Makefile for building sunec.jar and sunec native library. # # This file was derived from make/com/sun/crypto/provider/Makefile. # @@ -121,7 +121,15 @@ CLASSDESTDIR = $(TEMPDIR)/classes # AUTO_FILES_JAVA_DIRS = $(PKGDIR) -include $(BUILDDIR)/common/Classes.gmk +# +# Exclude the sources that get built by ../other/Makefile +# +AUTO_JAVA_PRUNE = \ + ECKeyFactory.java \ + ECParameters.java \ + ECPrivateKeyImpl.java \ + ECPublicKeyImpl.java \ + NamedCurve.java # # Some licensees do not get the native ECC sources, but we still need to @@ -130,7 +138,7 @@ include $(BUILDDIR)/common/Classes.gmk # NATIVE_ECC_AVAILABLE := $(shell \ - if [ -d $(SHARE_SRC)/native/$(PKGDIR) ] ; then \ + if [ -d $(SHARE_SRC)/native/$(PKGDIR)/impl ] ; then \ $(ECHO) true; \ else \ $(ECHO) false; \ @@ -138,7 +146,7 @@ NATIVE_ECC_AVAILABLE := $(shell \ ifeq ($(NATIVE_ECC_AVAILABLE), true) - LIBRARY = sunecc + LIBRARY = sunec # # Java files that define native methods @@ -166,12 +174,12 @@ ifeq ($(NATIVE_ECC_AVAILABLE), true) # vpath %.cpp $(SHARE_SRC)/native/$(PKGDIR) - vpath %.c $(SHARE_SRC)/native/$(PKGDIR) + vpath %.c $(SHARE_SRC)/native/$(PKGDIR)/impl # # Find include files # - OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR) + OTHER_INCLUDES += -I$(SHARE_SRC)/native/$(PKGDIR)/impl # # Compiler flags @@ -191,6 +199,10 @@ ifeq ($(NATIVE_ECC_AVAILABLE), true) include $(BUILDDIR)/common/Library.gmk +else # NATIVE_ECC_AVAILABLE + + include $(BUILDDIR)/common/Classes.gmk + endif # NATIVE_ECC_AVAILABLE # diff --git a/make/sun/security/other/Makefile b/make/sun/security/other/Makefile index 3f120fa473f18e04df7adabf9d2771dcffcd9384..2722fbc32cd643a2aa2fc67bbca8319da84fc6a6 100644 --- a/make/sun/security/other/Makefile +++ b/make/sun/security/other/Makefile @@ -44,6 +44,16 @@ AUTO_FILES_JAVA_DIRS = \ sun/security/x509 \ com/sun/net/ssl/internal/ssl +# +# EC classes used by the packages above +# +FILES_java += \ + sun/security/ec/ECKeyFactory.java \ + sun/security/ec/ECParameters.java \ + sun/security/ec/ECPrivateKeyImpl.java \ + sun/security/ec/ECPublicKeyImpl.java \ + sun/security/ec/NamedCurve.java + # # Rules # diff --git a/src/share/bin/java.h b/src/share/bin/java.h index fe039cdcc88452d2562c88e475e3478309432f79..cebdb5fc81afad84d0c6415886636434d03ab0f6 100644 --- a/src/share/bin/java.h +++ b/src/share/bin/java.h @@ -187,9 +187,6 @@ void InitLauncher(jboolean javaw); * */ typedef jclass (JNICALL FindClassFromBootLoader_t(JNIEnv *env, - const char *name, - jboolean init, - jobject loader, - jboolean throwError)); + const char *name)); jclass FindBootStrapClass(JNIEnv *env, const char *classname); #endif /* _JAVA_H_ */ diff --git a/src/share/bin/parse_manifest.c b/src/share/bin/parse_manifest.c index 6dcca091a4bb3c6be3324cda7217ad54f00342fc..a59540213c2dc4ce20585b000b725cbe5cff25c7 100644 --- a/src/share/bin/parse_manifest.c +++ b/src/share/bin/parse_manifest.c @@ -59,7 +59,7 @@ inflate_file(int fd, zentry *entry, int *size_out) char *out; z_stream zs; - if (entry->csize == 0xffffffff || entry->isize == 0xffffffff) + if (entry->csize == (size_t) -1 || entry->isize == (size_t) -1 ) return (NULL); if (lseek(fd, entry->offset, SEEK_SET) < (off_t)0) return (NULL); diff --git a/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java b/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java index 002d20785ff45dcc52fff642db6f4e5406d6f0da..1ebeb565ddbc651bb48351df81ec105bd060c799 100644 --- a/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java +++ b/src/share/classes/com/sun/rowset/JdbcRowSetResourceBundle.java @@ -133,7 +133,7 @@ public class JdbcRowSetResourceBundle implements Serializable { * This method returns an enumerated handle of the keys * which correspond to values translated to various locales. * - * @returns an enumerated keys which have messages tranlated to + * @return an enumeration of keys which have messages tranlated to * corresponding locales. */ public Enumeration getKeys() { @@ -146,7 +146,7 @@ public class JdbcRowSetResourceBundle implements Serializable { * returns the corresponding value reading it * from the Resource Bundle loaded earlier. * - * @returns value in locale specific language + * @return value in locale specific language * according to the key passed. */ public Object handleGetObject(String key) { diff --git a/src/share/classes/com/sun/rowset/JoinRowSetImpl.java b/src/share/classes/com/sun/rowset/JoinRowSetImpl.java index 7908848b2974be904947a15f01fc3c05ccc29f7d..d301c605cdb829526a5c902d1e12c374467a5530 100644 --- a/src/share/classes/com/sun/rowset/JoinRowSetImpl.java +++ b/src/share/classes/com/sun/rowset/JoinRowSetImpl.java @@ -3737,7 +3737,6 @@ public class JoinRowSetImpl extends WebRowSetImpl implements JoinRowSet { * Returns a result set containing the original value of the current * row only. * - * @return the original result set of the row * @throws SQLException if there is no current row * @see #setOriginalRow */ diff --git a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java index 8db17537187b108c21780b6d9db789a500f6ed51..f25cec7e62e0fae47927ac9c3686e17745b885d7 100644 --- a/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java +++ b/src/share/classes/com/sun/rowset/internal/WebRowSetXmlReader.java @@ -46,6 +46,17 @@ import javax.sql.rowset.spi.*; */ public class WebRowSetXmlReader implements XmlReader, Serializable { + + private JdbcRowSetResourceBundle resBundle; + + public WebRowSetXmlReader(){ + try { + resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); + } catch(IOException ioe) { + throw new RuntimeException(ioe); + } + } + /** * Parses the given WebRowSet object, getting its input from * the given java.io.Reader object. The parser will send @@ -69,17 +80,6 @@ public class WebRowSetXmlReader implements XmlReader, Serializable { * reader for the given rowset * @see XmlReaderContentHandler */ - - private JdbcRowSetResourceBundle resBundle; - - public WebRowSetXmlReader(){ - try { - resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); - } catch(IOException ioe) { - throw new RuntimeException(ioe); - } - } - public void readXML(WebRowSet caller, java.io.Reader reader) throws SQLException { try { // Crimson Parser(as in J2SE 1.4.1 is NOT able to handle diff --git a/src/share/classes/java/lang/Class.java b/src/share/classes/java/lang/Class.java index ddf5763179019e8e521c68bb76252f55a3328730..46414ad849164d034cbebf9d8de9a8cc64bbd090 100644 --- a/src/share/classes/java/lang/Class.java +++ b/src/share/classes/java/lang/Class.java @@ -565,8 +565,9 @@ public final * represented by this object. */ public String getName() { + String name = this.name; if (name == null) - name = getName0(); + this.name = name = getName0(); return name; } diff --git a/src/share/classes/java/lang/ClassLoader.java b/src/share/classes/java/lang/ClassLoader.java index d25100958a00980f9ba4b9ed95b73df115030e4c..9fec9b570a06ad2eb10b09ab62a4c4888e677267 100644 --- a/src/share/classes/java/lang/ClassLoader.java +++ b/src/share/classes/java/lang/ClassLoader.java @@ -380,16 +380,28 @@ public abstract class ClassLoader { // First, check if the class has already been loaded Class c = findLoadedClass(name); if (c == null) { + long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { - c = findBootstrapClass0(name); + c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { + // ClassNotFoundException thrown if class not found + // from the non-null parent class loader + } + + if (c == null) { // If still not found, then invoke findClass in order // to find the class. + long t1 = System.nanoTime(); c = findClass(name); + + // this is the defining class loader; record the stats + sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); + sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); + sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { @@ -1008,22 +1020,29 @@ public abstract class ClassLoader { if (system == null) { if (!checkName(name)) throw new ClassNotFoundException(name); - return findBootstrapClass(name); + Class cls = findBootstrapClass(name); + if (cls == null) { + throw new ClassNotFoundException(name); + } + return cls; } return system.loadClass(name); } - private Class findBootstrapClass0(String name) - throws ClassNotFoundException + /** + * Returns a class loaded by the bootstrap class loader; + * or return null if not found. + */ + private Class findBootstrapClassOrNull(String name) { check(); - if (!checkName(name)) - throw new ClassNotFoundException(name); + if (!checkName(name)) return null; + return findBootstrapClass(name); } - private native Class findBootstrapClass(String name) - throws ClassNotFoundException; + // return null if not found + private native Class findBootstrapClass(String name); // Check to make sure the class loader has been initialized. private void check() { diff --git a/src/share/classes/java/net/CookieManager.java b/src/share/classes/java/net/CookieManager.java index 32790a8f185197b377903cb1c24bc837eb448a88..95de8c0db3bb9a40be2e0354f03c64da27a5a1bc 100644 --- a/src/share/classes/java/net/CookieManager.java +++ b/src/share/classes/java/net/CookieManager.java @@ -157,7 +157,7 @@ public class CookieManager extends CookieHandler // if not specify CookieStore to use, use default one if (store == null) { - cookieJar = new sun.net.www.protocol.http.InMemoryCookieStore(); + cookieJar = new InMemoryCookieStore(); } else { cookieJar = store; } diff --git a/src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java b/src/share/classes/java/net/InMemoryCookieStore.java similarity index 99% rename from src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java rename to src/share/classes/java/net/InMemoryCookieStore.java index 2e7b54f70c00577e24960d21531bb4a64db1a635..697ca88d7107d1f47efaa0ab51faa18afbbc1487 100644 --- a/src/share/classes/sun/net/www/protocol/http/InMemoryCookieStore.java +++ b/src/share/classes/java/net/InMemoryCookieStore.java @@ -23,7 +23,7 @@ * have any questions. */ -package sun.net.www.protocol.http; +package java.net; import java.net.URI; import java.net.CookieStore; @@ -43,7 +43,7 @@ import java.util.concurrent.locks.ReentrantLock; * @author Edward Wang * @since 1.6 */ -public class InMemoryCookieStore implements CookieStore { +class InMemoryCookieStore implements CookieStore { // the in-memory representation of cookies private List cookieJar = null; diff --git a/src/share/classes/java/net/URLClassLoader.java b/src/share/classes/java/net/URLClassLoader.java index 22be20b7ecd5fc43cfcc377d0060dc2a13edf661..c4f775db71a18703a81e4f0d6ec482a727bd95e2 100644 --- a/src/share/classes/java/net/URLClassLoader.java +++ b/src/share/classes/java/net/URLClassLoader.java @@ -340,6 +340,7 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { * used. */ private Class defineClass(String name, Resource res) throws IOException { + long t0 = System.nanoTime(); int i = name.lastIndexOf('.'); URL url = res.getCodeSourceURL(); if (i != -1) { @@ -370,12 +371,14 @@ public class URLClassLoader extends SecureClassLoader implements Closeable { // Use (direct) ByteBuffer: CodeSigner[] signers = res.getCodeSigners(); CodeSource cs = new CodeSource(url, signers); + sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0); return defineClass(name, bb, cs); } else { byte[] b = res.getBytes(); // must read certificates AFTER reading bytes. CodeSigner[] signers = res.getCodeSigners(); CodeSource cs = new CodeSource(url, signers); + sun.misc.PerfCounter.getReadClassBytesTime().addElapsedTimeFrom(t0); return defineClass(name, b, 0, b.length, cs); } } diff --git a/src/share/classes/java/net/doc-files/net-properties.html b/src/share/classes/java/net/doc-files/net-properties.html index e6b6330ba42aa3e00ae63ca478b1ca523fc809e6..384abd8d93fce0b9a3f1f53f33574c78d0c6706d 100644 --- a/src/share/classes/java/net/doc-files/net-properties.html +++ b/src/share/classes/java/net/doc-files/net-properties.html @@ -71,12 +71,12 @@ of proxies.

  • HTTP

    The following proxy settings are used by the HTTP protocol handler.

    +

    The default value excludes all common variations of the loopback address.

    +
  • HTTPS
    This is HTTP over SSL, a secure version of HTTP mainly used when confidentiality (like on payment sites) is needed.

    The following proxy settings are used by the HTTPS protocol handler.

    @@ -107,7 +108,7 @@ of proxies.

  • ftp.proxyPort (default: 80)
    The port number of the proxy server.

    -
  • ftp.nonProxyHosts (default: <none>)
    +

  • ftp.nonProxyHosts (default: localhost|127.*|[::1])
    Indicates the hosts that should be accessed without going through the proxy. Typically this defines internal hosts. The value of this property is a list of hosts, separated by @@ -117,6 +118,7 @@ of proxies.

    will indicate that every hosts in the foo.com domain and the localhost should be accessed directly even if a proxy server is specified.

    +

    The default value excludes all common variations of the loopback address.

  • SOCKS
    This is another type of proxy. It allows for lower level type of tunneling since it works at the TCP level. In effect, diff --git a/src/share/classes/java/nio/file/FileTreeWalker.java b/src/share/classes/java/nio/file/FileTreeWalker.java index 71cb86eb88a883606900dbb906b9f62086626694..1452bd66b2aa96dc2ad4ba190d947849493e17cf 100644 --- a/src/share/classes/java/nio/file/FileTreeWalker.java +++ b/src/share/classes/java/nio/file/FileTreeWalker.java @@ -41,8 +41,12 @@ class FileTreeWalker { private final boolean detectCycles; private final LinkOption[] linkOptions; private final FileVisitor visitor; + private final int maxDepth; - FileTreeWalker(Set options, FileVisitor visitor) { + FileTreeWalker(Set options, + FileVisitor visitor, + int maxDepth) + { boolean fl = false; boolean dc = false; for (FileVisitOption option: options) { @@ -58,18 +62,15 @@ class FileTreeWalker { this.linkOptions = (fl) ? new LinkOption[0] : new LinkOption[] { LinkOption.NOFOLLOW_LINKS }; this.visitor = visitor; + this.maxDepth = maxDepth; } /** * Walk file tree starting at the given file */ - void walk(Path start, int maxDepth) { - // don't use attributes of starting file as they may be stale - if (start instanceof BasicFileAttributesHolder) { - ((BasicFileAttributesHolder)start).invalidate(); - } + void walk(Path start) { FileVisitResult result = walk(start, - maxDepth, + 0, new ArrayList()); if (result == null) { throw new NullPointerException("Visitor returned 'null'"); @@ -89,12 +90,15 @@ class FileTreeWalker { List ancestors) { // depth check - if (depth-- < 0) + if (depth > maxDepth) return FileVisitResult.CONTINUE; // if attributes are cached then use them if possible BasicFileAttributes attrs = null; - if (file instanceof BasicFileAttributesHolder) { + if ((depth > 0) && + (file instanceof BasicFileAttributesHolder) && + (System.getSecurityManager() == null)) + { BasicFileAttributes cached = ((BasicFileAttributesHolder)file).get(); if (!followLinks || !cached.isSymbolicLink()) attrs = cached; @@ -120,6 +124,10 @@ class FileTreeWalker { } } } catch (SecurityException x) { + // If access to starting file is denied then SecurityException + // is thrown, otherwise the file is ignored. + if (depth == 0) + throw x; return FileVisitResult.CONTINUE; } } @@ -196,7 +204,7 @@ class FileTreeWalker { try { for (Path entry: stream) { inAction = true; - result = walk(entry, depth, ancestors); + result = walk(entry, depth+1, ancestors); inAction = false; // returning null will cause NPE to be thrown diff --git a/src/share/classes/java/nio/file/Files.java b/src/share/classes/java/nio/file/Files.java index bf596409e5a5724364e342b9fb35331e262268a7..ca5bc5698e1db19ea601a3cd6bc6f4ca48c4bdfa 100644 --- a/src/share/classes/java/nio/file/Files.java +++ b/src/share/classes/java/nio/file/Files.java @@ -223,7 +223,7 @@ public final class Files { { if (maxDepth < 0) throw new IllegalArgumentException("'maxDepth' is negative"); - new FileTreeWalker(options, visitor).walk(start, maxDepth); + new FileTreeWalker(options, visitor, maxDepth).walk(start); } /** diff --git a/src/share/classes/java/util/Currency.java b/src/share/classes/java/util/Currency.java index 5c9124a90c87797e052fe9beb7cf75d64d9c4f2c..714bd3b2363b4eedc156f8c8b445127a511cdc64 100644 --- a/src/share/classes/java/util/Currency.java +++ b/src/share/classes/java/util/Currency.java @@ -35,12 +35,12 @@ import java.io.Serializable; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.logging.Level; -import java.util.logging.Logger; import java.util.regex.Pattern; import java.util.regex.Matcher; import java.util.spi.CurrencyNameProvider; import java.util.spi.LocaleServiceProvider; import sun.util.LocaleServiceProviderPool; +import sun.util.logging.PlatformLogger; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; @@ -244,7 +244,7 @@ public final class Currency implements Serializable { } } } catch (IOException e) { - log(Level.INFO, "currency.properties is ignored because of an IOException", e); + info("currency.properties is ignored because of an IOException", e); } return null; } @@ -686,7 +686,7 @@ public final class Currency implements Serializable { .append("The entry in currency.properties for ") .append(ctry).append(" is ignored because of the invalid country code.") .toString(); - log(Level.INFO, message, null); + info(message, null); return; } @@ -698,7 +698,7 @@ public final class Currency implements Serializable { .append(ctry) .append(" is ignored because the value format is not recognized.") .toString(); - log(Level.INFO, message, null); + info(message, null); return; } @@ -726,13 +726,13 @@ public final class Currency implements Serializable { setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry); } - private static void log(Level level, String message, Throwable t) { - Logger logger = Logger.getLogger("java.util.Currency"); - if (logger.isLoggable(level)) { + private static void info(String message, Throwable t) { + PlatformLogger logger = PlatformLogger.getLogger("java.util.Currency"); + if (logger.isLoggable(PlatformLogger.INFO)) { if (t != null) { - logger.log(level, message, t); + logger.info(message, t); } else { - logger.log(level, message); + logger.info(message); } } } diff --git a/src/share/classes/java/util/jar/Attributes.java b/src/share/classes/java/util/jar/Attributes.java index 27a2aba8ef98596120d6a1c06e847932b6210ceb..e9a9e6e6f691707680aede942c7bf94a5d6c9941 100644 --- a/src/share/classes/java/util/jar/Attributes.java +++ b/src/share/classes/java/util/jar/Attributes.java @@ -34,7 +34,7 @@ import java.util.Set; import java.util.Collection; import java.util.AbstractSet; import java.util.Iterator; -import java.util.logging.Logger; +import sun.util.logging.PlatformLogger; import java.util.Comparator; import sun.misc.ASCIICaseInsensitiveComparator; @@ -419,7 +419,7 @@ public class Attributes implements Map, Cloneable { } try { if ((putValue(name, value) != null) && (!lineContinued)) { - Logger.getLogger("java.util.jar").warning( + PlatformLogger.getLogger("java.util.jar").warning( "Duplicate name in Manifest: " + name + ".\n" + "Ensure that the manifest does not " diff --git a/src/share/classes/java/util/logging/ErrorManager.java b/src/share/classes/java/util/logging/ErrorManager.java index 39c215151fc2180de3033f000c45c88884293d9c..8a6d935dea3456f626297738a464236a10a49faf 100644 --- a/src/share/classes/java/util/logging/ErrorManager.java +++ b/src/share/classes/java/util/logging/ErrorManager.java @@ -28,7 +28,7 @@ package java.util.logging; /** * ErrorManager objects can be attached to Handlers to process - * any error that occur on a Handler during Logging. + * any error that occurs on a Handler during Logging. *

    * When processing logging output, if a Handler encounters problems * then rather than throwing an Exception back to the issuer of @@ -72,7 +72,7 @@ public class ErrorManager { /** * The error method is called when a Handler failure occurs. *

    - * This method may be overriden in subclasses. The default + * This method may be overridden in subclasses. The default * behavior in this base class is that the first call is * reported to System.err, and subsequent calls are ignored. * diff --git a/src/share/classes/java/util/logging/FileHandler.java b/src/share/classes/java/util/logging/FileHandler.java index a4f18bd2130c8705c21d27204a4253980912f396..23031a010c8bf8b5b8d43a341d51900bf08730da 100644 --- a/src/share/classes/java/util/logging/FileHandler.java +++ b/src/share/classes/java/util/logging/FileHandler.java @@ -39,7 +39,7 @@ import java.security.*; * For a rotating set of files, as each file reaches a given size * limit, it is closed, rotated out, and a new file opened. * Successively older files are named by adding "0", "1", "2", - * etc into the base filename. + * etc. into the base filename. *

    * By default buffering is enabled in the IO libraries but each log * record is flushed out when it is complete. @@ -391,7 +391,7 @@ public class FileHandler extends StreamHandler { // Generate a lock file name from the "unique" int. lockFileName = generate(pattern, 0, unique).toString() + ".lck"; // Now try to lock that filename. - // Because some systems (e.g. Solaris) can only do file locks + // Because some systems (e.g., Solaris) can only do file locks // between processes (and not within a process), we first check // if we ourself already have the file locked. synchronized(locks) { diff --git a/src/share/classes/java/util/logging/Formatter.java b/src/share/classes/java/util/logging/Formatter.java index 7e7030ba6b0bef63a0bde0c8914dd8aac5db96d9..7cf5c1764a1b3500b247e12a4d0a74796753d786 100644 --- a/src/share/classes/java/util/logging/Formatter.java +++ b/src/share/classes/java/util/logging/Formatter.java @@ -52,7 +52,7 @@ public abstract class Formatter { * Format the given log record and return the formatted string. *

    * The resulting formatted String will normally include a - * localized and formated version of the LogRecord's message field. + * localized and formatted version of the LogRecord's message field. * It is recommended to use the {@link Formatter#formatMessage} * convenience method to localize and format the message field. * @@ -66,7 +66,7 @@ public abstract class Formatter { * Return the header string for a set of formatted records. *

    * This base class returns an empty string, but this may be - * overriden by subclasses. + * overridden by subclasses. * * @param h The target handler (can be null) * @return header string @@ -79,7 +79,7 @@ public abstract class Formatter { * Return the tail string for a set of formatted records. *

    * This base class returns an empty string, but this may be - * overriden by subclasses. + * overridden by subclasses. * * @param h The target handler (can be null) * @return tail string diff --git a/src/share/classes/java/util/logging/Handler.java b/src/share/classes/java/util/logging/Handler.java index 2643c73471489332498d7f15a0b3aeaf5719071d..7c1c6268b00bc795eaf796d918494b207ddfb3c0 100644 --- a/src/share/classes/java/util/logging/Handler.java +++ b/src/share/classes/java/util/logging/Handler.java @@ -274,7 +274,7 @@ public abstract class Handler { * Level and whether it satisfies any Filter. It also * may make other Handler specific checks that might prevent a * handler from logging the LogRecord. It will return false if - * the LogRecord is Null. + * the LogRecord is null. *

    * @param record a LogRecord * @return true if the LogRecord would be logged. diff --git a/src/share/classes/java/util/logging/Level.java b/src/share/classes/java/util/logging/Level.java index 910a50d1ebba75aee5f7725cfb5ee1ef465cf080..173201f80eee201a02e4fdb10745ae6271d0f0a2 100644 --- a/src/share/classes/java/util/logging/Level.java +++ b/src/share/classes/java/util/logging/Level.java @@ -110,7 +110,7 @@ public class Level implements java.io.Serializable { * Typically INFO messages will be written to the console * or its equivalent. So the INFO level should only be * used for reasonably significant messages that will - * make sense to end users and system admins. + * make sense to end users and system administrators. * This level is initialized to 800. */ public static final Level INFO = new Level("INFO", 800, defaultBundle); @@ -245,6 +245,8 @@ public class Level implements java.io.Serializable { } /** + * Returns a string representation of this Level. + * * @return the non-localized name of the Level, for example "INFO". */ public final String toString() { @@ -299,14 +301,14 @@ public class Level implements java.io.Serializable { * @throws IllegalArgumentException if the value is not valid. * Valid values are integers between Integer.MIN_VALUE * and Integer.MAX_VALUE, and all known level names. - * Known names are the levels defined by this class (i.e. FINE, + * Known names are the levels defined by this class (e.g., FINE, * FINER, FINEST), or created by this class with * appropriate package access, or new levels defined or created * by subclasses. * * @return The parsed value. Passing an integer that corresponds to a known name - * (eg 700) will return the associated name (eg CONFIG). - * Passing an integer that does not (eg 1) will return a new level name + * (e.g., 700) will return the associated name (e.g., CONFIG). + * Passing an integer that does not (e.g., 1) will return a new level name * initialized to that value. */ public static synchronized Level parse(String name) throws IllegalArgumentException { diff --git a/src/share/classes/java/util/logging/LogManager.java b/src/share/classes/java/util/logging/LogManager.java index e6412565a87ec94d238428c958204c674f84c1e3..4faea17d79e5e9689ed01c79660429524b287d15 100644 --- a/src/share/classes/java/util/logging/LogManager.java +++ b/src/share/classes/java/util/logging/LogManager.java @@ -283,6 +283,10 @@ public class LogManager { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws Exception { readConfiguration(); + + // Platform loggers begin to delegate to java.util.logging.Logger + sun.util.logging.PlatformLogger.redirectPlatformLoggers(); + return null; } }); diff --git a/src/share/classes/java/util/logging/LogRecord.java b/src/share/classes/java/util/logging/LogRecord.java index 2610316a5e38b7e1a08d2d5c11dd90f7c63d84b7..e6706319ffadf4d728aef54045767712cbf5500b 100644 --- a/src/share/classes/java/util/logging/LogRecord.java +++ b/src/share/classes/java/util/logging/LogRecord.java @@ -188,7 +188,7 @@ public class LogRecord implements java.io.Serializable { } /** - * Get the source Logger name's + * Get the source Logger's name. * * @return source logger name (may be null) */ @@ -197,7 +197,7 @@ public class LogRecord implements java.io.Serializable { } /** - * Set the source Logger name. + * Set the source Logger's name. * * @param name the source logger name (may be null) */ @@ -530,6 +530,7 @@ public class LogRecord implements java.io.Serializable { int depth = access.getStackTraceDepth(throwable); String logClassName = "java.util.logging.Logger"; + String plogClassName = "sun.util.logging.PlatformLogger"; boolean lookingForLogger = true; for (int ix = 0; ix < depth; ix++) { // Calling getStackTraceElement directly prevents the VM @@ -539,15 +540,18 @@ public class LogRecord implements java.io.Serializable { String cname = frame.getClassName(); if (lookingForLogger) { // Skip all frames until we have found the first logger frame. - if (cname.equals(logClassName)) { + if (cname.equals(logClassName) || cname.startsWith(plogClassName)) { lookingForLogger = false; } } else { - if (!cname.equals(logClassName)) { - // We've found the relevant frame. - setSourceClassName(cname); - setSourceMethodName(frame.getMethodName()); - return; + if (!cname.equals(logClassName) && !cname.startsWith(plogClassName)) { + // skip reflection call + if (!cname.startsWith("java.lang.reflect.") && !cname.startsWith("sun.reflect.")) { + // We've found the relevant frame. + setSourceClassName(cname); + setSourceMethodName(frame.getMethodName()); + return; + } } } } diff --git a/src/share/classes/java/util/logging/Logger.java b/src/share/classes/java/util/logging/Logger.java index 5ae2b42713361f38875dd8141a1c172ebb1861e4..cd9f4d90568cbc7371762e1a206d4eb8daf1eea7 100644 --- a/src/share/classes/java/util/logging/Logger.java +++ b/src/share/classes/java/util/logging/Logger.java @@ -66,7 +66,7 @@ import java.lang.ref.WeakReference; * effective level from its parent. *

    * On each logging call the Logger initially performs a cheap - * check of the request level (e.g. SEVERE or FINE) against the + * check of the request level (e.g., SEVERE or FINE) against the * effective log level of the logger. If the request level is * lower than the log level, the logging call returns immediately. *

    @@ -230,7 +230,7 @@ public class Logger { * Protected method to construct a logger for a named subsystem. *

    * The logger will be initially configured with a null Level - * and with useParentHandlers true. + * and with useParentHandlers set to true. * * @param name A name for the logger. This should * be a dot-separated name and should normally @@ -240,7 +240,7 @@ public class Logger { * @param resourceBundleName name of ResourceBundle to be used for localizing * messages for this logger. May be null if none * of the messages require localization. - * @throws MissingResourceException if the ResourceBundleName is non-null and + * @throws MissingResourceException if the resourceBundleName is non-null and * no corresponding resource can be found. */ protected Logger(String name, String resourceBundleName) { @@ -285,7 +285,7 @@ public class Logger { *

    * If a new logger is created its log level will be configured * based on the LogManager configuration and it will configured - * to also send logging output to its parent's handlers. It will + * to also send logging output to its parent's Handlers. It will * be registered in the LogManager global namespace. * * @param name A name for the logger. This should @@ -308,7 +308,7 @@ public class Logger { *

    * If a new logger is created its log level will be configured * based on the LogManager and it will configured to also send logging - * output to its parent loggers Handlers. It will be registered in + * output to its parent's Handlers. It will be registered in * the LogManager global namespace. *

    * If the named Logger already exists and does not yet have a @@ -326,7 +326,8 @@ public class Logger { * messages for this logger. May be null if none of * the messages require localization. * @return a suitable Logger - * @throws MissingResourceException if the named ResourceBundle cannot be found. + * @throws MissingResourceException if the resourceBundleName is non-null and + * no corresponding resource can be found. * @throws IllegalArgumentException if the Logger already exists and uses * a different resource bundle name. * @throws NullPointerException if the name is null. @@ -395,7 +396,8 @@ public class Logger { * messages for this logger. * May be null if none of the messages require localization. * @return a newly created private Logger - * @throws MissingResourceException if the named ResourceBundle cannot be found. + * @throws MissingResourceException if the resourceBundleName is non-null and + * no corresponding resource can be found. */ public static synchronized Logger getAnonymousLogger(String resourceBundleName) { LogManager manager = LogManager.getLogManager(); @@ -514,7 +516,7 @@ public class Logger { * level then the given message is forwarded to all the * registered output Handler objects. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) */ public void log(Level level, String msg) { @@ -532,7 +534,7 @@ public class Logger { * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) * @param param1 parameter to the message */ @@ -553,7 +555,7 @@ public class Logger { * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) * @param params array of parameters to the message */ @@ -578,7 +580,7 @@ public class Logger { * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param msg The string message (or a key in the message catalog) * @param thrown Throwable associated with log message. */ @@ -603,7 +605,7 @@ public class Logger { * level then the given message is forwarded to all the * registered output Handler objects. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param msg The string message (or a key in the message catalog) @@ -626,7 +628,7 @@ public class Logger { * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param msg The string message (or a key in the message catalog) @@ -653,7 +655,7 @@ public class Logger { * level then a corresponding LogRecord is created and forwarded * to all the registered output Handler objects. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param msg The string message (or a key in the message catalog) @@ -684,7 +686,7 @@ public class Logger { * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param msg The string message (or a key in the message catalog) @@ -731,7 +733,7 @@ public class Logger { * resource bundle name is null, or an empty String or invalid * then the msg string is not localized. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param bundleName name of resource bundle to localize msg, @@ -762,7 +764,7 @@ public class Logger { * resource bundle name is null, or an empty String or invalid * then the msg string is not localized. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param bundleName name of resource bundle to localize msg, @@ -795,7 +797,7 @@ public class Logger { * resource bundle name is null, or an empty String or invalid * then the msg string is not localized. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param bundleName name of resource bundle to localize msg, @@ -832,7 +834,7 @@ public class Logger { * processed specially by output Formatters and is not treated * as a formatting parameter to the LogRecord message property. *

    - * @param level One of the message level identifiers, e.g. SEVERE + * @param level One of the message level identifiers, e.g., SEVERE * @param sourceClass name of class that issued the logging request * @param sourceMethod name of method that issued the logging request * @param bundleName name of resource bundle to localize msg, @@ -1214,7 +1216,7 @@ public class Logger { /** * Specify whether or not this logger should send its output - * to it's parent Logger. This means that any LogRecords will + * to its parent Logger. This means that any LogRecords will * also be written to the parent's Handlers, and potentially * to its parent, recursively up the namespace. * diff --git a/src/share/classes/java/util/logging/LoggingMXBean.java b/src/share/classes/java/util/logging/LoggingMXBean.java index cb67d7b4fb071c410615b21956750df0c50a5d6e..a3abe3c69b16fc4cc0c848c1ca5940e9625b0fa8 100644 --- a/src/share/classes/java/util/logging/LoggingMXBean.java +++ b/src/share/classes/java/util/logging/LoggingMXBean.java @@ -105,8 +105,8 @@ public interface LoggingMXBean extends PlatformManagedObject { * * @param loggerName The name of the Logger to be set. * Must be non-null. - * @param levelName The name of the level to set the specified logger to, - * or null if to set the level to inherit + * @param levelName The name of the level to set on the specified logger, + * or null if setting the level to inherit * from its nearest ancestor. * * @throws IllegalArgumentException if the specified logger diff --git a/src/share/classes/java/util/logging/MemoryHandler.java b/src/share/classes/java/util/logging/MemoryHandler.java index d812e3bf64f82cdb02afd4e94b5d53ee3c8fc9f2..aa632223667fd0b8e10ab36e252dd830883b391e 100644 --- a/src/share/classes/java/util/logging/MemoryHandler.java +++ b/src/share/classes/java/util/logging/MemoryHandler.java @@ -136,7 +136,7 @@ public class MemoryHandler extends Handler { * @param size the number of log records to buffer (must be greater than zero) * @param pushLevel message level to push on * - * @throws IllegalArgumentException is size is <= 0 + * @throws IllegalArgumentException if size is <= 0 */ public MemoryHandler(Handler target, int size, Level pushLevel) { if (target == null || pushLevel == null) { @@ -258,7 +258,7 @@ public class MemoryHandler extends Handler { * This method checks if the LogRecord has an appropriate level and * whether it satisfies any Filter. However it does not * check whether the LogRecord would result in a "push" of the - * buffer contents. It will return false if the LogRecord is Null. + * buffer contents. It will return false if the LogRecord is null. *

    * @param record a LogRecord * @return true if the LogRecord would be logged. diff --git a/src/share/classes/java/util/logging/StreamHandler.java b/src/share/classes/java/util/logging/StreamHandler.java index 766142a1a58883c1ae758bcd998cfbe6e9b241ab..ce47fe904272f39e6778cefc72a9f9ef4717d6bd 100644 --- a/src/share/classes/java/util/logging/StreamHandler.java +++ b/src/share/classes/java/util/logging/StreamHandler.java @@ -220,7 +220,7 @@ public class StreamHandler extends Handler { *

    * This method checks if the LogRecord has an appropriate level and * whether it satisfies any Filter. It will also return false if - * no output stream has been assigned yet or the LogRecord is Null. + * no output stream has been assigned yet or the LogRecord is null. *

    * @param record a LogRecord * @return true if the LogRecord would be logged. diff --git a/src/share/classes/java/util/zip/ZipEntry.java b/src/share/classes/java/util/zip/ZipEntry.java index cba69b0c1a2e37cbdc15562fbf2b8f78c469be77..0e2ddaec3fb15abaf09987e5ee8fa4c88e1fed25 100644 --- a/src/share/classes/java/util/zip/ZipEntry.java +++ b/src/share/classes/java/util/zip/ZipEntry.java @@ -253,14 +253,10 @@ class ZipEntry implements ZipConstants, Cloneable { * the first 0xFFFF bytes are output to the ZIP file entry. * * @param comment the comment string - * @exception IllegalArgumentException if the length of the specified - * comment string is greater than 0xFFFF bytes + * * @see #getComment() */ public void setComment(String comment) { - if (comment != null && comment.length() > 0xffff) { - throw new IllegalArgumentException("invalid entry comment length"); - } this.comment = comment; } diff --git a/src/share/classes/java/util/zip/ZipFile.java b/src/share/classes/java/util/zip/ZipFile.java index 76c270c1b1019561548c503dbf65ecd1323206a6..583d7dcfe1aa7d250eecf439a51fb258eec1f503 100644 --- a/src/share/classes/java/util/zip/ZipFile.java +++ b/src/share/classes/java/util/zip/ZipFile.java @@ -195,7 +195,10 @@ class ZipFile implements ZipConstants, Closeable { if (charset == null) throw new NullPointerException("charset is null"); this.zc = ZipCoder.get(charset); + long t0 = System.nanoTime(); jzfile = open(name, mode, file.lastModified()); + sun.misc.PerfCounter.getZipFileOpenTime().addElapsedTimeFrom(t0); + sun.misc.PerfCounter.getZipFileCount().increment(); this.name = name; this.total = getTotal(jzfile); } diff --git a/src/share/classes/javax/sql/rowset/BaseRowSet.java b/src/share/classes/javax/sql/rowset/BaseRowSet.java index 2d13d835c1ba3989f727b71422aa23fc4e8d96d9..f3e79555ba1d80d3890ccf398ef0ba6f692d1afc 100644 --- a/src/share/classes/javax/sql/rowset/BaseRowSet.java +++ b/src/share/classes/javax/sql/rowset/BaseRowSet.java @@ -168,8 +168,8 @@ import javax.sql.rowset.serial.*; * The majority of methods for setting placeholder parameters take two parameters, * with the first parameter * indicating which placeholder parameter is to be set, and the second parameter - * giving the value to be set. Methods such as getInt, - * getString, getBoolean, and getLong fall into + * giving the value to be set. Methods such as setInt, + * setString, setBoolean, and setLong fall into * this category. After these methods have been called, a call to the method * getParams will return an array with the values that have been set. Each * element in the array is an Object instance representing the @@ -3259,9 +3259,9 @@ public static final int ASCII_STREAM_PARAM = 2; * @param x the parameter value * @exception SQLException if a database access error occurs or * this method is called on a closed CallableStatement - * @see #getBoolean * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method + * @see #getParams * @since 1.4 */ public void setBoolean(String parameterName, boolean x) throws SQLException{ @@ -3281,7 +3281,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getByte + * @see #getParams * @since 1.4 */ public void setByte(String parameterName, byte x) throws SQLException{ @@ -3301,7 +3301,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getShort + * @see #getParams * @since 1.4 */ public void setShort(String parameterName, short x) throws SQLException{ @@ -3320,7 +3320,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getInt + * @see #getParams * @since 1.4 */ public void setInt(String parameterName, int x) throws SQLException{ @@ -3339,7 +3339,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getLong + * @see #getParams * @since 1.4 */ public void setLong(String parameterName, long x) throws SQLException{ @@ -3358,7 +3358,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getFloat + * @see #getParams * @since 1.4 */ public void setFloat(String parameterName, float x) throws SQLException{ @@ -3377,7 +3377,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getDouble + * @see #getParams * @since 1.4 */ public void setDouble(String parameterName, double x) throws SQLException{ @@ -3398,7 +3398,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getBigDecimal + * @see #getParams * @since 1.4 */ public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException{ @@ -3421,7 +3421,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getString + * @see #getParams * @since 1.4 */ public void setString(String parameterName, String x) throws SQLException{ @@ -3443,7 +3443,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getBytes + * @see #getParams * @since 1.4 */ public void setBytes(String parameterName, byte x[]) throws SQLException{ @@ -3464,7 +3464,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getTimestamp + * @see #getParams * @since 1.4 */ public void setTimestamp(String parameterName, java.sql.Timestamp x) @@ -3712,7 +3712,7 @@ public static final int ASCII_STREAM_PARAM = 2; * or STRUCT data type and the JDBC driver does not support * this data type * @see Types - * @see #getObject + * @see #getParams * @since 1.4 */ public void setObject(String parameterName, Object x, int targetSqlType, int scale) @@ -3740,7 +3740,7 @@ public static final int ASCII_STREAM_PARAM = 2; * REF, ROWID, SQLXML * or STRUCT data type and the JDBC driver does not support * this data type - * @see #getObject + * @see #getParams * @since 1.4 */ public void setObject(String parameterName, Object x, int targetSqlType) @@ -3782,7 +3782,7 @@ public static final int ASCII_STREAM_PARAM = 2; * Object parameter is ambiguous * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getObject + * @see #getParams * @since 1.4 */ public void setObject(String parameterName, Object x) throws SQLException{ @@ -4064,7 +4064,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getDate + * @see #getParams * @since 1.4 */ public void setDate(String parameterName, java.sql.Date x) @@ -4091,7 +4091,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getDate + * @see #getParams * @since 1.4 */ public void setDate(String parameterName, java.sql.Date x, Calendar cal) @@ -4111,7 +4111,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getTime + * @see #getParams * @since 1.4 */ public void setTime(String parameterName, java.sql.Time x) @@ -4138,7 +4138,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getTime + * @see #getParams * @since 1.4 */ public void setTime(String parameterName, java.sql.Time x, Calendar cal) @@ -4165,7 +4165,7 @@ public static final int ASCII_STREAM_PARAM = 2; * this method is called on a closed CallableStatement * @exception SQLFeatureNotSupportedException if the JDBC driver does not support * this method - * @see #getTimestamp + * @see #getParams * @since 1.4 */ public void setTimestamp(String parameterName, java.sql.Timestamp x, Calendar cal) diff --git a/src/share/classes/sun/misc/PerfCounter.java b/src/share/classes/sun/misc/PerfCounter.java new file mode 100644 index 0000000000000000000000000000000000000000..8c47234407a4cc2f81066521e2a455d024784904 --- /dev/null +++ b/src/share/classes/sun/misc/PerfCounter.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.misc; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.LongBuffer; +import java.security.AccessController; + +/** + * Performance counter support for internal JRE classes. + * This class defines a fixed list of counters for the platform + * to use as an interim solution until RFE# 6209222 is implemented. + * The perf counters will be created in the jvmstat perf buffer + * that the HotSpot VM creates. The default size is 32K and thus + * the number of counters is bounded. You can alter the size + * with -XX:PerfDataMemorySize= option. If there is + * insufficient memory in the jvmstat perf buffer, the C heap memory + * will be used and thus the application will continue to run if + * the counters added exceeds the buffer size but the counters + * will be missing. + * + * See HotSpot jvmstat implementation for certain circumstances + * that the jvmstat perf buffer is not supported. + * + */ +public class PerfCounter { + private static final Perf perf = + AccessController.doPrivileged(new Perf.GetPerfAction()); + + // Must match values defined in hotspot/src/share/vm/runtime/perfdata.hpp + private final static int V_Constant = 1; + private final static int V_Monotonic = 2; + private final static int V_Variable = 3; + private final static int U_None = 1; + + private final String name; + private final LongBuffer lb; + + private PerfCounter(String name, int type) { + this.name = name; + ByteBuffer bb = perf.createLong(name, U_None, type, 0L); + bb.order(ByteOrder.nativeOrder()); + this.lb = bb.asLongBuffer(); + } + + static PerfCounter newPerfCounter(String name) { + return new PerfCounter(name, V_Variable); + } + + static PerfCounter newConstantPerfCounter(String name) { + PerfCounter c = new PerfCounter(name, V_Constant); + return c; + } + + /** + * Returns the current value of the perf counter. + */ + public synchronized long get() { + return lb.get(0); + } + + /** + * Sets the value of the perf counter to the given newValue. + */ + public synchronized void set(long newValue) { + lb.put(0, newValue); + } + + /** + * Adds the given value to the perf counter. + */ + public synchronized void add(long value) { + long res = get() + value; + lb.put(0, res); + } + + /** + * Increments the perf counter with 1. + */ + public void increment() { + add(1); + } + + /** + * Adds the given interval to the perf counter. + */ + public void addTime(long interval) { + add(interval); + } + + /** + * Adds the elapsed time from the given start time (ns) to the perf counter. + */ + public void addElapsedTimeFrom(long startTime) { + add(System.nanoTime() - startTime); + } + + @Override + public String toString() { + return name + " = " + get(); + } + + static class CoreCounters { + static final PerfCounter pdt = newPerfCounter("sun.classloader.parentDelegationTime"); + static final PerfCounter lc = newPerfCounter("sun.classloader.findClasses"); + static final PerfCounter lct = newPerfCounter("sun.classloader.findClassTime"); + static final PerfCounter rcbt = newPerfCounter("sun.urlClassLoader.readClassBytesTime"); + static final PerfCounter zfc = newPerfCounter("sun.zip.zipFiles"); + static final PerfCounter zfot = newPerfCounter("sun.zip.zipFile.openTime"); + } + + static class WindowsClientCounters { + static final PerfCounter d3dAvailable = newConstantPerfCounter("sun.java2d.d3d.available"); + } + + /** + * Number of findClass calls + */ + public static PerfCounter getFindClasses() { + return CoreCounters.lc; + } + + /** + * Time (ns) spent in finding classes that includes + * lookup and read class bytes and defineClass + */ + public static PerfCounter getFindClassTime() { + return CoreCounters.lct; + } + + /** + * Time (ns) spent in finding classes + */ + public static PerfCounter getReadClassBytesTime() { + return CoreCounters.rcbt; + } + + /** + * Time (ns) spent in the parent delegation to + * the parent of the defining class loader + */ + public static PerfCounter getParentDelegationTime() { + return CoreCounters.pdt; + } + + /** + * Number of zip files opened. + */ + public static PerfCounter getZipFileCount() { + return CoreCounters.zfc; + } + + /** + * Time (ns) spent in opening the zip files that + * includes building the entries hash table + */ + public static PerfCounter getZipFileOpenTime() { + return CoreCounters.zfot; + } + + /** + * D3D graphic pipeline available + */ + public static PerfCounter getD3DAvailable() { + return WindowsClientCounters.d3dAvailable; + } +} diff --git a/src/share/classes/sun/net/spi/DefaultProxySelector.java b/src/share/classes/sun/net/spi/DefaultProxySelector.java index 714dc4ce5c3ba133a47825a1a13ab674ead65e63..af34ada8ccff61ccbc167044c8e16424d6afe727 100644 --- a/src/share/classes/sun/net/spi/DefaultProxySelector.java +++ b/src/share/classes/sun/net/spi/DefaultProxySelector.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,9 @@ package sun.net.spi; -import sun.net.www.http.*; import sun.net.NetProperties; import java.net.*; import java.util.*; -import java.util.regex.*; import java.io.*; import sun.misc.RegexpPool; import java.security.AccessController; @@ -102,17 +100,22 @@ public class DefaultProxySelector extends ProxySelector { */ static class NonProxyInfo { + // Default value for nonProxyHosts, this provides backward compatibility + // by excluding localhost and its litteral notations. + static final String defStringVal = "localhost|127.*|[::1]"; + String hostsSource; RegexpPool hostsPool; - String property; - - static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null); - static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null); + final String property; + final String defaultVal; + static NonProxyInfo ftpNonProxyInfo = new NonProxyInfo("ftp.nonProxyHosts", null, null, defStringVal); + static NonProxyInfo httpNonProxyInfo = new NonProxyInfo("http.nonProxyHosts", null, null, defStringVal); - NonProxyInfo(String p, String s, RegexpPool pool) { + NonProxyInfo(String p, String s, RegexpPool pool, String d) { property = p; hostsSource = s; hostsPool = pool; + defaultVal = d; } } @@ -130,7 +133,6 @@ public class DefaultProxySelector extends ProxySelector { } String protocol = uri.getScheme(); String host = uri.getHost(); - int port = uri.getPort(); if (host == null) { // This is a hack to ensure backward compatibility in two @@ -149,11 +151,6 @@ public class DefaultProxySelector extends ProxySelector { } i = auth.lastIndexOf(':'); if (i >= 0) { - try { - port = Integer.parseInt(auth.substring(i+1)); - } catch (NumberFormatException e) { - port = -1; - } auth = auth.substring(0,i); } host = auth; @@ -165,13 +162,6 @@ public class DefaultProxySelector extends ProxySelector { } List proxyl = new ArrayList(1); - // special case localhost and loopback addresses to - // not go through proxy - if (isLoopback(host)) { - proxyl.add(Proxy.NO_PROXY); - return proxyl; - } - NonProxyInfo pinfo = null; if ("http".equalsIgnoreCase(protocol)) { @@ -244,9 +234,14 @@ public class DefaultProxySelector extends ProxySelector { nphosts = NetProperties.get(nprop.property); synchronized (nprop) { if (nphosts == null) { - nprop.hostsSource = null; - nprop.hostsPool = null; - } else { + if (nprop.defaultVal != null) { + nphosts = nprop.defaultVal; + } else { + nprop.hostsSource = null; + nprop.hostsPool = null; + } + } + if (nphosts != null) { if (!nphosts.equals(nprop.hostsSource)) { RegexpPool pool = new RegexpPool(); StringTokenizer st = new StringTokenizer(nphosts, "|", false); @@ -334,107 +329,6 @@ public class DefaultProxySelector extends ProxySelector { } } - private boolean isLoopback(String host) { - if (host == null || host.length() == 0) - return false; - - if (host.equalsIgnoreCase("localhost")) - return true; - - /* The string could represent a numerical IP address. - * For IPv4 addresses, check whether it starts with 127. - * For IPv6 addresses, check whether it is ::1 or its equivalent. - * Don't check IPv4-mapped or IPv4-compatible addresses - */ - - if (host.startsWith("127.")) { - // possible IPv4 loopback address - int p = 4; - int q; - int n = host.length(); - // Per RFC2732: At most three digits per byte - // Further constraint: Each element fits in a byte - if ((q = scanByte(host, p, n)) <= p) return false; p = q; - if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q; - if ((q = scanByte(host, p, n)) <= p) return false; p = q; - if ((q = scan(host, p, n, '.')) <= p) return q == n && number > 0; p = q; - if ((q = scanByte(host, p, n)) <= p) return false; - return q == n && number > 0; - } - - if (host.endsWith(":1")) { - final Pattern p6 = Pattern.compile("::1|(0:){7}1|(0:){1,6}:1"); - return p6.matcher(host).matches(); - } - return false; - } - - // Character-class masks, in reverse order from RFC2396 because - // initializers for static fields cannot make forward references. - - // Compute a low-order mask for the characters - // between first and last, inclusive - private static long lowMask(char first, char last) { - long m = 0; - int f = Math.max(Math.min(first, 63), 0); - int l = Math.max(Math.min(last, 63), 0); - for (int i = f; i <= l; i++) - m |= 1L << i; - return m; - } - // digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | - // "8" | "9" - private static final long L_DIGIT = lowMask('0', '9'); - private static final long H_DIGIT = 0L; - - // Scan a string of decimal digits whose value fits in a byte - // - private int number; - private int scanByte(String input, int start, int n) - { - int p = start; - int q = scan(input, p, n, L_DIGIT, H_DIGIT); - if (q <= p) return q; - number = Integer.parseInt(input.substring(p, q)); - if (number > 255) return p; - return q; - } - - // Scan a specific char: If the char at the given start position is - // equal to c, return the index of the next char; otherwise, return the - // start position. - // - private int scan(String input, int start, int end, char c) { - if ((start < end) && (input.charAt(start) == c)) - return start + 1; - return start; - } - - // Scan chars that match the given mask pair - // - private int scan(String input, int start, int n, long lowMask, long highMask) - { - int p = start; - while (p < n) { - char c = input.charAt(p); - if (match(c, lowMask, highMask)) { - p++; - continue; - } - break; - } - return p; - } - - // Tell whether the given character is permitted by the given mask pair - private boolean match(char c, long lowMask, long highMask) { - if (c < 64) - return ((1L << c) & lowMask) != 0; - if (c < 128) - return ((1L << (c - 64)) & highMask) != 0; - return false; - } - private native static boolean init(); private native Proxy getSystemProxy(String protocol, String host); } diff --git a/src/share/classes/sun/net/www/http/HttpCapture.java b/src/share/classes/sun/net/www/http/HttpCapture.java index 78debed415f3253f0f557234603ed84f13af9a54..4fc59d4cacd97d5a46f6fb75b5c9b4d1c668d713 100644 --- a/src/share/classes/sun/net/www/http/HttpCapture.java +++ b/src/share/classes/sun/net/www/http/HttpCapture.java @@ -24,14 +24,12 @@ */ package sun.net.www.http; + import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; -import sun.net.NetProperties; import java.util.regex.*; +import sun.net.NetProperties; +import sun.util.logging.PlatformLogger; /** * Main class of the HTTP traffic capture tool. @@ -62,76 +60,6 @@ public class HttpCapture { private static boolean initialized = false; private static volatile ArrayList patterns = null; private static volatile ArrayList capFiles = null; - /* Logging is done in an ugly way so that it does not require the presence - * the java.util.logging package. If the Logger class is not available, then - * logging is turned off. This is for helping the modularization effort. - */ - private static Object logger = null; - private static boolean logging = false; - - static { - Class cl; - try { - cl = Class.forName("java.util.logging.Logger"); - } catch (ClassNotFoundException ex) { - cl = null; - } - if (cl != null) { - try { - Method m = cl.getMethod("getLogger", String.class); - logger = m.invoke(null, "sun.net.www.protocol.http.HttpURLConnection"); - logging = true; - } catch (NoSuchMethodException noSuchMethodException) { - } catch (SecurityException securityException) { - } catch (IllegalAccessException illegalAccessException) { - } catch (IllegalArgumentException illegalArgumentException) { - } catch (InvocationTargetException invocationTargetException) { - } - } - } - - public static void fine(String s) { - if (logging) { - ((Logger)logger).fine(s); - } - } - - public static void finer(String s) { - if (logging) { - ((Logger)logger).finer(s); - } - } - - public static void finest(String s) { - if (logging) { - ((Logger)logger).finest(s); - } - } - - public static void severe(String s) { - if (logging) { - ((Logger)logger).finest(s); - } - } - - public static void info(String s) { - if (logging) { - ((Logger)logger).info(s); - } - } - - public static void warning(String s) { - if (logging) { - ((Logger)logger).warning(s); - } - } - - public static boolean isLoggable(String level) { - if (!logging) { - return false; - } - return ((Logger)logger).isLoggable(Level.parse(level)); - } private static synchronized void init() { initialized = true; @@ -187,7 +115,7 @@ public class HttpCapture { out = new BufferedWriter(new FileWriter(file, true)); out.write("URL: " + url + "\n"); } catch (IOException ex) { - Logger.getLogger(HttpCapture.class.getName()).log(Level.SEVERE, null, ex); + PlatformLogger.getLogger(HttpCapture.class.getName()).severe(null, ex); } } diff --git a/src/share/classes/sun/net/www/http/HttpClient.java b/src/share/classes/sun/net/www/http/HttpClient.java index 5d269bf51ab807e058991431c61380352653597d..37ea7ada1c57f9a17c3b2739e8a9f88ded49484f 100644 --- a/src/share/classes/sun/net/www/http/HttpClient.java +++ b/src/share/classes/sun/net/www/http/HttpClient.java @@ -35,6 +35,7 @@ import sun.net.www.HeaderParser; import sun.net.www.MeteredStream; import sun.net.www.ParseUtil; import sun.net.www.protocol.http.HttpURLConnection; +import sun.util.logging.PlatformLogger; /** * @author Herb Jellinek @@ -804,8 +805,9 @@ public class HttpClient extends NetworkClient { if (isKeepingAlive()) { // Wrap KeepAliveStream if keep alive is enabled. - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("KeepAlive stream used: " + url); + PlatformLogger logger = HttpURLConnection.getHttpLogger(); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("KeepAlive stream used: " + url); } serverInput = new KeepAliveStream(serverInput, pi, cl, this); failedOnce = false; diff --git a/src/share/classes/sun/net/www/http/KeepAliveCache.java b/src/share/classes/sun/net/www/http/KeepAliveCache.java index 4ec0111651a5e4099607c8ae45526ee9366e3396..5e41c33ae1156ec833ce145bfe13a14ede95994a 100644 --- a/src/share/classes/sun/net/www/http/KeepAliveCache.java +++ b/src/share/classes/sun/net/www/http/KeepAliveCache.java @@ -25,12 +25,11 @@ package sun.net.www.http; -import java.io.InputStream; import java.io.IOException; import java.io.NotSerializableException; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; import java.net.URL; -import java.util.concurrent.ConcurrentHashMap; /** * A class that implements a cache of idle Http connections for keep-alive @@ -39,7 +38,7 @@ import java.util.concurrent.ConcurrentHashMap; * @author Dave Brown */ public class KeepAliveCache - extends ConcurrentHashMap + extends HashMap implements Runnable { private static final long serialVersionUID = -2937172892064557949L; @@ -163,8 +162,8 @@ public class KeepAliveCache * Errs on the side of caution (leave connections idle for a relatively * short time). */ + @Override public void run() { - int total_cache; do { try { Thread.sleep(LIFETIME); @@ -311,6 +310,7 @@ class KeepAliveKey { /** * Determine whether or not two objects of this type are equal */ + @Override public boolean equals(Object obj) { if ((obj instanceof KeepAliveKey) == false) return false; @@ -325,6 +325,7 @@ class KeepAliveKey { * The hashCode() for this object is the string hashCode() of * concatenation of the protocol, host name and port. */ + @Override public int hashCode() { String str = protocol+host+port; return this.obj == null? str.hashCode() : diff --git a/src/share/classes/sun/net/www/http/KeepAliveStream.java b/src/share/classes/sun/net/www/http/KeepAliveStream.java index 3a64c465e54d3fee2a86e405d112eccbc1155b60..ff5ffada90762a92940dd33555bfc439dfd36fd4 100644 --- a/src/share/classes/sun/net/www/http/KeepAliveStream.java +++ b/src/share/classes/sun/net/www/http/KeepAliveStream.java @@ -25,10 +25,7 @@ package sun.net.www.http; -import java.net.URL; -import java.net.HttpURLConnection; import java.io.*; -import java.util.StringTokenizer; import sun.net.ProgressSource; import sun.net.www.MeteredStream; @@ -50,9 +47,8 @@ class KeepAliveStream extends MeteredStream implements Hurryable { // has this KeepAliveStream been put on the queue for asynchronous cleanup. protected boolean queuedForCleanup = false; - private static KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner(); - private static Thread cleanerThread = null; - private static boolean startCleanupThread; + private static final KeepAliveStreamCleaner queue = new KeepAliveStreamCleaner(); + private static Thread cleanerThread; // null /** * Constructor @@ -155,43 +151,46 @@ class KeepAliveStream extends MeteredStream implements Hurryable { } } - private static synchronized void queueForCleanup(KeepAliveCleanerEntry kace) { - if(queue != null && !kace.getQueuedForCleanup()) { - if (!queue.offer(kace)) { - kace.getHttpClient().closeServer(); - return; - } + private static void queueForCleanup(KeepAliveCleanerEntry kace) { + synchronized(queue) { + if(!kace.getQueuedForCleanup()) { + if (!queue.offer(kace)) { + kace.getHttpClient().closeServer(); + return; + } - kace.setQueuedForCleanup(); - } + kace.setQueuedForCleanup(); + queue.notifyAll(); + } - startCleanupThread = (cleanerThread == null); - if (!startCleanupThread) { - if (!cleanerThread.isAlive()) { - startCleanupThread = true; + boolean startCleanupThread = (cleanerThread == null); + if (!startCleanupThread) { + if (!cleanerThread.isAlive()) { + startCleanupThread = true; + } } - } - if (startCleanupThread) { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - // We want to create the Keep-Alive-SocketCleaner in the - // system threadgroup - ThreadGroup grp = Thread.currentThread().getThreadGroup(); - ThreadGroup parent = null; - while ((parent = grp.getParent()) != null) { - grp = parent; + if (startCleanupThread) { + java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Void run() { + // We want to create the Keep-Alive-SocketCleaner in the + // system threadgroup + ThreadGroup grp = Thread.currentThread().getThreadGroup(); + ThreadGroup parent = null; + while ((parent = grp.getParent()) != null) { + grp = parent; + } + + cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner"); + cleanerThread.setDaemon(true); + cleanerThread.setPriority(Thread.MAX_PRIORITY - 2); + cleanerThread.start(); + return null; } - - cleanerThread = new Thread(grp, queue, "Keep-Alive-SocketCleaner"); - cleanerThread.setDaemon(true); - cleanerThread.setPriority(Thread.MAX_PRIORITY - 2); - cleanerThread.start(); - return null; - } - }); - } + }); + } + } // queue } protected long remainingToRead() { diff --git a/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java b/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java index 0b19b6bb88db8839f345c2da36975c3183e3b4a0..6bb28d68d9cb4b2c9539c74548b33a6462feacb2 100644 --- a/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java +++ b/src/share/classes/sun/net/www/http/KeepAliveStreamCleaner.java @@ -25,9 +25,8 @@ package sun.net.www.http; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; import java.io.IOException; +import java.util.LinkedList; import sun.net.NetProperties; import java.security.AccessController; import java.security.PrivilegedAction; @@ -44,7 +43,9 @@ import java.security.PrivilegedAction; */ @SuppressWarnings("serial") // never serialized -public class KeepAliveStreamCleaner extends LinkedBlockingQueue implements Runnable +class KeepAliveStreamCleaner + extends LinkedList + implements Runnable { // maximum amount of remaining data that we will try to cleanup protected static int MAX_DATA_REMAINING = 512; @@ -78,23 +79,39 @@ public class KeepAliveStreamCleaner extends LinkedBlockingQueue= MAX_CAPACITY) + return false; - public KeepAliveStreamCleaner(int capacity) - { - super(capacity); + return super.offer(e); } + @Override public void run() { KeepAliveCleanerEntry kace = null; do { try { - kace = poll((long)TIMEOUT, TimeUnit.MILLISECONDS); + synchronized(this) { + long before = System.currentTimeMillis(); + long timeout = TIMEOUT; + while ((kace = poll()) == null) { + this.wait(timeout); + + long after = System.currentTimeMillis(); + long elapsed = after - before; + if (elapsed > timeout) { + /* one last try */ + kace = poll(); + break; + } + before = after; + timeout -= elapsed; + } + } + if(kace == null) break; diff --git a/src/share/classes/sun/net/www/protocol/http/AuthCache.java b/src/share/classes/sun/net/www/protocol/http/AuthCache.java index 26ad1ac7bbcd70e38dade1777f492e62076fc1aa..704ca1b7f218c9d254a3a4431d4706dbd0b56900 100644 --- a/src/share/classes/sun/net/www/protocol/http/AuthCache.java +++ b/src/share/classes/sun/net/www/protocol/http/AuthCache.java @@ -25,14 +25,6 @@ package sun.net.www.protocol.http; -import java.io.IOException; -import java.net.URL; -import java.util.Hashtable; -import java.util.LinkedList; -import java.util.ListIterator; -import java.util.Enumeration; -import java.util.HashMap; - /** * @author Michael McMahon * @@ -49,7 +41,7 @@ public interface AuthCache { * A:[B:]C:D:E[:F] Between 4 and 6 fields separated by ":" * where the fields have the following meaning: * A is "s" or "p" for server or proxy authentication respectively - * B is optional and is "D", "B", or "N" for digest, basic or ntlm auth. + * B is optional and is the {@link AuthScheme}, e.g. BASIC, DIGEST, NTLM, etc * C is either "http" or "https" * D is the hostname * E is the port number diff --git a/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java b/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java index 539d483b2e41ee9c5123e4067d1065a8c74b94a4..27eca1a6dc76be2a58d330037c7e71313b39fe0c 100644 --- a/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java +++ b/src/share/classes/sun/net/www/protocol/http/AuthCacheValue.java @@ -25,15 +25,8 @@ package sun.net.www.protocol.http; -import java.io.IOException; import java.io.Serializable; -import java.net.*; -import java.util.Hashtable; -import java.util.LinkedList; -import java.util.ListIterator; -import java.util.Enumeration; -import java.util.HashMap; - +import java.net.PasswordAuthentication; /** * AuthCacheValue: interface to minimise exposure to authentication cache @@ -62,8 +55,16 @@ public abstract class AuthCacheValue implements Serializable { AuthCacheValue() {} + /** + * Proxy or Server + */ abstract Type getAuthType (); + /** + * Authentication scheme + */ + abstract AuthScheme getAuthScheme(); + /** * name of server/proxy */ diff --git a/src/share/classes/sun/net/www/protocol/http/AuthScheme.java b/src/share/classes/sun/net/www/protocol/http/AuthScheme.java new file mode 100644 index 0000000000000000000000000000000000000000..bdc070fd9aa746a77885241f04e0997c367f2b5f --- /dev/null +++ b/src/share/classes/sun/net/www/protocol/http/AuthScheme.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 sun.net.www.protocol.http; + +/* Authentication schemes supported by the http implementation. New schemes, if + * supported, should be defined here. + */ +public enum AuthScheme { + BASIC, + DIGEST, + NTLM, + NEGOTIATE, + KERBEROS, + UNKNOWN; +} + diff --git a/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java b/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java index 042ad693d5200c06ee1968d7edaf22af6496acd6..f5cfd33c9981f5e60ebf7c1e8987779d83004130 100644 --- a/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java +++ b/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java @@ -85,6 +85,11 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { AuthCacheValue.Type.Server: AuthCacheValue.Type.Proxy; } + + AuthScheme getAuthScheme() { + return authScheme; + } + public String getHost() { return host; } @@ -151,7 +156,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { } //public String toString () { - //return ("{"+type+":"+authType+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}"); + //return ("{"+type+":"+authScheme+":"+protocol+":"+host+":"+port+":"+realm+":"+path+"}"); //} // REMIND: This cache just grows forever. We should put in a bounded @@ -160,8 +165,8 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { /** The type (server/proxy) of authentication this is. Used for key lookup */ char type; - /** The authentication type (basic/digest). Also used for key lookup */ - char authType; + /** The authentication scheme (basic/digest). Also used for key lookup */ + AuthScheme authScheme; /** The protocol/scheme (i.e. http or https ). Need to keep the caches * logically separate for the two protocols. This field is only used @@ -183,9 +188,9 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { String path; /** Use this constructor only for proxy entries */ - AuthenticationInfo(char type, char authType, String host, int port, String realm) { + AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) { this.type = type; - this.authType = authType; + this.authScheme = authScheme; this.protocol = ""; this.host = host.toLowerCase(); this.port = port; @@ -206,9 +211,9 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { * Constructor used to limit the authorization to the path within * the URL. Use this constructor for origin server entries. */ - AuthenticationInfo(char type, char authType, URL url, String realm) { + AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) { this.type = type; - this.authType = authType; + this.authScheme = authScheme; this.protocol = url.getProtocol().toLowerCase(); this.host = url.getHost().toLowerCase(); this.port = url.getPort(); @@ -264,12 +269,12 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { * In this case we do not use the path because the protection space * is identified by the host:port:realm only */ - static AuthenticationInfo getServerAuth(URL url, String realm, char atype) { + static AuthenticationInfo getServerAuth(URL url, String realm, AuthScheme scheme) { int port = url.getPort(); if (port == -1) { port = url.getDefaultPort(); } - String key = SERVER_AUTHENTICATION + ":" + atype + ":" + url.getProtocol().toLowerCase() + String key = SERVER_AUTHENTICATION + ":" + scheme + ":" + url.getProtocol().toLowerCase() + ":" + url.getHost().toLowerCase() + ":" + port + ":" + realm; AuthenticationInfo cached = getAuth(key, null); if ((cached == null) && requestIsInProgress (key)) { @@ -308,8 +313,8 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { * Used in response to a challenge. Note, the protocol field is always * blank for proxies. */ - static AuthenticationInfo getProxyAuth(String host, int port, String realm, char atype) { - String key = PROXY_AUTHENTICATION + ":" + atype + "::" + host.toLowerCase() + static AuthenticationInfo getProxyAuth(String host, int port, String realm, AuthScheme scheme) { + String key = PROXY_AUTHENTICATION + ":" + scheme + "::" + host.toLowerCase() + ":" + port + ":" + realm; AuthenticationInfo cached = (AuthenticationInfo) cache.get(key, null); if ((cached == null) && requestIsInProgress (key)) { @@ -409,7 +414,7 @@ abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable { // This must be kept in sync with the getXXXAuth() methods in this // class. if (includeRealm) { - return type + ":" + authType + ":" + protocol + ":" + return type + ":" + authScheme + ":" + protocol + ":" + host + ":" + port + ":" + realm; } else { return type + ":" + protocol + ":" + host + ":" + port; diff --git a/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java b/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java index 22f1c28a49f0b0a702c07dc10338af996b67ace1..ba2cfad52b7df73b28952fd1852dad3403957af5 100644 --- a/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java +++ b/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java @@ -44,8 +44,6 @@ class BasicAuthentication extends AuthenticationInfo { private static final long serialVersionUID = 100L; - static final char BASIC_AUTH = 'B'; - /** The authentication string for this host, port, and realm. This is a simple BASE64 encoding of "login:password". */ String auth; @@ -56,7 +54,7 @@ class BasicAuthentication extends AuthenticationInfo { public BasicAuthentication(boolean isProxy, String host, int port, String realm, PasswordAuthentication pw) { super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, - BASIC_AUTH, host, port, realm); + AuthScheme.BASIC, host, port, realm); String plain = pw.getUserName() + ":"; byte[] nameBytes = null; try { @@ -86,7 +84,7 @@ class BasicAuthentication extends AuthenticationInfo { public BasicAuthentication(boolean isProxy, String host, int port, String realm, String auth) { super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, - BASIC_AUTH, host, port, realm); + AuthScheme.BASIC, host, port, realm); this.auth = "Basic " + auth; } @@ -96,7 +94,7 @@ class BasicAuthentication extends AuthenticationInfo { public BasicAuthentication(boolean isProxy, URL url, String realm, PasswordAuthentication pw) { super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, - BASIC_AUTH, url, realm); + AuthScheme.BASIC, url, realm); String plain = pw.getUserName() + ":"; byte[] nameBytes = null; try { @@ -126,7 +124,7 @@ class BasicAuthentication extends AuthenticationInfo { public BasicAuthentication(boolean isProxy, URL url, String realm, String auth) { super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, - BASIC_AUTH, url, realm); + AuthScheme.BASIC, url, realm); this.auth = "Basic " + auth; } diff --git a/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java b/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java index 8ddaa4d87d3b83f79445527c54e1cd85c6bccf66..99026760089be0dec3bc929b460e6185db549622 100644 --- a/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java +++ b/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java @@ -38,7 +38,6 @@ import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import static sun.net.www.protocol.http.HttpURLConnection.HTTP_CONNECT; - /** * DigestAuthentication: Encapsulate an http server authentication using * the "Digest" scheme, as described in RFC2069 and updated in RFC2617 @@ -50,8 +49,6 @@ class DigestAuthentication extends AuthenticationInfo { private static final long serialVersionUID = 100L; - static final char DIGEST_AUTH = 'D'; - private String authMethod; // Authentication parameters defined in RFC2617. @@ -178,7 +175,10 @@ class DigestAuthentication extends AuthenticationInfo { public DigestAuthentication(boolean isProxy, URL url, String realm, String authMethod, PasswordAuthentication pw, Parameters params) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,url, realm); + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, + AuthScheme.DIGEST, + url, + realm); this.authMethod = authMethod; this.pw = pw; this.params = params; @@ -187,7 +187,11 @@ class DigestAuthentication extends AuthenticationInfo { public DigestAuthentication(boolean isProxy, String host, int port, String realm, String authMethod, PasswordAuthentication pw, Parameters params) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, DIGEST_AUTH,host, port, realm); + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, + AuthScheme.DIGEST, + host, + port, + realm); this.authMethod = authMethod; this.pw = pw; this.params = params; diff --git a/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java b/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java index 97b9be64ed17691ed1205f4041235b51fdfdfde1..b1b5a0d78212f0b5729cf37d280aadd71d7f2aee 100644 --- a/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java +++ b/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java @@ -49,8 +49,10 @@ public class HttpLogFormatter extends java.util.logging.SimpleFormatter { @Override public String format(LogRecord record) { - if (!"sun.net.www.http.HttpCapture".equalsIgnoreCase(record.getSourceClassName())) { - // Don't change format for stuff that doesn't concern us + String sourceClassName = record.getSourceClassName(); + if (sourceClassName == null || + !(sourceClassName.startsWith("sun.net.www.protocol.http") || + sourceClassName.startsWith("sun.net.www.http"))) { return super.format(record); } String src = record.getMessage(); diff --git a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index d56602c50685af79515cc518ba80e29b1e602612..5a52099fdee309d2dc34b32cf7b26a9b5e4e91ab 100644 --- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -57,11 +57,17 @@ import sun.net.www.http.HttpClient; import sun.net.www.http.PosterOutputStream; import sun.net.www.http.ChunkedInputStream; import sun.net.www.http.ChunkedOutputStream; -import sun.net.www.http.HttpCapture; +import sun.util.logging.PlatformLogger; import java.text.SimpleDateFormat; import java.util.TimeZone; import java.net.MalformedURLException; import java.nio.ByteBuffer; +import static sun.net.www.protocol.http.AuthScheme.BASIC; +import static sun.net.www.protocol.http.AuthScheme.DIGEST; +import static sun.net.www.protocol.http.AuthScheme.NTLM; +import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; +import static sun.net.www.protocol.http.AuthScheme.KERBEROS; +import static sun.net.www.protocol.http.AuthScheme.UNKNOWN; /** * A class to represent an HTTP connection to a remote object. @@ -231,9 +237,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection { boolean needToCheck = true; private boolean doingNTLM2ndStage = false; /* doing the 2nd stage of an NTLM server authentication */ private boolean doingNTLMp2ndStage = false; /* doing the 2nd stage of an NTLM proxy authentication */ - /* try auth without calling Authenticator */ - private boolean tryTransparentNTLMServer = NTLMAuthentication.supportsTransparentAuth(); - private boolean tryTransparentNTLMProxy = NTLMAuthentication.supportsTransparentAuth(); + + /* try auth without calling Authenticator. Used for transparent NTLM authentication */ + private boolean tryTransparentNTLMServer = true; + private boolean tryTransparentNTLMProxy = true; + /* Used by Windows specific code */ Object authObj; @@ -284,6 +292,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection { private int connectTimeout = -1; private int readTimeout = -1; + /* Logging support */ + private static final PlatformLogger logger = + PlatformLogger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); + /* * privileged request password authentication * @@ -301,20 +313,25 @@ public class HttpURLConnection extends java.net.HttpURLConnection { return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public PasswordAuthentication run() { - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("Requesting Authentication: host =" + host + " url = " + url); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("Requesting Authentication: host =" + host + " url = " + url); } PasswordAuthentication pass = Authenticator.requestPasswordAuthentication( host, addr, port, protocol, prompt, scheme, url, authType); - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("Authentication returned: " + (pass != null ? pass.toString() : "null")); } return pass; } }); } + /* Logging support */ + public static PlatformLogger getHttpLogger() { + return logger; + } + /* * checks the validity of http message header and throws * IllegalArgumentException if invalid. @@ -463,8 +480,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { setRequests=true; } - if (HttpCapture.isLoggable("FINE")) { - HttpCapture.fine(requests.toString()); + if (logger.isLoggable(PlatformLogger.FINE)) { + logger.fine(requests.toString()); } http.writeRequests(requests, poster); if (ps.checkError()) { @@ -728,9 +745,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { && !(cachedResponse instanceof SecureCacheResponse)) { cachedResponse = null; } - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("Cache Request for " + uri + " / " + getRequestMethod()); - HttpCapture.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null")); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("Cache Request for " + uri + " / " + getRequestMethod()); + logger.finest("From cache: " + (cachedResponse != null ? cachedResponse.toString() : "null")); } if (cachedResponse != null) { cachedHeaders = mapToMessageHeader(cachedResponse.getHeaders()); @@ -769,8 +786,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { }); if (sel != null) { URI uri = sun.net.www.ParseUtil.toURI(url); - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("ProxySelector Request for " + uri); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("ProxySelector Request for " + uri); } Iterator it = sel.select(uri).iterator(); Proxy p; @@ -786,9 +803,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { http = getNewHttpClient(url, p, connectTimeout, false); http.setReadTimeout(readTimeout); } - if (HttpCapture.isLoggable("FINEST")) { + if (logger.isLoggable(PlatformLogger.FINEST)) { if (p != null) { - HttpCapture.finest("Proxy used: " + p.toString()); + logger.finest("Proxy used: " + p.toString()); } } break; @@ -1018,15 +1035,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection { URI uri = ParseUtil.toURI(url); if (uri != null) { - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("CookieHandler request for " + uri); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("CookieHandler request for " + uri); } Map> cookies = cookieHandler.get( uri, requests.getHeaders(EXCLUDE_HEADERS)); if (!cookies.isEmpty()) { - if (HttpCapture.isLoggable("FINEST")) { - HttpCapture.finest("Cookies retrieved: " + cookies.toString()); + if (logger.isLoggable(PlatformLogger.FINEST)) { + logger.finest("Cookies retrieved: " + cookies.toString()); } for (Map.Entry> entry : cookies.entrySet()) { @@ -1157,8 +1174,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { writeRequests(); } http.parseHTTP(responses, pi, this); - if (HttpCapture.isLoggable("FINE")) { - HttpCapture.fine(responses.toString()); + if (logger.isLoggable(PlatformLogger.FINE)) { + logger.fine(responses.toString()); } inputStream = http.getInputStream(); @@ -1270,7 +1287,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection { String raw = srvHdr.raw(); if (!doingNTLM2ndStage) { if ((serverAuthentication != null)&& - !(serverAuthentication instanceof NTLMAuthentication)) { + serverAuthentication.getAuthScheme() != NTLM) { if (serverAuthentication.isAuthorizationStale (raw)) { /* we can retry with the current credentials */ disconnectInternal(); @@ -1523,8 +1540,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { */ private AuthenticationInfo resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) { - if ((proxyAuthentication != null )&& ! (proxyAuthentication instanceof - NTLMAuthentication)) { + if ((proxyAuthentication != null )&& + proxyAuthentication.getAuthScheme() != NTLM) { String raw = auth.raw(); if (proxyAuthentication.isAuthorizationStale (raw)) { /* we can retry with the current credentials */ @@ -1602,8 +1619,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { http.parseHTTP(responses, null, this); /* Log the response to the CONNECT */ - if (HttpCapture.isLoggable("FINE")) { - HttpCapture.fine(responses.toString()); + if (logger.isLoggable(PlatformLogger.FINE)) { + logger.fine(responses.toString()); } statusLine = responses.getValue(0); @@ -1730,8 +1747,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { setPreemptiveProxyAuthentication(requests); /* Log the CONNECT request */ - if (HttpCapture.isLoggable("FINE")) { - HttpCapture.fine(requests.toString()); + if (logger.isLoggable(PlatformLogger.FINE)) { + logger.fine(requests.toString()); } http.writeRequests(requests, null); @@ -1776,28 +1793,31 @@ public class HttpURLConnection extends java.net.HttpURLConnection { HeaderParser p = authhdr.headerParser(); String realm = p.findValue("realm"); String scheme = authhdr.scheme(); - char schemeID; + AuthScheme authScheme = UNKNOWN; if ("basic".equalsIgnoreCase(scheme)) { - schemeID = BasicAuthentication.BASIC_AUTH; + authScheme = BASIC; } else if ("digest".equalsIgnoreCase(scheme)) { - schemeID = DigestAuthentication.DIGEST_AUTH; + authScheme = DIGEST; } else if ("ntlm".equalsIgnoreCase(scheme)) { - schemeID = NTLMAuthentication.NTLM_AUTH; + authScheme = NTLM; doingNTLMp2ndStage = true; } else if ("Kerberos".equalsIgnoreCase(scheme)) { - schemeID = NegotiateAuthentication.KERBEROS_AUTH; + authScheme = KERBEROS; doingNTLMp2ndStage = true; } else if ("Negotiate".equalsIgnoreCase(scheme)) { - schemeID = NegotiateAuthentication.NEGOTIATE_AUTH; + authScheme = NEGOTIATE; doingNTLMp2ndStage = true; - } else { - schemeID = 0; } + if (realm == null) realm = ""; - ret = AuthenticationInfo.getProxyAuth(host, port, realm, schemeID); + ret = AuthenticationInfo.getProxyAuth(host, + port, + realm, + authScheme); if (ret == null) { - if (schemeID == BasicAuthentication.BASIC_AUTH) { + switch (authScheme) { + case BASIC: InetAddress addr = null; try { final String finalHost = host; @@ -1818,9 +1838,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { if (a != null) { ret = new BasicAuthentication(true, host, port, realm, a); } - } else if (schemeID == DigestAuthentication.DIGEST_AUTH) { - PasswordAuthentication a = - privilegedRequestPasswordAuthentication( + break; + case DIGEST: + a = privilegedRequestPasswordAuthentication( host, null, port, url.getProtocol(), realm, scheme, url, RequestorType.PROXY); if (a != null) { @@ -1829,29 +1849,49 @@ public class HttpURLConnection extends java.net.HttpURLConnection { ret = new DigestAuthentication(true, host, port, realm, scheme, a, params); } - } else if (schemeID == NTLMAuthentication.NTLM_AUTH) { - PasswordAuthentication a = null; - if (!tryTransparentNTLMProxy) { - a = privilegedRequestPasswordAuthentication( - host, null, port, url.getProtocol(), - "", scheme, url, RequestorType.PROXY); - } - /* If we are not trying transparent authentication then - * we need to have a PasswordAuthentication instance. For - * transparent authentication (Windows only) the username - * and password will be picked up from the current logged - * on users credentials. - */ - if (tryTransparentNTLMProxy || - (!tryTransparentNTLMProxy && a != null)) { - ret = new NTLMAuthentication(true, host, port, a); - } + break; + case NTLM: + if (NTLMAuthenticationProxy.proxy.supported) { + /* tryTransparentNTLMProxy will always be true the first + * time around, but verify that the platform supports it + * otherwise don't try. */ + if (tryTransparentNTLMProxy) { + tryTransparentNTLMProxy = + NTLMAuthenticationProxy.proxy.supportsTransparentAuth; + } + a = null; + if (tryTransparentNTLMProxy) { + logger.finest("Trying Transparent NTLM authentication"); + } else { + a = privilegedRequestPasswordAuthentication( + host, null, port, url.getProtocol(), + "", scheme, url, RequestorType.PROXY); + } + /* If we are not trying transparent authentication then + * we need to have a PasswordAuthentication instance. For + * transparent authentication (Windows only) the username + * and password will be picked up from the current logged + * on users credentials. + */ + if (tryTransparentNTLMProxy || + (!tryTransparentNTLMProxy && a != null)) { + ret = NTLMAuthenticationProxy.proxy.create(true, host, port, a); + } - tryTransparentNTLMProxy = false; - } else if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) { + /* set to false so that we do not try again */ + tryTransparentNTLMProxy = false; + } + break; + case NEGOTIATE: ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate")); - } else if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) { + break; + case KERBEROS: ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos")); + break; + case UNKNOWN: + logger.finest("Unknown/Unsupported authentication scheme: " + scheme); + default: + throw new AssertionError("should not reach here"); } } // For backwards compatibility, we also try defaultAuth @@ -1875,8 +1915,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } } - if (HttpCapture.isLoggable("FINER")) { - HttpCapture.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null")); + if (logger.isLoggable(PlatformLogger.FINER)) { + logger.finer("Proxy Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null")); } return ret; } @@ -1896,27 +1936,26 @@ public class HttpURLConnection extends java.net.HttpURLConnection { HeaderParser p = authhdr.headerParser(); String realm = p.findValue("realm"); String scheme = authhdr.scheme(); - char schemeID; + AuthScheme authScheme = UNKNOWN; if ("basic".equalsIgnoreCase(scheme)) { - schemeID = BasicAuthentication.BASIC_AUTH; + authScheme = BASIC; } else if ("digest".equalsIgnoreCase(scheme)) { - schemeID = DigestAuthentication.DIGEST_AUTH; + authScheme = DIGEST; } else if ("ntlm".equalsIgnoreCase(scheme)) { - schemeID = NTLMAuthentication.NTLM_AUTH; + authScheme = NTLM; doingNTLM2ndStage = true; } else if ("Kerberos".equalsIgnoreCase(scheme)) { - schemeID = NegotiateAuthentication.KERBEROS_AUTH; + authScheme = KERBEROS; doingNTLM2ndStage = true; } else if ("Negotiate".equalsIgnoreCase(scheme)) { - schemeID = NegotiateAuthentication.NEGOTIATE_AUTH; + authScheme = NEGOTIATE; doingNTLM2ndStage = true; - } else { - schemeID = 0; } + domain = p.findValue ("domain"); if (realm == null) realm = ""; - ret = AuthenticationInfo.getServerAuth(url, realm, schemeID); + ret = AuthenticationInfo.getServerAuth(url, realm, authScheme); InetAddress addr = null; if (ret == null) { try { @@ -1931,13 +1970,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { port = url.getDefaultPort(); } if (ret == null) { - if (schemeID == NegotiateAuthentication.KERBEROS_AUTH) { + switch(authScheme) { + case KERBEROS: ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Kerberos")); - } - if (schemeID == NegotiateAuthentication.NEGOTIATE_AUTH) { + break; + case NEGOTIATE: ret = new NegotiateAuthentication(new HttpCallerInfo(authhdr.getHttpCallerInfo(), "Negotiate")); - } - if (schemeID == BasicAuthentication.BASIC_AUTH) { + break; + case BASIC: PasswordAuthentication a = privilegedRequestPasswordAuthentication( url.getHost(), addr, port, url.getProtocol(), @@ -1945,45 +1985,60 @@ public class HttpURLConnection extends java.net.HttpURLConnection { if (a != null) { ret = new BasicAuthentication(false, url, realm, a); } - } - - if (schemeID == DigestAuthentication.DIGEST_AUTH) { - PasswordAuthentication a = - privilegedRequestPasswordAuthentication( + break; + case DIGEST: + a = privilegedRequestPasswordAuthentication( url.getHost(), addr, port, url.getProtocol(), realm, scheme, url, RequestorType.SERVER); if (a != null) { digestparams = new DigestAuthentication.Parameters(); ret = new DigestAuthentication(false, url, realm, scheme, a, digestparams); } - } + break; + case NTLM: + if (NTLMAuthenticationProxy.proxy.supported) { + URL url1; + try { + url1 = new URL (url, "/"); /* truncate the path */ + } catch (Exception e) { + url1 = url; + } - if (schemeID == NTLMAuthentication.NTLM_AUTH) { - URL url1; - try { - url1 = new URL (url, "/"); /* truncate the path */ - } catch (Exception e) { - url1 = url; - } - PasswordAuthentication a = null; - if (!tryTransparentNTLMServer) { - a = privilegedRequestPasswordAuthentication( - url.getHost(), addr, port, url.getProtocol(), - "", scheme, url, RequestorType.SERVER); - } + /* tryTransparentNTLMServer will always be true the first + * time around, but verify that the platform supports it + * otherwise don't try. */ + if (tryTransparentNTLMServer) { + tryTransparentNTLMServer = + NTLMAuthenticationProxy.proxy.supportsTransparentAuth; + } + a = null; + if (tryTransparentNTLMServer) { + logger.finest("Trying Transparent NTLM authentication"); + } else { + a = privilegedRequestPasswordAuthentication( + url.getHost(), addr, port, url.getProtocol(), + "", scheme, url, RequestorType.SERVER); + } - /* If we are not trying transparent authentication then - * we need to have a PasswordAuthentication instance. For - * transparent authentication (Windows only) the username - * and password will be picked up from the current logged - * on users credentials. - */ - if (tryTransparentNTLMServer || - (!tryTransparentNTLMServer && a != null)) { - ret = new NTLMAuthentication(false, url1, a); - } + /* If we are not trying transparent authentication then + * we need to have a PasswordAuthentication instance. For + * transparent authentication (Windows only) the username + * and password will be picked up from the current logged + * on users credentials. + */ + if (tryTransparentNTLMServer || + (!tryTransparentNTLMServer && a != null)) { + ret = NTLMAuthenticationProxy.proxy.create(false, url1, a); + } - tryTransparentNTLMServer = false; + /* set to false so that we do not try again */ + tryTransparentNTLMServer = false; + } + break; + case UNKNOWN: + logger.finest("Unknown/Unsupported authentication scheme: " + scheme); + default: + throw new AssertionError("should not reach here"); } } @@ -2005,8 +2060,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } } - if (HttpCapture.isLoggable("FINER")) { - HttpCapture.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null")); + if (logger.isLoggable(PlatformLogger.FINER)) { + logger.finer("Server Authentication for " + authhdr.toString() +" returned " + (ret != null ? ret.toString() : "null")); } return ret; } @@ -2081,8 +2136,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { if (streaming()) { throw new HttpRetryException (RETRY_MSG3, stat, loc); } - if (HttpCapture.isLoggable("FINE")) { - HttpCapture.fine("Redirected from " + url + " to " + locUrl); + if (logger.isLoggable(PlatformLogger.FINE)) { + logger.fine("Redirected from " + url + " to " + locUrl); } // clear out old response headers!!!! diff --git a/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java b/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java new file mode 100644 index 0000000000000000000000000000000000000000..646728fb9e6484f682e9117f0d9b5129f4b04235 --- /dev/null +++ b/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java @@ -0,0 +1,131 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.net.www.protocol.http; + +import java.net.URL; +import java.net.PasswordAuthentication; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import sun.util.logging.PlatformLogger; + +/** + * Proxy class for loading NTLMAuthentication, so as to remove static + * dependancy. + */ +class NTLMAuthenticationProxy { + private static Method supportsTA; + private static final String clazzStr = "sun.net.www.protocol.http.NTLMAuthentication"; + private static final String supportsTAStr = "supportsTransparentAuth"; + + static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication(); + static final boolean supported = proxy != null ? true : false; + static final boolean supportsTransparentAuth = supported ? supportsTransparentAuth(supportsTA) : false; + + private final Constructor threeArgCtr; + private final Constructor fiveArgCtr; + + private NTLMAuthenticationProxy(Constructor threeArgCtr, + Constructor fiveArgCtr) { + this.threeArgCtr = threeArgCtr; + this.fiveArgCtr = fiveArgCtr; + } + + + AuthenticationInfo create(boolean isProxy, + URL url, + PasswordAuthentication pw) { + try { + return threeArgCtr.newInstance(isProxy, url, pw); + } catch (ReflectiveOperationException roe) { + finest(roe); + } + + return null; + } + + AuthenticationInfo create(boolean isProxy, + String host, + int port, + PasswordAuthentication pw) { + try { + return fiveArgCtr.newInstance(isProxy, host, port, pw); + } catch (ReflectiveOperationException roe) { + finest(roe); + } + + return null; + } + + /* Returns true if the NTLM implementation supports transparent + * authentication (try with the current users credentials before + * prompting for username and password, etc). + */ + private static boolean supportsTransparentAuth(Method method) { + try { + return (Boolean)method.invoke(null); + } catch (ReflectiveOperationException roe) { + finest(roe); + } + + return false; + } + + /** + * Loads the NTLM authentiation implementation through reflection. If + * the class is present, then it must have the required constructors and + * method. Otherwise, it is considered an error. + */ + @SuppressWarnings("unchecked") + private static NTLMAuthenticationProxy tryLoadNTLMAuthentication() { + Class cl; + Constructor threeArg, fiveArg; + try { + cl = (Class)Class.forName(clazzStr, true, null); + if (cl != null) { + threeArg = cl.getConstructor(boolean.class, + URL.class, + PasswordAuthentication.class); + fiveArg = cl.getConstructor(boolean.class, + String.class, + int.class, + PasswordAuthentication.class); + supportsTA = cl.getDeclaredMethod(supportsTAStr); + return new NTLMAuthenticationProxy(threeArg, + fiveArg); + } + } catch (ClassNotFoundException cnfe) { + finest(cnfe); + } catch (ReflectiveOperationException roe) { + throw new AssertionError(roe); + } + + return null; + } + + static void finest(Exception e) { + PlatformLogger logger = HttpURLConnection.getHttpLogger(); + logger.finest("NTLMAuthenticationProxy: " + e); + } +} diff --git a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java index db5d509a3642a8232b907dbf411c7ba59e5fc3e6..3faedd279f2010f3f509c2177fe38c90d2519eda 100644 --- a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +++ b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java @@ -30,11 +30,14 @@ import java.util.HashMap; import sun.net.www.HeaderParser; import sun.misc.BASE64Decoder; import sun.misc.BASE64Encoder; +import sun.util.logging.PlatformLogger; import java.net.URL; import java.io.IOException; import java.net.Authenticator.RequestorType; - +import java.lang.reflect.Constructor; +import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE; +import static sun.net.www.protocol.http.AuthScheme.KERBEROS; /** * NegotiateAuthentication: @@ -49,9 +52,6 @@ class NegotiateAuthentication extends AuthenticationInfo { final private HttpCallerInfo hci; - static final char NEGOTIATE_AUTH = 'S'; - static final char KERBEROS_AUTH = 'K'; - // These maps are used to manage the GSS availability for diffrent // hosts. The key for both maps is the host name. // supported is set when isSupported is checked, @@ -68,11 +68,10 @@ class NegotiateAuthentication extends AuthenticationInfo { * @param hci a schemed object. */ public NegotiateAuthentication(HttpCallerInfo hci) { - super(RequestorType.PROXY==hci.authType? - PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, - hci.scheme.equalsIgnoreCase("Negotiate")? - NEGOTIATE_AUTH:KERBEROS_AUTH, - hci.url, ""); + super(RequestorType.PROXY==hci.authType ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, + hci.scheme.equalsIgnoreCase("Negotiate") ? NEGOTIATE : KERBEROS, + hci.url, + ""); this.hci = hci; } @@ -249,13 +248,41 @@ abstract class Negotiator { // The current implementation will make sure NegotiatorImpl is not // directly referenced when compiling, thus smooth the way of building // the J2SE platform where HttpURLConnection is a bootstrap class. + // + // Makes NegotiatorImpl, and the security classes it references, a + // runtime dependency rather than a static one. + + Class clazz; + Constructor c; + try { + clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl", true, null); + c = clazz.getConstructor(HttpCallerInfo.class); + } catch (ClassNotFoundException cnfe) { + finest(cnfe); + throw cnfe; + } catch (ReflectiveOperationException roe) { + // if the class is there then something seriously wrong if + // the constructor is not. + throw new AssertionError(roe); + } - Class clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl"); - java.lang.reflect.Constructor c = clazz.getConstructor(HttpCallerInfo.class); - return (Negotiator) (c.newInstance(hci)); + try { + return (Negotiator) (c.newInstance(hci)); + } catch (ReflectiveOperationException roe) { + finest(roe); + Throwable t = roe.getCause(); + if (t != null && t instanceof Exception) + finest((Exception)t); + throw roe; + } } abstract byte[] firstToken() throws IOException; abstract byte[] nextToken(byte[] in) throws IOException; + + static void finest(Exception e) { + PlatformLogger logger = HttpURLConnection.getHttpLogger(); + logger.finest("NegotiateAuthentication: " + e); + } } diff --git a/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java b/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java new file mode 100644 index 0000000000000000000000000000000000000000..3310c93e4febaf43e44ca24f45dcacc129e9be18 --- /dev/null +++ b/src/share/classes/sun/security/action/GetBooleanSecurityPropertyAction.java @@ -0,0 +1,74 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.security.action; + +import java.security.Security; + +/** + * A convenience class for retrieving the boolean value of a security property + * as a privileged action. + * + *

    An instance of this class can be used as the argument of + * AccessController.doPrivileged. + * + *

    The following code retrieves the boolean value of the security + * property named "prop" as a privileged action:

    + * + *

    + * boolean b = java.security.AccessController.doPrivileged
    + *              (new GetBooleanSecurityPropertyAction("prop")).booleanValue();
    + * 
    + * + */ +public class GetBooleanSecurityPropertyAction + implements java.security.PrivilegedAction { + private String theProp; + + /** + * Constructor that takes the name of the security property whose boolean + * value needs to be determined. + * + * @param theProp the name of the security property + */ + public GetBooleanSecurityPropertyAction(String theProp) { + this.theProp = theProp; + } + + /** + * Determines the boolean value of the security property whose name was + * specified in the constructor. + * + * @return the Boolean value of the security property. + */ + public Boolean run() { + boolean b = false; + try { + String value = Security.getProperty(theProp); + b = (value != null) && value.equalsIgnoreCase("true"); + } catch (NullPointerException e) {} + return b; + } +} diff --git a/src/share/classes/sun/security/ec/ECDHKeyAgreement.java b/src/share/classes/sun/security/ec/ECDHKeyAgreement.java index 8a61a7b1193f5395dc40ff39d505eb076be1b5d3..5ed3ffe2b006d2eaa17abf3bddfbac2a4b5a305b 100644 --- a/src/share/classes/sun/security/ec/ECDHKeyAgreement.java +++ b/src/share/classes/sun/security/ec/ECDHKeyAgreement.java @@ -39,21 +39,6 @@ import javax.crypto.spec.*; */ 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; @@ -65,16 +50,12 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { /** * Constructs a new ECDHKeyAgreement. - * - * @exception ProviderException if the native ECC library is unavailable. */ public ECDHKeyAgreement() { - if (!implementationPresent) { - throw new ProviderException("ECDH implementation is not available"); - } } // see JCE spec + @Override protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { if (!(key instanceof PrivateKey)) { @@ -86,6 +67,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { } // see JCE spec + @Override protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { @@ -97,6 +79,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { } // see JCE spec + @Override protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException { if (privateKey == null) { @@ -130,6 +113,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { } // see JCE spec + @Override protected byte[] engineGenerateSecret() throws IllegalStateException { if ((privateKey == null) || (publicValue == null)) { throw new IllegalStateException("Not initialized correctly"); @@ -150,6 +134,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { } // see JCE spec + @Override protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException { if (offset + secretLen > sharedSecret.length) { @@ -162,6 +147,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi { } // see JCE spec + @Override protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { diff --git a/src/share/classes/sun/security/ec/ECDSASignature.java b/src/share/classes/sun/security/ec/ECDSASignature.java index b2bf8936c1583da176f1852abd2f4376f3eb06b4..3c9857cd1c368af72b391012ae08278801d78ead 100644 --- a/src/share/classes/sun/security/ec/ECDSASignature.java +++ b/src/share/classes/sun/security/ec/ECDSASignature.java @@ -52,21 +52,6 @@ import sun.security.x509.AlgorithmId; */ 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; @@ -88,24 +73,13 @@ abstract class ECDSASignature extends SignatureSpi { * @exception ProviderException if the native ECC library is unavailable. */ ECDSASignature() { - if (!implementationPresent) { - throw new - ProviderException("ECDSA implementation is not available"); - } messageDigest = null; } /** * Constructs a new ECDSASignature. Used by subclasses. - * - * @exception ProviderException if the native ECC library is unavailable. */ ECDSASignature(String digestName) { - if (!implementationPresent) { - throw new - ProviderException("ECDSA implementation is not available"); - } - try { messageDigest = MessageDigest.getInstance(digestName); } catch (NoSuchAlgorithmException e) { @@ -299,8 +273,8 @@ abstract class ECDSASignature extends SignatureSpi { byte[] encodedParams = ECParameters.encodeParameters(params); // DER OID int keySize = params.getCurve().getField().getFieldSize(); - // seed is twice the key size (in bytes) - byte[] seed = new byte[((keySize + 7) >> 3) * 2]; + // seed is twice the key size (in bytes) plus 1 + byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2]; if (random == null) { random = JCAUtil.getSecureRandom(); } @@ -356,6 +330,7 @@ abstract class ECDSASignature extends SignatureSpi { // Convert the concatenation of R and S into their DER encoding private byte[] encodeSignature(byte[] signature) throws SignatureException { + try { int n = signature.length >> 1; diff --git a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java index af98de60b8b87887761aa739480897a37faf88d4..99b82521293d1538f4be525e095c60f176837f2d 100644 --- a/src/share/classes/sun/security/ec/ECKeyPairGenerator.java +++ b/src/share/classes/sun/security/ec/ECKeyPairGenerator.java @@ -46,20 +46,6 @@ import sun.security.jca.JCAUtil; */ 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; @@ -75,13 +61,8 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi { /** * Constructs a new ECKeyPairGenerator. - * - * @exception ProviderException if the native ECC library is unavailable. */ public ECKeyPairGenerator() { - if (!implementationPresent) { - throw new ProviderException("EC implementation is not available"); - } // initialize to default in case the app does not call initialize() initialize(KEY_SIZE_DEFAULT, null); } @@ -133,8 +114,8 @@ public final class ECKeyPairGenerator extends KeyPairGeneratorSpi { byte[] encodedParams = ECParameters.encodeParameters((ECParameterSpec)params); - // seed is twice the key size (in bytes) - byte[] seed = new byte[2 * ((keySize + 7) >> 3)]; + // seed is twice the key size (in bytes) plus 1 + byte[] seed = new byte[(((keySize + 7) >> 3) + 1) * 2]; if (random == null) { random = JCAUtil.getSecureRandom(); } diff --git a/src/share/classes/sun/security/ec/SunEC.java b/src/share/classes/sun/security/ec/SunEC.java index 49223ca37b21e6a7755ce5799381e8b31fb960a5..69afe5bf3523668ca04d2b52cdf186da49046a42 100644 --- a/src/share/classes/sun/security/ec/SunEC.java +++ b/src/share/classes/sun/security/ec/SunEC.java @@ -39,7 +39,10 @@ import sun.security.action.PutAllAction; * via JNI to a C++ wrapper class which in turn calls C functions. * The Java classes are packaged into the signed sunec.jar in the JRE * extensions directory and the C++ and C functions are packaged into - * libsunecc.so or sunecc.dll in the JRE native libraries directory. + * libsunec.so or sunec.dll in the JRE native libraries directory. + * If the native library is not present then this provider is registered + * with support for fewer ECC algorithms (KeyPairGenerator, Signature and + * KeyAgreement are omitted). * * @since 1.7 */ @@ -47,6 +50,22 @@ public final class SunEC extends Provider { private static final long serialVersionUID = -2279741672933606418L; + // flag indicating whether the full EC implementation is present + // (when native library is absent then fewer EC algorithms are available) + private static boolean useFullImplementation = true; + static { + try { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + System.loadLibrary("sunec"); // check for native library + return null; + } + }); + } catch (UnsatisfiedLinkError e) { + useFullImplementation = false; + } + } + public SunEC() { super("SunEC", 1.7d, "Sun Elliptic Curve provider (EC, ECDSA, ECDH)"); @@ -54,10 +73,10 @@ public final class SunEC extends Provider { // the provider. Otherwise, create a temporary map and use a // doPrivileged() call at the end to transfer the contents if (System.getSecurityManager() == null) { - SunECEntries.putEntries(this); + SunECEntries.putEntries(this, useFullImplementation); } else { Map map = new HashMap(); - SunECEntries.putEntries(map); + SunECEntries.putEntries(map, useFullImplementation); AccessController.doPrivileged(new PutAllAction(this, map)); } } diff --git a/src/share/classes/sun/security/ec/SunECEntries.java b/src/share/classes/sun/security/ec/SunECEntries.java index 759d3007e85a202e2163ca240146fbe3d6a719b4..58e99121a25d6088a4b38c8db4369770af4d621d 100644 --- a/src/share/classes/sun/security/ec/SunECEntries.java +++ b/src/share/classes/sun/security/ec/SunECEntries.java @@ -38,7 +38,93 @@ final class SunECEntries { // empty } - static void putEntries(Map map) { + static void putEntries(Map map, + boolean useFullImplementation) { + + /* + * Key Factory engine + */ + map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory"); + map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC"); + + map.put("KeyFactory.EC ImplementedIn", "Software"); + + /* + * Algorithm Parameter engine + */ + map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters"); + map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC"); + + map.put("AlgorithmParameters.EC KeySize", "256"); + + map.put("AlgorithmParameters.EC ImplementedIn", "Software"); + + map.put("AlgorithmParameters.EC SupportedCurves", + + // A list comprising lists of curve names and object identifiers. + // '[' ( ',' )+ ']' '|' + + // SEC 2 prime curves + "[secp112r1,1.3.132.0.6]|" + + "[secp112r2,1.3.132.0.7]|" + + "[secp128r1,1.3.132.0.28]|" + + "[secp128r2,1.3.132.0.29]|" + + "[secp160k1,1.3.132.0.9]|" + + "[secp160r1,1.3.132.0.8]|" + + "[secp160r2,1.3.132.0.30]|" + + "[secp192k1,1.3.132.0.31]|" + + "[secp192r1,NIST P-192,X9.62 prime192v1,1.2.840.10045.3.1.1]|" + + "[secp224k1,1.3.132.0.32]|" + + "[secp224r1,NIST P-224,1.3.132.0.33]|" + + "[secp256k1,1.3.132.0.10]|" + + "[secp256r1,NIST P-256,X9.62 prime256v1,1.2.840.10045.3.1.7]|" + + "[secp384r1,NIST P-384,1.3.132.0.34]|" + + "[secp521r1,NIST P-521,1.3.132.0.35]|" + + + // ANSI X9.62 prime curves + "[X9.62 prime192v2,1.2.840.10045.3.1.2]|" + + "[X9.62 prime192v3,1.2.840.10045.3.1.3]|" + + "[X9.62 prime239v1,1.2.840.10045.3.1.4]|" + + "[X9.62 prime239v2,1.2.840.10045.3.1.5]|" + + "[X9.62 prime239v3,1.2.840.10045.3.1.6]|" + + + // SEC 2 binary curves + "[sect113r1,1.3.132.0.4]|" + + "[sect113r2,1.3.132.0.5]|" + + "[sect131r1,1.3.132.0.22]|" + + "[sect131r2,1.3.132.0.23]|" + + "[sect163k1,NIST K-163,1.3.132.0.1]|" + + "[sect163r1,1.3.132.0.2]|" + + "[sect163r2,NIST B-163,1.3.132.0.15]|" + + "[sect193r1,1.3.132.0.24]|" + + "[sect193r2,1.3.132.0.25]|" + + "[sect233k1,NIST K-233,1.3.132.0.26]|" + + "[sect233r1,NIST B-233,1.3.132.0.27]|" + + "[sect239k1,1.3.132.0.3]|" + + "[sect283k1,NIST K-283,1.3.132.0.16]|" + + "[sect283r1,NIST B-283,1.3.132.0.17]|" + + "[sect409k1,NIST K-409,1.3.132.0.36]|" + + "[sect409r1,NIST B-409,1.3.132.0.37]|" + + "[sect571k1,NIST K-571,1.3.132.0.38]|" + + "[sect571r1,NIST B-571,1.3.132.0.39]|" + + + // ANSI X9.62 binary curves + "[X9.62 c2tnb191v1,1.2.840.10045.3.0.5]|" + + "[X9.62 c2tnb191v2,1.2.840.10045.3.0.6]|" + + "[X9.62 c2tnb191v3,1.2.840.10045.3.0.7]|" + + "[X9.62 c2tnb239v1,1.2.840.10045.3.0.11]|" + + "[X9.62 c2tnb239v2,1.2.840.10045.3.0.12]|" + + "[X9.62 c2tnb239v3,1.2.840.10045.3.0.13]|" + + "[X9.62 c2tnb359v1,1.2.840.10045.3.0.18]|" + + "[X9.62 c2tnb431r1,1.2.840.10045.3.0.20]"); + + /* + * Register the algorithms below only when the full ECC implementation + * is available + */ + if (!useFullImplementation) { + return; + } /* * Signature engines @@ -62,48 +148,31 @@ final class SunECEntries { map.put("Signature.SHA384withECDSA SupportedKeyClasses", ecKeyClasses); map.put("Signature.SHA512withECDSA SupportedKeyClasses", ecKeyClasses); + map.put("Signature.SHA1withECDSA KeySize", "256"); + + map.put("Signature.NONEwithECDSA ImplementedIn", "Software"); + map.put("Signature.SHA1withECDSA ImplementedIn", "Software"); + map.put("Signature.SHA256withECDSA ImplementedIn", "Software"); + map.put("Signature.SHA384withECDSA ImplementedIn", "Software"); + map.put("Signature.SHA512withECDSA ImplementedIn", "Software"); + /* * Key Pair Generator engine */ map.put("KeyPairGenerator.EC", "sun.security.ec.ECKeyPairGenerator"); map.put("Alg.Alias.KeyPairGenerator.EllipticCurve", "EC"); - /* - * Key Factory engine - */ - map.put("KeyFactory.EC", "sun.security.ec.ECKeyFactory"); - map.put("Alg.Alias.KeyFactory.EllipticCurve", "EC"); + map.put("KeyPairGenerator.EC KeySize", "256"); - /* - * Algorithm Parameter engine - */ - map.put("AlgorithmParameters.EC", "sun.security.ec.ECParameters"); - map.put("Alg.Alias.AlgorithmParameters.EllipticCurve", "EC"); + map.put("KeyPairGenerator.EC ImplementedIn", "Software"); /* * Key Agreement engine */ map.put("KeyAgreement.ECDH", "sun.security.ec.ECDHKeyAgreement"); - map.put("KeyAgreement.ECDH SupportedKeyClasses", ecKeyClasses); - /* - * Key sizes - */ - map.put("Signature.SHA1withECDSA KeySize", "256"); - map.put("KeyPairGenerator.EC KeySize", "256"); - map.put("AlgorithmParameterGenerator.ECDSA KeySize", "256"); + map.put("KeyAgreement.ECDH SupportedKeyClasses", ecKeyClasses); - /* - * 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/src/share/classes/sun/security/krb5/KrbKdcReq.java b/src/share/classes/sun/security/krb5/KrbKdcReq.java index 259aedd66fa35a848e221a065ba54cdb1b53991a..b915ff99711dd0fabf8bbf24b835dd3d0e3adce6 100644 --- a/src/share/classes/sun/security/krb5/KrbKdcReq.java +++ b/src/share/classes/sun/security/krb5/KrbKdcReq.java @@ -1,5 +1,5 @@ /* - * Portions Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,6 +149,11 @@ public abstract class KrbKdcReq { send(realm,tempKdc,useTCP); break; } catch (Exception e) { + if (DEBUG) { + System.out.println(">>> KrbKdcReq send: error trying " + + tempKdc); + e.printStackTrace(System.out); + } savedException = e; } } @@ -179,10 +184,36 @@ public abstract class KrbKdcReq { /* * Get port number for this KDC. */ - StringTokenizer strTok = new StringTokenizer(tempKdc, ":"); - String kdc = strTok.nextToken(); - if (strTok.hasMoreTokens()) { - String portStr = strTok.nextToken(); + String kdc = null; + String portStr = null; + + if (tempKdc.charAt(0) == '[') { // Explicit IPv6 in [] + int pos = tempKdc.indexOf(']', 1); + if (pos == -1) { + throw new IOException("Illegal KDC: " + tempKdc); + } + kdc = tempKdc.substring(1, pos); + if (pos != tempKdc.length() - 1) { // with port number + if (tempKdc.charAt(pos+1) != ':') { + throw new IOException("Illegal KDC: " + tempKdc); + } + portStr = tempKdc.substring(pos+2); + } + } else { + int colon = tempKdc.indexOf(':'); + if (colon == -1) { // Hostname or IPv4 host only + kdc = tempKdc; + } else { + int nextColon = tempKdc.indexOf(':', colon+1); + if (nextColon > 0) { // >=2 ":", IPv6 with no port + kdc = tempKdc; + } else { // 1 ":", hostname or IPv4 with port + kdc = tempKdc.substring(0, colon); + portStr = tempKdc.substring(colon+1); + } + } + } + if (portStr != null) { int tempPort = parsePositiveIntString(portStr); if (tempPort > 0) port = tempPort; diff --git a/src/share/classes/sun/security/provider/certpath/Builder.java b/src/share/classes/sun/security/provider/certpath/Builder.java index 8e13fb8b777318f775cd0fdd9ce8e330adc1c7af..5892b1b328db20d953664ccd484d147133b11c32 100644 --- a/src/share/classes/sun/security/provider/certpath/Builder.java +++ b/src/share/classes/sun/security/provider/certpath/Builder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,12 +26,14 @@ package sun.security.provider.certpath; import java.io.IOException; +import java.security.AccessController; import java.security.GeneralSecurityException; import java.security.cert.*; import java.util.*; import javax.security.auth.x500.X500Principal; +import sun.security.action.GetBooleanAction; import sun.security.util.Debug; import sun.security.x509.GeneralNames; import sun.security.x509.GeneralNameInterface; @@ -64,9 +66,8 @@ public abstract class Builder { * Authority Information Access extension shall be enabled. Currently * disabled by default for compatibility reasons. */ - final static boolean USE_AIA = - DistributionPointFetcher.getBooleanProperty - ("com.sun.security.enableAIAcaIssuers", false); + final static boolean USE_AIA = AccessController.doPrivileged + (new GetBooleanAction("com.sun.security.enableAIAcaIssuers")); /** * Initialize the builder with the input parameters. diff --git a/src/share/classes/sun/security/provider/certpath/CertId.java b/src/share/classes/sun/security/provider/certpath/CertId.java index 1ee63949964452c1217897df50d2d8beaed8b2f9..20e9aa2a789a1416b5e76219250557388d5c0924 100644 --- a/src/share/classes/sun/security/provider/certpath/CertId.java +++ b/src/share/classes/sun/security/provider/certpath/CertId.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,11 @@ package sun.security.provider.certpath; -import java.io.*; +import java.io.IOException; import java.math.BigInteger; import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; import java.util.Arrays; import sun.misc.HexDumpEncoder; import sun.security.x509.*; @@ -54,21 +56,28 @@ import sun.security.util.*; public class CertId { private static final boolean debug = false; - private AlgorithmId hashAlgId; - private byte[] issuerNameHash; - private byte[] issuerKeyHash; - private SerialNumber certSerialNumber; + private static final AlgorithmId SHA1_ALGID + = new AlgorithmId(AlgorithmId.SHA_oid); + private final AlgorithmId hashAlgId; + private final byte[] issuerNameHash; + private final byte[] issuerKeyHash; + private final SerialNumber certSerialNumber; private int myhash = -1; // hashcode for this CertId /** * Creates a CertId. The hash algorithm used is SHA-1. */ - public CertId(X509CertImpl issuerCert, SerialNumber serialNumber) - throws Exception { + public CertId(X509Certificate issuerCert, SerialNumber serialNumber) + throws IOException { // compute issuerNameHash - MessageDigest md = MessageDigest.getInstance("SHA1"); - hashAlgId = AlgorithmId.get("SHA1"); + MessageDigest md = null; + try { + md = MessageDigest.getInstance("SHA1"); + } catch (NoSuchAlgorithmException nsae) { + throw new IOException("Unable to create CertId", nsae); + } + hashAlgId = SHA1_ALGID; md.update(issuerCert.getSubjectX500Principal().getEncoded()); issuerNameHash = md.digest(); @@ -90,6 +99,7 @@ public class CertId { encoder.encode(issuerNameHash)); System.out.println("issuerKeyHash is " + encoder.encode(issuerKeyHash)); + System.out.println("SerialNumber is " + serialNumber.getNumber()); } } @@ -97,7 +107,6 @@ public class CertId { * Creates a CertId from its ASN.1 DER encoding. */ public CertId(DerInputStream derIn) throws IOException { - hashAlgId = AlgorithmId.parse(derIn.getDerValue()); issuerNameHash = derIn.getOctetString(); issuerKeyHash = derIn.getOctetString(); @@ -157,7 +166,7 @@ public class CertId { * * @return the hashcode value. */ - public int hashCode() { + @Override public int hashCode() { if (myhash == -1) { myhash = hashAlgId.hashCode(); for (int i = 0; i < issuerNameHash.length; i++) { @@ -180,8 +189,7 @@ public class CertId { * @param other the object to test for equality with this object. * @return true if the objects are considered equal, false otherwise. */ - public boolean equals(Object other) { - + @Override public boolean equals(Object other) { if (this == other) { return true; } @@ -203,7 +211,7 @@ public class CertId { /** * Create a string representation of the CertId. */ - public String toString() { + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("CertId \n"); sb.append("Algorithm: " + hashAlgId.toString() +"\n"); diff --git a/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java b/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java index b462dd5ba0870486ad0e3fe1554e82b63175a3bc..18845113edb39d7422d9b0ada49ff1d89e7b9834 100644 --- a/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java +++ b/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java @@ -80,6 +80,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker { { false, false, false, false, false, false, true }; private static final boolean[] ALL_REASONS = {true, true, true, true, true, true, true, true, true}; + private boolean mOnlyEECert = false; // Maximum clock skew in milliseconds (15 minutes) allowed when checking // validity of CRLs @@ -114,6 +115,12 @@ class CrlRevocationChecker extends PKIXCertPathChecker { CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params, Collection certs) throws CertPathValidatorException { + this(anchor, params, certs, false); + } + + CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params, + Collection certs, boolean onlyEECert) + throws CertPathValidatorException { mAnchor = anchor; mParams = params; mStores = new ArrayList(params.getCertStores()); @@ -133,6 +140,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker { } Date testDate = params.getDate(); mCurrentTime = (testDate != null ? testDate : new Date()); + mOnlyEECert = onlyEECert; init(false); } @@ -264,6 +272,13 @@ class CrlRevocationChecker extends PKIXCertPathChecker { " ---checking " + msg + "..."); } + if (mOnlyEECert && currCert.getBasicConstraints() != -1) { + if (debug != null) { + debug.println("Skipping revocation check, not end entity cert"); + } + return; + } + // reject circular dependencies - RFC 3280 is not explicit on how // to handle this, so we feel it is safest to reject them until // the issue is resolved in the PKIX WG. diff --git a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java index 39ee1f1dad6395171e9e8bceb7583e56b98e7543..dea521a4a19c21215b05821870a29712374ae15d 100644 --- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java +++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java @@ -32,7 +32,7 @@ import java.security.*; import java.security.cert.*; import javax.security.auth.x500.X500Principal; -import sun.security.action.GetPropertyAction; +import sun.security.action.GetBooleanAction; import sun.security.util.Debug; import sun.security.util.DerOutputStream; import sun.security.x509.*; @@ -62,28 +62,8 @@ class DistributionPointFetcher { * extension shall be enabled. Currently disabled by default for * compatibility and legal reasons. */ - private final static boolean USE_CRLDP = - getBooleanProperty("com.sun.security.enableCRLDP", false); - - /** - * Return the value of the boolean System property propName. - */ - public static boolean getBooleanProperty(String propName, - boolean defaultValue) { - // if set, require value of either true or false - String b = AccessController.doPrivileged( - new GetPropertyAction(propName)); - if (b == null) { - return defaultValue; - } else if (b.equalsIgnoreCase("false")) { - return false; - } else if (b.equalsIgnoreCase("true")) { - return true; - } else { - throw new RuntimeException("Value of " + propName - + " must either be 'true' or 'false'"); - } - } + private final static boolean USE_CRLDP = AccessController.doPrivileged + (new GetBooleanAction("com.sun.security.enableCRLDP")); // singleton instance private static final DistributionPointFetcher INSTANCE = diff --git a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java index 393a7663c91a23ab7b58aae5ff3cb52d3134b4ff..41fe50d66b706466b089077703facb7a96cbe7f7 100644 --- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java +++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java @@ -82,6 +82,7 @@ class ForwardBuilder extends Builder { TrustAnchor trustAnchor; private Comparator comparator; private boolean searchAllCertStores = true; + private boolean onlyEECert = false; /** * Initialize the builder with the input parameters. @@ -89,7 +90,8 @@ class ForwardBuilder extends Builder { * @param params the parameter set used to build a certification path */ ForwardBuilder(PKIXBuilderParameters buildParams, - X500Principal targetSubjectDN, boolean searchAllCertStores) + X500Principal targetSubjectDN, boolean searchAllCertStores, + boolean onlyEECert) { super(buildParams, targetSubjectDN); @@ -108,6 +110,7 @@ class ForwardBuilder extends Builder { } comparator = new PKIXCertComparator(trustedSubjectDNs); this.searchAllCertStores = searchAllCertStores; + this.onlyEECert = onlyEECert; } /** @@ -875,8 +878,8 @@ class ForwardBuilder extends Builder { /* Check revocation if it is enabled */ if (buildParams.isRevocationEnabled()) { try { - CrlRevocationChecker crlChecker = - new CrlRevocationChecker(anchor, buildParams); + CrlRevocationChecker crlChecker = new CrlRevocationChecker + (anchor, buildParams, null, onlyEECert); crlChecker.check(cert, anchor.getCAPublicKey(), true); } catch (CertPathValidatorException cpve) { if (debug != null) { diff --git a/src/share/classes/sun/security/provider/certpath/OCSP.java b/src/share/classes/sun/security/provider/certpath/OCSP.java new file mode 100644 index 0000000000000000000000000000000000000000..2665de6d6801c05cd8231b9c4090d5ffa69046af --- /dev/null +++ b/src/share/classes/sun/security/provider/certpath/OCSP.java @@ -0,0 +1,329 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +package sun.security.provider.certpath; + +import java.io.InputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.URI; +import java.net.URL; +import java.net.HttpURLConnection; +import java.security.cert.CertificateException; +import java.security.cert.CertPathValidatorException; +import java.security.cert.CRLReason; +import java.security.cert.Extension; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import static sun.security.provider.certpath.OCSPResponse.*; +import sun.security.util.Debug; +import sun.security.x509.AccessDescription; +import sun.security.x509.AuthorityInfoAccessExtension; +import sun.security.x509.GeneralName; +import sun.security.x509.GeneralNameInterface; +import sun.security.x509.URIName; +import sun.security.x509.X509CertImpl; + +/** + * This is a class that checks the revocation status of a certificate(s) using + * OCSP. It is not a PKIXCertPathChecker and therefore can be used outside of + * the CertPathValidator framework. It is useful when you want to + * just check the revocation status of a certificate, and you don't want to + * incur the overhead of validating all of the certificates in the + * associated certificate chain. + * + * @author Sean Mullan + */ +public final class OCSP { + + private static final Debug debug = Debug.getInstance("certpath"); + + private OCSP() {} + + /** + * Obtains the revocation status of a certificate using OCSP using the most + * common defaults. The OCSP responder URI is retrieved from the + * certificate's AIA extension. The OCSP responder certificate is assumed + * to be the issuer's certificate (or issued by the issuer CA). + * + * @param cert the certificate to be checked + * @param issuerCert the issuer certificate + * @return the RevocationStatus + * @throws IOException if there is an exception connecting to or + * communicating with the OCSP responder + * @throws CertPathValidatorException if an exception occurs while + * encoding the OCSP Request or validating the OCSP Response + */ + public static RevocationStatus check(X509Certificate cert, + X509Certificate issuerCert) + throws IOException, CertPathValidatorException { + CertId certId = null; + URI responderURI = null; + try { + X509CertImpl certImpl = X509CertImpl.toImpl(cert); + responderURI = getResponderURI(certImpl); + if (responderURI == null) { + throw new CertPathValidatorException + ("No OCSP Responder URI in certificate"); + } + certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); + } catch (CertificateException ce) { + throw new CertPathValidatorException + ("Exception while encoding OCSPRequest", ce); + } catch (IOException ioe) { + throw new CertPathValidatorException + ("Exception while encoding OCSPRequest", ioe); + } + OCSPResponse ocspResponse = check(Collections.singletonList(certId), + responderURI, issuerCert, null); + return (RevocationStatus) ocspResponse.getSingleResponse(certId); + } + + /** + * Obtains the revocation status of a certificate using OCSP. + * + * @param cert the certificate to be checked + * @param issuerCert the issuer certificate + * @param responderURI the URI of the OCSP responder + * @param responderCert the OCSP responder's certificate + * @param date the time the validity of the OCSP responder's certificate + * should be checked against. If null, the current time is used. + * @return the RevocationStatus + * @throws IOException if there is an exception connecting to or + * communicating with the OCSP responder + * @throws CertPathValidatorException if an exception occurs while + * encoding the OCSP Request or validating the OCSP Response + */ + public static RevocationStatus check(X509Certificate cert, + X509Certificate issuerCert, URI responderURI, X509Certificate + responderCert, Date date) + throws IOException, CertPathValidatorException { + CertId certId = null; + try { + X509CertImpl certImpl = X509CertImpl.toImpl(cert); + certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); + } catch (CertificateException ce) { + throw new CertPathValidatorException + ("Exception while encoding OCSPRequest", ce); + } catch (IOException ioe) { + throw new CertPathValidatorException + ("Exception while encoding OCSPRequest", ioe); + } + OCSPResponse ocspResponse = check(Collections.singletonList(certId), + responderURI, responderCert, date); + return (RevocationStatus) ocspResponse.getSingleResponse(certId); + } + + /** + * Checks the revocation status of a list of certificates using OCSP. + * + * @param certs the CertIds to be checked + * @param responderURI the URI of the OCSP responder + * @param responderCert the OCSP responder's certificate + * @param date the time the validity of the OCSP responder's certificate + * should be checked against. If null, the current time is used. + * @return the OCSPResponse + * @throws IOException if there is an exception connecting to or + * communicating with the OCSP responder + * @throws CertPathValidatorException if an exception occurs while + * encoding the OCSP Request or validating the OCSP Response + */ + static OCSPResponse check(List certIds, URI responderURI, + X509Certificate responderCert, Date date) + throws IOException, CertPathValidatorException { + + byte[] bytes = null; + try { + OCSPRequest request = new OCSPRequest(certIds); + bytes = request.encodeBytes(); + } catch (IOException ioe) { + throw new CertPathValidatorException + ("Exception while encoding OCSPRequest", ioe); + } + + InputStream in = null; + OutputStream out = null; + byte[] response = null; + try { + URL url = responderURI.toURL(); + if (debug != null) { + debug.println("connecting to OCSP service at: " + url); + } + HttpURLConnection con = (HttpURLConnection)url.openConnection(); + con.setDoOutput(true); + con.setDoInput(true); + con.setRequestMethod("POST"); + con.setRequestProperty + ("Content-type", "application/ocsp-request"); + con.setRequestProperty + ("Content-length", String.valueOf(bytes.length)); + out = con.getOutputStream(); + out.write(bytes); + out.flush(); + // Check the response + if (debug != null && + con.getResponseCode() != HttpURLConnection.HTTP_OK) { + debug.println("Received HTTP error: " + con.getResponseCode() + + " - " + con.getResponseMessage()); + } + in = con.getInputStream(); + int contentLength = con.getContentLength(); + if (contentLength == -1) { + contentLength = Integer.MAX_VALUE; + } + response = new byte[contentLength > 2048 ? 2048 : contentLength]; + int total = 0; + while (total < contentLength) { + int count = in.read(response, total, response.length - total); + if (count < 0) + break; + + total += count; + if (total >= response.length && total < contentLength) { + response = Arrays.copyOf(response, total * 2); + } + } + response = Arrays.copyOf(response, total); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException ioe) { + throw ioe; + } + } + if (out != null) { + try { + out.close(); + } catch (IOException ioe) { + throw ioe; + } + } + } + + OCSPResponse ocspResponse = null; + try { + ocspResponse = new OCSPResponse(response, date, responderCert); + } catch (IOException ioe) { + // response decoding exception + throw new CertPathValidatorException(ioe); + } + if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) { + throw new CertPathValidatorException + ("OCSP response error: " + ocspResponse.getResponseStatus()); + } + + // Check that the response includes a response for all of the + // certs that were supplied in the request + for (CertId certId : certIds) { + SingleResponse sr = ocspResponse.getSingleResponse(certId); + if (sr == null) { + if (debug != null) { + debug.println("No response found for CertId: " + certId); + } + throw new CertPathValidatorException( + "OCSP response does not include a response for a " + + "certificate supplied in the OCSP request"); + } + if (debug != null) { + debug.println("Status of certificate (with serial number " + + certId.getSerialNumber() + ") is: " + sr.getCertStatus()); + } + } + return ocspResponse; + } + + /** + * Returns the URI of the OCSP Responder as specified in the + * certificate's Authority Information Access extension, or null if + * not specified. + * + * @param cert the certificate + * @return the URI of the OCSP Responder, or null if not specified + */ + public static URI getResponderURI(X509Certificate cert) { + try { + return getResponderURI(X509CertImpl.toImpl(cert)); + } catch (CertificateException ce) { + // treat this case as if the cert had no extension + return null; + } + } + + static URI getResponderURI(X509CertImpl certImpl) { + + // Examine the certificate's AuthorityInfoAccess extension + AuthorityInfoAccessExtension aia = + certImpl.getAuthorityInfoAccessExtension(); + if (aia == null) { + return null; + } + + List descriptions = aia.getAccessDescriptions(); + for (AccessDescription description : descriptions) { + if (description.getAccessMethod().equals( + AccessDescription.Ad_OCSP_Id)) { + + GeneralName generalName = description.getAccessLocation(); + if (generalName.getType() == GeneralNameInterface.NAME_URI) { + URIName uri = (URIName) generalName.getName(); + return uri.getURI(); + } + } + } + return null; + } + + /** + * The Revocation Status of a certificate. + */ + public static interface RevocationStatus { + public enum CertStatus { GOOD, REVOKED, UNKNOWN }; + + /** + * Returns the revocation status. + */ + CertStatus getCertStatus(); + /** + * Returns the time when the certificate was revoked, or null + * if it has not been revoked. + */ + Date getRevocationTime(); + /** + * Returns the reason the certificate was revoked, or null if it + * has not been revoked. + */ + CRLReason getRevocationReason(); + + /** + * Returns a Map of additional extensions. + */ + Map getSingleExtensions(); + } +} diff --git a/src/share/classes/sun/security/provider/certpath/OCSPChecker.java b/src/share/classes/sun/security/provider/certpath/OCSPChecker.java index 04e0649d8ffc0a5188cca9dd0baf2d6410177f17..6f72c7ec185dc9e2fe5c80889dd75ff52fe52b8e 100644 --- a/src/share/classes/sun/security/provider/certpath/OCSPChecker.java +++ b/src/share/classes/sun/security/provider/certpath/OCSPChecker.java @@ -25,19 +25,20 @@ package sun.security.provider.certpath; -import java.io.*; +import java.io.IOException; import java.math.BigInteger; import java.util.*; import java.security.AccessController; -import java.security.Principal; import java.security.PrivilegedAction; import java.security.Security; import java.security.cert.*; import java.security.cert.CertPathValidatorException.BasicReason; -import java.net.*; +import java.net.URI; +import java.net.URISyntaxException; import javax.security.auth.x500.X500Principal; -import sun.security.util.*; +import static sun.security.provider.certpath.OCSP.*; +import sun.security.util.Debug; import sun.security.x509.*; /** @@ -50,27 +51,18 @@ import sun.security.x509.*; */ class OCSPChecker extends PKIXCertPathChecker { - public static final String OCSP_ENABLE_PROP = "ocsp.enable"; - public static final String OCSP_URL_PROP = "ocsp.responderURL"; - public static final String OCSP_CERT_SUBJECT_PROP = + static final String OCSP_ENABLE_PROP = "ocsp.enable"; + static final String OCSP_URL_PROP = "ocsp.responderURL"; + static final String OCSP_CERT_SUBJECT_PROP = "ocsp.responderCertSubjectName"; - public static final String OCSP_CERT_ISSUER_PROP = - "ocsp.responderCertIssuerName"; - public static final String OCSP_CERT_NUMBER_PROP = + static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName"; + static final String OCSP_CERT_NUMBER_PROP = "ocsp.responderCertSerialNumber"; private static final String HEX_DIGITS = "0123456789ABCDEFabcdef"; private static final Debug DEBUG = Debug.getInstance("certpath"); private static final boolean dump = false; - // Supported extensions - private static final int OCSP_NONCE_DATA[] = - { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2 }; - private static final ObjectIdentifier OCSP_NONCE_OID; - static { - OCSP_NONCE_OID = ObjectIdentifier.newInternal(OCSP_NONCE_DATA); - } - private int remainingCerts; private X509Certificate[] certs; @@ -79,19 +71,26 @@ class OCSPChecker extends PKIXCertPathChecker { private PKIXParameters pkixParams; + private boolean onlyEECert = false; + /** * Default Constructor * * @param certPath the X509 certification path * @param pkixParams the input PKIX parameter set - * @exception CertPathValidatorException Exception thrown if cert path - * does not validate. + * @throws CertPathValidatorException if OCSPChecker can not be created */ OCSPChecker(CertPath certPath, PKIXParameters pkixParams) throws CertPathValidatorException { + this(certPath, pkixParams, false); + } + + OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert) + throws CertPathValidatorException { this.cp = certPath; this.pkixParams = pkixParams; + this.onlyEECert = onlyEECert; List tmp = cp.getCertificates(); certs = tmp.toArray(new X509Certificate[tmp.size()]); init(false); @@ -101,6 +100,7 @@ class OCSPChecker extends PKIXCertPathChecker { * Initializes the internal state of the checker from parameters * specified in the constructor */ + @Override public void init(boolean forward) throws CertPathValidatorException { if (!forward) { remainingCerts = certs.length + 1; @@ -110,11 +110,11 @@ class OCSPChecker extends PKIXCertPathChecker { } } - public boolean isForwardCheckingSupported() { + @Override public boolean isForwardCheckingSupported() { return false; } - public Set getSupportedExtensions() { + @Override public Set getSupportedExtensions() { return Collections.emptySet(); } @@ -127,300 +127,233 @@ class OCSPChecker extends PKIXCertPathChecker { * @exception CertPathValidatorException Exception is thrown if the * certificate has been revoked. */ + @Override public void check(Certificate cert, Collection unresolvedCritExts) throws CertPathValidatorException { - InputStream in = null; - OutputStream out = null; - // Decrement the certificate counter remainingCerts--; + X509CertImpl currCertImpl = null; try { - X509Certificate responderCert = null; - boolean seekResponderCert = false; - X500Principal responderSubjectName = null; - X500Principal responderIssuerName = null; - BigInteger responderSerialNumber = null; - - boolean seekIssuerCert = true; - X509CertImpl issuerCertImpl = null; - X509CertImpl currCertImpl = - X509CertImpl.toImpl((X509Certificate)cert); - - /* - * OCSP security property values, in the following order: - * 1. ocsp.responderURL - * 2. ocsp.responderCertSubjectName - * 3. ocsp.responderCertIssuerName - * 4. ocsp.responderCertSerialNumber - */ - String[] properties = getOCSPProperties(); - - // Check whether OCSP is feasible before seeking cert information - URL url = getOCSPServerURL(currCertImpl, properties); - - // When responder's subject name is set then the issuer/serial - // properties are ignored - if (properties[1] != null) { - responderSubjectName = new X500Principal(properties[1]); - - } else if (properties[2] != null && properties[3] != null) { - responderIssuerName = new X500Principal(properties[2]); - // remove colon or space separators - String value = stripOutSeparators(properties[3]); - responderSerialNumber = new BigInteger(value, 16); - - } else if (properties[2] != null || properties[3] != null) { - throw new CertPathValidatorException( - "Must specify both ocsp.responderCertIssuerName and " + - "ocsp.responderCertSerialNumber properties"); - } - - // If the OCSP responder cert properties are set then the - // identified cert must be located in the trust anchors or - // in the cert stores. - if (responderSubjectName != null || responderIssuerName != null) { - seekResponderCert = true; - } + currCertImpl = X509CertImpl.toImpl((X509Certificate)cert); + } catch (CertificateException ce) { + throw new CertPathValidatorException(ce); + } - // Set the issuer certificate to the next cert in the chain - // (unless we're processing the final cert). - if (remainingCerts < certs.length) { - issuerCertImpl = X509CertImpl.toImpl(certs[remainingCerts]); - seekIssuerCert = false; // done - - // By default, the OCSP responder's cert is the same as the - // issuer of the cert being validated. - if (! seekResponderCert) { - responderCert = certs[remainingCerts]; - if (DEBUG != null) { - DEBUG.println("Responder's certificate is the same " + - "as the issuer of the certificate being validated"); - } - } + if (onlyEECert && currCertImpl.getBasicConstraints() != -1) { + if (DEBUG != null) { + DEBUG.println("Skipping revocation check, not end entity cert"); } + return; + } - // Check anchor certs for: - // - the issuer cert (of the cert being validated) - // - the OCSP responder's cert - if (seekIssuerCert || seekResponderCert) { + /* + * OCSP security property values, in the following order: + * 1. ocsp.responderURL + * 2. ocsp.responderCertSubjectName + * 3. ocsp.responderCertIssuerName + * 4. ocsp.responderCertSerialNumber + */ + // should cache these properties to avoid calling every time? + String[] properties = getOCSPProperties(); + + // Check whether OCSP is feasible before seeking cert information + URI uri = getOCSPServerURI(currCertImpl, properties[0]); + + // When responder's subject name is set then the issuer/serial + // properties are ignored + X500Principal responderSubjectName = null; + X500Principal responderIssuerName = null; + BigInteger responderSerialNumber = null; + if (properties[1] != null) { + responderSubjectName = new X500Principal(properties[1]); + } else if (properties[2] != null && properties[3] != null) { + responderIssuerName = new X500Principal(properties[2]); + // remove colon or space separators + String value = stripOutSeparators(properties[3]); + responderSerialNumber = new BigInteger(value, 16); + } else if (properties[2] != null || properties[3] != null) { + throw new CertPathValidatorException( + "Must specify both ocsp.responderCertIssuerName and " + + "ocsp.responderCertSerialNumber properties"); + } - if (DEBUG != null && seekResponderCert) { - DEBUG.println("Searching trust anchors for responder's " + - "certificate"); - } + // If the OCSP responder cert properties are set then the + // identified cert must be located in the trust anchors or + // in the cert stores. + boolean seekResponderCert = false; + if (responderSubjectName != null || responderIssuerName != null) { + seekResponderCert = true; + } - // Extract the anchor certs - Iterator anchors = pkixParams.getTrustAnchors().iterator(); - if (! anchors.hasNext()) { - throw new CertPathValidatorException( - "Must specify at least one trust anchor"); + // Set the issuer certificate to the next cert in the chain + // (unless we're processing the final cert). + X509Certificate issuerCert = null; + boolean seekIssuerCert = true; + X509Certificate responderCert = null; + if (remainingCerts < certs.length) { + issuerCert = certs[remainingCerts]; + seekIssuerCert = false; // done + + // By default, the OCSP responder's cert is the same as the + // issuer of the cert being validated. + if (!seekResponderCert) { + responderCert = issuerCert; + if (DEBUG != null) { + DEBUG.println("Responder's certificate is the same " + + "as the issuer of the certificate being validated"); } + } + } - X500Principal certIssuerName = - currCertImpl.getIssuerX500Principal(); - while (anchors.hasNext() && - (seekIssuerCert || seekResponderCert)) { + // Check anchor certs for: + // - the issuer cert (of the cert being validated) + // - the OCSP responder's cert + if (seekIssuerCert || seekResponderCert) { - TrustAnchor anchor = (TrustAnchor)anchors.next(); - X509Certificate anchorCert = anchor.getTrustedCert(); - X500Principal anchorSubjectName = - anchorCert.getSubjectX500Principal(); + if (DEBUG != null && seekResponderCert) { + DEBUG.println("Searching trust anchors for responder's " + + "certificate"); + } - if (dump) { - System.out.println("Issuer DN is " + certIssuerName); - System.out.println("Subject DN is " + - anchorSubjectName); - } + // Extract the anchor certs + Iterator anchors + = pkixParams.getTrustAnchors().iterator(); + if (!anchors.hasNext()) { + throw new CertPathValidatorException( + "Must specify at least one trust anchor"); + } - // Check if anchor cert is the issuer cert - if (seekIssuerCert && - certIssuerName.equals(anchorSubjectName)) { + X500Principal certIssuerName = + currCertImpl.getIssuerX500Principal(); + while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) { - issuerCertImpl = X509CertImpl.toImpl(anchorCert); - seekIssuerCert = false; // done + TrustAnchor anchor = anchors.next(); + X509Certificate anchorCert = anchor.getTrustedCert(); + X500Principal anchorSubjectName = + anchorCert.getSubjectX500Principal(); - // By default, the OCSP responder's cert is the same as - // the issuer of the cert being validated. - if (! seekResponderCert && responderCert == null) { - responderCert = anchorCert; - if (DEBUG != null) { - DEBUG.println("Responder's certificate is the" + - " same as the issuer of the certificate " + - "being validated"); - } - } - } + if (dump) { + System.out.println("Issuer DN is " + certIssuerName); + System.out.println("Subject DN is " + anchorSubjectName); + } - // Check if anchor cert is the responder cert - if (seekResponderCert) { - // Satisfy the responder subject name property only, or - // satisfy the responder issuer name and serial number - // properties only - if ((responderSubjectName != null && - responderSubjectName.equals(anchorSubjectName)) || - (responderIssuerName != null && - responderSerialNumber != null && - responderIssuerName.equals( - anchorCert.getIssuerX500Principal()) && - responderSerialNumber.equals( - anchorCert.getSerialNumber()))) { - - responderCert = anchorCert; - seekResponderCert = false; // done + // Check if anchor cert is the issuer cert + if (seekIssuerCert && + certIssuerName.equals(anchorSubjectName)) { + + issuerCert = anchorCert; + seekIssuerCert = false; // done + + // By default, the OCSP responder's cert is the same as + // the issuer of the cert being validated. + if (!seekResponderCert && responderCert == null) { + responderCert = anchorCert; + if (DEBUG != null) { + DEBUG.println("Responder's certificate is the" + + " same as the issuer of the certificate " + + "being validated"); } } } - if (issuerCertImpl == null) { - throw new CertPathValidatorException( - "No trusted certificate for " + - currCertImpl.getIssuerDN()); - } - // Check cert stores if responder cert has not yet been found + // Check if anchor cert is the responder cert if (seekResponderCert) { - if (DEBUG != null) { - DEBUG.println("Searching cert stores for responder's " + - "certificate"); - } - X509CertSelector filter = null; - if (responderSubjectName != null) { - filter = new X509CertSelector(); - filter.setSubject(responderSubjectName.getName()); - } else if (responderIssuerName != null && - responderSerialNumber != null) { - filter = new X509CertSelector(); - filter.setIssuer(responderIssuerName.getName()); - filter.setSerialNumber(responderSerialNumber); - } - if (filter != null) { - List certStores = pkixParams.getCertStores(); - for (CertStore certStore : certStores) { - Iterator i = - certStore.getCertificates(filter).iterator(); - if (i.hasNext()) { - responderCert = (X509Certificate) i.next(); - seekResponderCert = false; // done - break; - } - } + // Satisfy the responder subject name property only, or + // satisfy the responder issuer name and serial number + // properties only + if ((responderSubjectName != null && + responderSubjectName.equals(anchorSubjectName)) || + (responderIssuerName != null && + responderSerialNumber != null && + responderIssuerName.equals( + anchorCert.getIssuerX500Principal()) && + responderSerialNumber.equals( + anchorCert.getSerialNumber()))) { + + responderCert = anchorCert; + seekResponderCert = false; // done } } } - - // Could not find the certificate identified in the OCSP properties - if (seekResponderCert) { + if (issuerCert == null) { throw new CertPathValidatorException( - "Cannot find the responder's certificate " + - "(set using the OCSP security properties)."); + "No trusted certificate for " + currCertImpl.getIssuerDN()); } - // Construct an OCSP Request - OCSPRequest ocspRequest = - new OCSPRequest(currCertImpl, issuerCertImpl); - - // Use the URL to the OCSP service that was created earlier - HttpURLConnection con = (HttpURLConnection)url.openConnection(); - if (DEBUG != null) { - DEBUG.println("connecting to OCSP service at: " + url); - } - - // Indicate that both input and output will be performed, - // that the method is POST, and that the content length is - // the length of the byte array - - con.setDoOutput(true); - con.setDoInput(true); - con.setRequestMethod("POST"); - con.setRequestProperty("Content-type", "application/ocsp-request"); - byte[] bytes = ocspRequest.encodeBytes(); - CertId certId = ocspRequest.getCertId(); - - con.setRequestProperty("Content-length", - String.valueOf(bytes.length)); - out = con.getOutputStream(); - out.write(bytes); - out.flush(); - - // Check the response - if (DEBUG != null && - con.getResponseCode() != HttpURLConnection.HTTP_OK) { - DEBUG.println("Received HTTP error: " + con.getResponseCode() + - " - " + con.getResponseMessage()); - } - in = con.getInputStream(); - - byte[] response = null; - int total = 0; - int contentLength = con.getContentLength(); - if (contentLength != -1) { - response = new byte[contentLength]; - } else { - response = new byte[2048]; - contentLength = Integer.MAX_VALUE; - } - - while (total < contentLength) { - int count = in.read(response, total, response.length - total); - if (count < 0) - break; - - total += count; - if (total >= response.length && total < contentLength) { - response = Arrays.copyOf(response, total * 2); + // Check cert stores if responder cert has not yet been found + if (seekResponderCert) { + if (DEBUG != null) { + DEBUG.println("Searching cert stores for responder's " + + "certificate"); + } + X509CertSelector filter = null; + if (responderSubjectName != null) { + filter = new X509CertSelector(); + filter.setSubject(responderSubjectName); + } else if (responderIssuerName != null && + responderSerialNumber != null) { + filter = new X509CertSelector(); + filter.setIssuer(responderIssuerName); + filter.setSerialNumber(responderSerialNumber); + } + if (filter != null) { + List certStores = pkixParams.getCertStores(); + for (CertStore certStore : certStores) { + Iterator i = null; + try { + i = certStore.getCertificates(filter).iterator(); + } catch (CertStoreException cse) { + // ignore and try next certStore + if (DEBUG != null) { + DEBUG.println("CertStore exception:" + cse); + } + continue; + } + if (i.hasNext()) { + responderCert = (X509Certificate) i.next(); + seekResponderCert = false; // done + break; + } + } } } - response = Arrays.copyOf(response, total); - - OCSPResponse ocspResponse = new OCSPResponse(response, pkixParams, - responderCert); - // Check that response applies to the cert that was supplied - if (! certId.equals(ocspResponse.getCertId())) { - throw new CertPathValidatorException( - "Certificate in the OCSP response does not match the " + - "certificate supplied in the OCSP request."); - } - SerialNumber serialNumber = currCertImpl.getSerialNumberObject(); - int certOCSPStatus = ocspResponse.getCertStatus(serialNumber); + } - if (DEBUG != null) { - DEBUG.println("Status of certificate (with serial number " + - serialNumber.getNumber() + ") is: " + - OCSPResponse.certStatusToText(certOCSPStatus)); - } + // Could not find the certificate identified in the OCSP properties + if (seekResponderCert) { + throw new CertPathValidatorException( + "Cannot find the responder's certificate " + + "(set using the OCSP security properties)."); + } - if (certOCSPStatus == OCSPResponse.CERT_STATUS_REVOKED) { - Throwable t = new CertificateRevokedException( - ocspResponse.getRevocationTime(), - ocspResponse.getRevocationReason(), - responderCert.getSubjectX500Principal(), - ocspResponse.getSingleExtensions()); - throw new CertPathValidatorException(t.getMessage(), t, - null, -1, BasicReason.REVOKED); + CertId certId = null; + OCSPResponse response = null; + try { + certId = new CertId + (issuerCert, currCertImpl.getSerialNumberObject()); + response = OCSP.check(Collections.singletonList(certId), uri, + responderCert, pkixParams.getDate()); + } catch (IOException ioe) { + // should allow this to pass if network failures are acceptable + throw new CertPathValidatorException + ("Unable to send OCSP request", ioe); + } - } else if (certOCSPStatus == OCSPResponse.CERT_STATUS_UNKNOWN) { - throw new CertPathValidatorException( - "Certificate's revocation status is unknown", null, cp, - remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS); - } - } catch (Exception e) { - throw new CertPathValidatorException(e); - } finally { - if (in != null) { - try { - in.close(); - } catch (IOException ioe) { - throw new CertPathValidatorException(ioe); - } - } - if (out != null) { - try { - out.close(); - } catch (IOException ioe) { - throw new CertPathValidatorException(ioe); - } - } + RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId); + RevocationStatus.CertStatus certStatus = rs.getCertStatus(); + if (certStatus == RevocationStatus.CertStatus.REVOKED) { + Throwable t = new CertificateRevokedException( + rs.getRevocationTime(), rs.getRevocationReason(), + responderCert.getSubjectX500Principal(), + rs.getSingleExtensions()); + throw new CertPathValidatorException(t.getMessage(), t, + null, -1, BasicReason.REVOKED); + } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) { + throw new CertPathValidatorException( + "Certificate's revocation status is unknown", null, cp, + remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS); } } @@ -431,20 +364,18 @@ class OCSPChecker extends PKIXCertPathChecker { * 3. ocsp.responderCertIssuerName * 4. ocsp.responderCertSerialNumber */ - private static URL getOCSPServerURL(X509CertImpl currCertImpl, - String[] properties) - throws CertificateParsingException, CertPathValidatorException { - - if (properties[0] != null) { - try { - return new URL(properties[0]); - } catch (java.net.MalformedURLException e) { + private static URI getOCSPServerURI(X509CertImpl currCertImpl, + String responderURL) throws CertPathValidatorException { + + if (responderURL != null) { + try { + return new URI(responderURL); + } catch (URISyntaxException e) { throw new CertPathValidatorException(e); - } + } } // Examine the certificate's AuthorityInfoAccess extension - AuthorityInfoAccessExtension aia = currCertImpl.getAuthorityInfoAccessExtension(); if (aia == null) { @@ -459,13 +390,8 @@ class OCSPChecker extends PKIXCertPathChecker { GeneralName generalName = description.getAccessLocation(); if (generalName.getType() == GeneralNameInterface.NAME_URI) { - try { - URIName uri = (URIName) generalName.getName(); - return (new URL(uri.getName())); - - } catch (java.net.MalformedURLException e) { - throw new CertPathValidatorException(e); - } + URIName uri = (URIName) generalName.getName(); + return uri.getURI(); } } } diff --git a/src/share/classes/sun/security/provider/certpath/OCSPRequest.java b/src/share/classes/sun/security/provider/certpath/OCSPRequest.java index b7350b55e9bc194541b312dccc0ae83f2aa15a79..393ac6f0e73d6bd85177d6e4196106a80a031d01 100644 --- a/src/share/classes/sun/security/provider/certpath/OCSPRequest.java +++ b/src/share/classes/sun/security/provider/certpath/OCSPRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,9 @@ package sun.security.provider.certpath; import java.io.IOException; -import java.security.cert.CertPathValidatorException; +import java.util.Collections; +import java.util.List; import sun.misc.HexDumpEncoder; -import sun.security.x509.*; import sun.security.util.*; /** @@ -77,47 +77,33 @@ class OCSPRequest { private static final Debug debug = Debug.getInstance("certpath"); private static final boolean dump = false; - // Serial number of the certificates to be checked for revocation - private SerialNumber serialNumber; - - // Issuer's certificate (for computing certId hash values) - private X509CertImpl issuerCert; - - // CertId of the certificate to be checked - private CertId certId = null; + // List of request CertIds + private final List certIds; /* * Constructs an OCSPRequest. This constructor is used * to construct an unsigned OCSP Request for a single user cert. */ - // used by OCSPChecker - OCSPRequest(X509CertImpl userCert, X509CertImpl issuerCert) - throws CertPathValidatorException { + OCSPRequest(CertId certId) { + this.certIds = Collections.singletonList(certId); + } - if (issuerCert == null) { - throw new CertPathValidatorException("Null IssuerCertificate"); - } - this.issuerCert = issuerCert; - serialNumber = userCert.getSerialNumberObject(); + OCSPRequest(List certIds) { + this.certIds = certIds; } - // used by OCSPChecker byte[] encodeBytes() throws IOException { // encode tbsRequest DerOutputStream tmp = new DerOutputStream(); - DerOutputStream derSingleReqList = new DerOutputStream(); - SingleRequest singleRequest = null; - - try { - singleRequest = new SingleRequest(issuerCert, serialNumber); - } catch (Exception e) { - throw new IOException("Error encoding OCSP request"); + DerOutputStream requestsOut = new DerOutputStream(); + for (CertId certId : certIds) { + DerOutputStream certIdOut = new DerOutputStream(); + certId.encode(certIdOut); + requestsOut.write(DerValue.tag_Sequence, certIdOut); } - certId = singleRequest.getCertId(); - singleRequest.encode(derSingleReqList); - tmp.write(DerValue.tag_Sequence, derSingleReqList); + tmp.write(DerValue.tag_Sequence, requestsOut); // No extensions supported DerOutputStream tbsRequest = new DerOutputStream(); tbsRequest.write(DerValue.tag_Sequence, tmp); @@ -130,35 +116,14 @@ class OCSPRequest { if (dump) { HexDumpEncoder hexEnc = new HexDumpEncoder(); - System.out.println ("OCSPRequest bytes are... "); + System.out.println("OCSPRequest bytes are... "); System.out.println(hexEnc.encode(bytes)); } - return(bytes); - } - - // used by OCSPChecker - CertId getCertId() { - return certId; + return bytes; } - private static class SingleRequest { - private CertId certId; - - // No extensions are set - - private SingleRequest(X509CertImpl cert, SerialNumber serialNo) throws Exception { - certId = new CertId(cert, serialNo); - } - - private void encode(DerOutputStream out) throws IOException { - DerOutputStream tmp = new DerOutputStream(); - certId.encode(tmp); - out.write(DerValue.tag_Sequence, tmp); - } - - private CertId getCertId() { - return certId; - } + List getCertIds() { + return certIds; } } diff --git a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java index cdadc45f66c0c4da21bbcb465ff33c636bf2a276..e7b148fbc7cae379c925082ffd5e6fb24d77b206 100644 --- a/src/share/classes/sun/security/provider/certpath/OCSPResponse.java +++ b/src/share/classes/sun/security/provider/certpath/OCSPResponse.java @@ -28,17 +28,16 @@ package sun.security.provider.certpath; import java.io.*; import java.math.BigInteger; import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; import java.security.cert.CertPathValidatorException; import java.security.cert.CRLReason; import java.security.cert.X509Certificate; -import java.security.cert.PKIXParameters; -import javax.security.auth.x500.X500Principal; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.Iterator; import sun.misc.HexDumpEncoder; import sun.security.x509.*; import sun.security.util.*; @@ -113,32 +112,29 @@ import sun.security.util.*; * @author Ram Marti */ -class OCSPResponse { +public final class OCSPResponse { - // Certificate status CHOICE - public static final int CERT_STATUS_GOOD = 0; - public static final int CERT_STATUS_REVOKED = 1; - public static final int CERT_STATUS_UNKNOWN = 2; + public enum ResponseStatus { + SUCCESSFUL, // Response has valid confirmations + MALFORMED_REQUEST, // Illegal confirmation request + INTERNAL_ERROR, // Internal error in issuer + TRY_LATER, // Try again later + UNUSED, // is not used + SIG_REQUIRED, // Must sign the request + UNAUTHORIZED // Request unauthorized + }; + private static ResponseStatus[] rsvalues = ResponseStatus.values(); private static final Debug DEBUG = Debug.getInstance("certpath"); private static final boolean dump = false; - private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID; - private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID; - static { - ObjectIdentifier tmp1 = null; - ObjectIdentifier tmp2 = null; - try { - tmp1 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.1"); - tmp2 = new ObjectIdentifier("1.3.6.1.5.5.7.48.1.2"); - } catch (Exception e) { - // should not happen; log and exit - } - OCSP_BASIC_RESPONSE_OID = tmp1; - OCSP_NONCE_EXTENSION_OID = tmp2; - } + private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID = + ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1}); + private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID = + ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2}); - // OCSP response status code - private static final int OCSP_RESPONSE_OK = 0; + private static final int CERT_STATUS_GOOD = 0; + private static final int CERT_STATUS_REVOKED = 1; + private static final int CERT_STATUS_UNKNOWN = 2; // ResponderID CHOICE tags private static final int NAME_TAG = 1; @@ -147,7 +143,8 @@ class OCSPResponse { // Object identifier for the OCSPSigning key purpose private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9"; - private SingleResponse singleResponse; + private final ResponseStatus responseStatus; + private final Map singleResponseMap; // Maximum clock skew in milliseconds (15 minutes) allowed when checking // validity of OCSP responses @@ -159,289 +156,289 @@ class OCSPResponse { /* * Create an OCSP response from its ASN.1 DER encoding. */ - // used by OCSPChecker - OCSPResponse(byte[] bytes, PKIXParameters params, + OCSPResponse(byte[] bytes, Date dateCheckedAgainst, X509Certificate responderCert) throws IOException, CertPathValidatorException { - try { - int responseStatus; - ObjectIdentifier responseType; - int version; - CertificateIssuerName responderName = null; - Date producedAtDate; - AlgorithmId sigAlgId; - byte[] ocspNonce; - - // OCSPResponse - if (dump) { - HexDumpEncoder hexEnc = new HexDumpEncoder(); - System.out.println("OCSPResponse bytes are..."); - System.out.println(hexEnc.encode(bytes)); - } - DerValue der = new DerValue(bytes); - if (der.tag != DerValue.tag_Sequence) { - throw new IOException("Bad encoding in OCSP response: " + - "expected ASN.1 SEQUENCE tag."); - } - DerInputStream derIn = der.getData(); + // OCSPResponse + if (dump) { + HexDumpEncoder hexEnc = new HexDumpEncoder(); + System.out.println("OCSPResponse bytes are..."); + System.out.println(hexEnc.encode(bytes)); + } + DerValue der = new DerValue(bytes); + if (der.tag != DerValue.tag_Sequence) { + throw new IOException("Bad encoding in OCSP response: " + + "expected ASN.1 SEQUENCE tag."); + } + DerInputStream derIn = der.getData(); + + // responseStatus + int status = derIn.getEnumerated(); + if (status >= 0 && status < rsvalues.length) { + responseStatus = rsvalues[status]; + } else { + // unspecified responseStatus + throw new IOException("Unknown OCSPResponse status: " + status); + } + if (DEBUG != null) { + DEBUG.println("OCSP response status: " + responseStatus); + } + if (responseStatus != ResponseStatus.SUCCESSFUL) { + // no need to continue, responseBytes are not set. + singleResponseMap = Collections.emptyMap(); + return; + } + + // responseBytes + der = derIn.getDerValue(); + if (!der.isContextSpecific((byte)0)) { + throw new IOException("Bad encoding in responseBytes element " + + "of OCSP response: expected ASN.1 context specific tag 0."); + } + DerValue tmp = der.data.getDerValue(); + if (tmp.tag != DerValue.tag_Sequence) { + throw new IOException("Bad encoding in responseBytes element " + + "of OCSP response: expected ASN.1 SEQUENCE tag."); + } - // responseStatus - responseStatus = derIn.getEnumerated(); + // responseType + derIn = tmp.data; + ObjectIdentifier responseType = derIn.getOID(); + if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) { if (DEBUG != null) { - DEBUG.println("OCSP response: " + - responseToText(responseStatus)); + DEBUG.println("OCSP response type: basic"); } - if (responseStatus != OCSP_RESPONSE_OK) { - throw new CertPathValidatorException( - "OCSP Response Failure: " + - responseToText(responseStatus)); + } else { + if (DEBUG != null) { + DEBUG.println("OCSP response type: " + responseType); } + throw new IOException("Unsupported OCSP response type: " + + responseType); + } - // responseBytes - der = derIn.getDerValue(); - if (! der.isContextSpecific((byte)0)) { - throw new IOException("Bad encoding in responseBytes element " + - "of OCSP response: expected ASN.1 context specific tag 0."); - }; - DerValue tmp = der.data.getDerValue(); - if (tmp.tag != DerValue.tag_Sequence) { - throw new IOException("Bad encoding in responseBytes element " + - "of OCSP response: expected ASN.1 SEQUENCE tag."); - } + // BasicOCSPResponse + DerInputStream basicOCSPResponse = + new DerInputStream(derIn.getOctetString()); - // responseType - derIn = tmp.data; - responseType = derIn.getOID(); - if (responseType.equals(OCSP_BASIC_RESPONSE_OID)) { - if (DEBUG != null) { - DEBUG.println("OCSP response type: basic"); - } - } else { - if (DEBUG != null) { - DEBUG.println("OCSP response type: " + responseType); - } - throw new IOException("Unsupported OCSP response type: " + - responseType); - } - - // BasicOCSPResponse - DerInputStream basicOCSPResponse = - new DerInputStream(derIn.getOctetString()); + DerValue[] seqTmp = basicOCSPResponse.getSequence(2); + if (seqTmp.length < 3) { + throw new IOException("Unexpected BasicOCSPResponse value"); + } - DerValue[] seqTmp = basicOCSPResponse.getSequence(2); - DerValue responseData = seqTmp[0]; + DerValue responseData = seqTmp[0]; - // Need the DER encoded ResponseData to verify the signature later - byte[] responseDataDer = seqTmp[0].toByteArray(); + // Need the DER encoded ResponseData to verify the signature later + byte[] responseDataDer = seqTmp[0].toByteArray(); - // tbsResponseData - if (responseData.tag != DerValue.tag_Sequence) { - throw new IOException("Bad encoding in tbsResponseData " + - " element of OCSP response: expected ASN.1 SEQUENCE tag."); - } - DerInputStream seqDerIn = responseData.data; - DerValue seq = seqDerIn.getDerValue(); - - // version - if (seq.isContextSpecific((byte)0)) { - // seq[0] is version - if (seq.isConstructed() && seq.isContextSpecific()) { - //System.out.println ("version is available"); - seq = seq.data.getDerValue(); - version = seq.getInteger(); - if (seq.data.available() != 0) { - throw new IOException("Bad encoding in version " + - " element of OCSP response: bad format"); - } - seq = seqDerIn.getDerValue(); + // tbsResponseData + if (responseData.tag != DerValue.tag_Sequence) { + throw new IOException("Bad encoding in tbsResponseData " + + "element of OCSP response: expected ASN.1 SEQUENCE tag."); + } + DerInputStream seqDerIn = responseData.data; + DerValue seq = seqDerIn.getDerValue(); + + // version + if (seq.isContextSpecific((byte)0)) { + // seq[0] is version + if (seq.isConstructed() && seq.isContextSpecific()) { + //System.out.println ("version is available"); + seq = seq.data.getDerValue(); + int version = seq.getInteger(); + if (seq.data.available() != 0) { + throw new IOException("Bad encoding in version " + + " element of OCSP response: bad format"); } + seq = seqDerIn.getDerValue(); } + } - // responderID - short tag = (byte)(seq.tag & 0x1f); - if (tag == NAME_TAG) { - responderName = new CertificateIssuerName(seq.getData()); - if (DEBUG != null) { - DEBUG.println("OCSP Responder name: " + responderName); - } - } else if (tag == KEY_TAG) { - // Ignore, for now - } else { - throw new IOException("Bad encoding in responderID element " + - "of OCSP response: expected ASN.1 context specific tag 0 " + - "or 1"); + // responderID + short tag = (byte)(seq.tag & 0x1f); + if (tag == NAME_TAG) { + if (DEBUG != null) { + X500Name responderName = new X500Name(seq.getData()); + DEBUG.println("OCSP Responder name: " + responderName); } + } else if (tag == KEY_TAG) { + // Ignore, for now + } else { + throw new IOException("Bad encoding in responderID element of " + + "OCSP response: expected ASN.1 context specific tag 0 or 1"); + } - // producedAt - seq = seqDerIn.getDerValue(); - producedAtDate = seq.getGeneralizedTime(); + // producedAt + seq = seqDerIn.getDerValue(); + if (DEBUG != null) { + Date producedAtDate = seq.getGeneralizedTime(); + DEBUG.println("OCSP response produced at: " + producedAtDate); + } - // responses - DerValue[] singleResponseDer = seqDerIn.getSequence(1); - // Examine only the first response - singleResponse = new SingleResponse(singleResponseDer[0]); + // responses + DerValue[] singleResponseDer = seqDerIn.getSequence(1); + singleResponseMap + = new HashMap(singleResponseDer.length); + if (DEBUG != null) { + DEBUG.println("OCSP number of SingleResponses: " + + singleResponseDer.length); + } + for (int i = 0; i < singleResponseDer.length; i++) { + SingleResponse singleResponse + = new SingleResponse(singleResponseDer[i]); + singleResponseMap.put(singleResponse.getCertId(), singleResponse); + } - // responseExtensions - if (seqDerIn.available() > 0) { - seq = seqDerIn.getDerValue(); - if (seq.isContextSpecific((byte)1)) { - DerValue[] responseExtDer = seq.data.getSequence(3); - Extension[] responseExtension = - new Extension[responseExtDer.length]; - for (int i = 0; i < responseExtDer.length; i++) { - responseExtension[i] = new Extension(responseExtDer[i]); - if (DEBUG != null) { - DEBUG.println("OCSP extension: " + - responseExtension[i]); - } - if ((responseExtension[i].getExtensionId()).equals( - OCSP_NONCE_EXTENSION_OID)) { - ocspNonce = - responseExtension[i].getExtensionValue(); - - } else if (responseExtension[i].isCritical()) { - throw new IOException( - "Unsupported OCSP critical extension: " + - responseExtension[i].getExtensionId()); - } + // responseExtensions + if (seqDerIn.available() > 0) { + seq = seqDerIn.getDerValue(); + if (seq.isContextSpecific((byte)1)) { + DerValue[] responseExtDer = seq.data.getSequence(3); + for (int i = 0; i < responseExtDer.length; i++) { + Extension responseExtension + = new Extension(responseExtDer[i]); + if (DEBUG != null) { + DEBUG.println("OCSP extension: " + responseExtension); + } + if (responseExtension.getExtensionId().equals( + OCSP_NONCE_EXTENSION_OID)) { + /* + ocspNonce = + responseExtension[i].getExtensionValue(); + */ + } else if (responseExtension.isCritical()) { + throw new IOException( + "Unsupported OCSP critical extension: " + + responseExtension.getExtensionId()); } } } + } - // signatureAlgorithmId - sigAlgId = AlgorithmId.parse(seqTmp[1]); + // signatureAlgorithmId + AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]); - // signature - byte[] signature = seqTmp[2].getBitString(); - X509CertImpl[] x509Certs = null; + // signature + byte[] signature = seqTmp[2].getBitString(); + X509CertImpl[] x509Certs = null; - // if seq[3] is available , then it is a sequence of certificates - if (seqTmp.length > 3) { - // certs are available - DerValue seqCert = seqTmp[3]; - if (! seqCert.isContextSpecific((byte)0)) { - throw new IOException("Bad encoding in certs element " + - "of OCSP response: expected ASN.1 context specific tag 0."); - } - DerValue[] certs = (seqCert.getData()).getSequence(3); - x509Certs = new X509CertImpl[certs.length]; + // if seq[3] is available , then it is a sequence of certificates + if (seqTmp.length > 3) { + // certs are available + DerValue seqCert = seqTmp[3]; + if (!seqCert.isContextSpecific((byte)0)) { + throw new IOException("Bad encoding in certs element of " + + "OCSP response: expected ASN.1 context specific tag 0."); + } + DerValue[] certs = seqCert.getData().getSequence(3); + x509Certs = new X509CertImpl[certs.length]; + try { for (int i = 0; i < certs.length; i++) { x509Certs[i] = new X509CertImpl(certs[i].toByteArray()); } + } catch (CertificateException ce) { + throw new IOException("Bad encoding in X509 Certificate", ce); } + } - // Check whether the cert returned by the responder is trusted - if (x509Certs != null && x509Certs[0] != null) { - X509CertImpl cert = x509Certs[0]; + // Check whether the cert returned by the responder is trusted + if (x509Certs != null && x509Certs[0] != null) { + X509CertImpl cert = x509Certs[0]; - // First check if the cert matches the responder cert which - // was set locally. - if (cert.equals(responderCert)) { - // cert is trusted, now verify the signed response + // First check if the cert matches the responder cert which + // was set locally. + if (cert.equals(responderCert)) { + // cert is trusted, now verify the signed response - // Next check if the cert was issued by the responder cert - // which was set locally. - } else if (cert.getIssuerX500Principal().equals( - responderCert.getSubjectX500Principal())) { + // Next check if the cert was issued by the responder cert + // which was set locally. + } else if (cert.getIssuerX500Principal().equals( + responderCert.getSubjectX500Principal())) { - // Check for the OCSPSigning key purpose + // Check for the OCSPSigning key purpose + try { List keyPurposes = cert.getExtendedKeyUsage(); if (keyPurposes == null || !keyPurposes.contains(KP_OCSP_SIGNING_OID)) { - if (DEBUG != null) { - DEBUG.println("Responder's certificate is not " + - "valid for signing OCSP responses."); - } throw new CertPathValidatorException( "Responder's certificate not valid for signing " + "OCSP responses"); } + } catch (CertificateParsingException cpe) { + // assume cert is not valid for signing + throw new CertPathValidatorException( + "Responder's certificate not valid for signing " + + "OCSP responses", cpe); + } - // check the validity - try { - Date dateCheckedAgainst = params.getDate(); - if (dateCheckedAgainst == null) { - cert.checkValidity(); - } else { - cert.checkValidity(dateCheckedAgainst); - } - } catch (GeneralSecurityException e) { - if (DEBUG != null) { - DEBUG.println("Responder's certificate is not " + - "within the validity period."); - } - throw new CertPathValidatorException( - "Responder's certificate not within the " + - "validity period"); - } - - // check for revocation - // - // A CA may specify that an OCSP client can trust a - // responder for the lifetime of the responder's - // certificate. The CA does so by including the - // extension id-pkix-ocsp-nocheck. - // - Extension noCheck = - cert.getExtension(PKIXExtensions.OCSPNoCheck_Id); - if (noCheck != null) { - if (DEBUG != null) { - DEBUG.println("Responder's certificate includes " + - "the extension id-pkix-ocsp-nocheck."); - } + // check the validity + try { + if (dateCheckedAgainst == null) { + cert.checkValidity(); } else { - // we should do the revocating checking of the - // authorized responder in a future update. + cert.checkValidity(dateCheckedAgainst); } + } catch (GeneralSecurityException e) { + throw new CertPathValidatorException( + "Responder's certificate not within the " + + "validity period", e); + } - // verify the signature - try { - cert.verify(responderCert.getPublicKey()); - responderCert = cert; - // cert is trusted, now verify the signed response - - } catch (GeneralSecurityException e) { - responderCert = null; - } - } else { + // check for revocation + // + // A CA may specify that an OCSP client can trust a + // responder for the lifetime of the responder's + // certificate. The CA does so by including the + // extension id-pkix-ocsp-nocheck. + // + Extension noCheck = + cert.getExtension(PKIXExtensions.OCSPNoCheck_Id); + if (noCheck != null) { if (DEBUG != null) { - DEBUG.println("Responder's certificate is not " + - "authorized to sign OCSP responses."); + DEBUG.println("Responder's certificate includes " + + "the extension id-pkix-ocsp-nocheck."); } - throw new CertPathValidatorException( - "Responder's certificate not authorized to sign " + - "OCSP responses"); + } else { + // we should do the revocation checking of the + // authorized responder in a future update. } - } - // Confirm that the signed response was generated using the public - // key from the trusted responder cert - if (responderCert != null) { + // verify the signature + try { + cert.verify(responderCert.getPublicKey()); + responderCert = cert; + // cert is trusted, now verify the signed response - if (! verifyResponse(responseDataDer, responderCert, - sigAlgId, signature, params)) { - if (DEBUG != null) { - DEBUG.println("Error verifying OCSP Responder's " + - "signature"); - } - throw new CertPathValidatorException( - "Error verifying OCSP Responder's signature"); + } catch (GeneralSecurityException e) { + responderCert = null; } } else { - // Need responder's cert in order to verify the signature - if (DEBUG != null) { - DEBUG.println("Unable to verify OCSP Responder's " + - "signature"); - } throw new CertPathValidatorException( - "Unable to verify OCSP Responder's signature"); + "Responder's certificate is not authorized to sign " + + "OCSP responses"); } - } catch (CertPathValidatorException cpve) { - throw cpve; - } catch (Exception e) { - throw new CertPathValidatorException(e); } + + // Confirm that the signed response was generated using the public + // key from the trusted responder cert + if (responderCert != null) { + if (!verifyResponse(responseDataDer, responderCert, + sigAlgId, signature)) { + throw new CertPathValidatorException( + "Error verifying OCSP Responder's signature"); + } + } else { + // Need responder's cert in order to verify the signature + throw new CertPathValidatorException( + "Unable to verify OCSP Responder's signature"); + } + } + + /** + * Returns the OCSP ResponseStatus. + */ + ResponseStatus getResponseStatus() { + return responseStatus; } /* @@ -449,11 +446,10 @@ class OCSPResponse { * The responder's cert is implicitly trusted. */ private boolean verifyResponse(byte[] responseData, X509Certificate cert, - AlgorithmId sigAlgId, byte[] signBytes, PKIXParameters params) - throws SignatureException { + AlgorithmId sigAlgId, byte[] signBytes) + throws CertPathValidatorException { try { - Signature respSignature = Signature.getInstance(sigAlgId.getName()); respSignature.initVerify(cert); respSignature.update(responseData); @@ -472,92 +468,33 @@ class OCSPResponse { return false; } } catch (InvalidKeyException ike) { - throw new SignatureException(ike); - + throw new CertPathValidatorException(ike); } catch (NoSuchAlgorithmException nsae) { - throw new SignatureException(nsae); + throw new CertPathValidatorException(nsae); + } catch (SignatureException se) { + throw new CertPathValidatorException(se); } } - /* - * Return the revocation status code for a given certificate. + /** + * Returns the SingleResponse of the specified CertId, or null if + * there is no response for that CertId. */ - // used by OCSPChecker - int getCertStatus(SerialNumber sn) { - // ignore serial number for now; if we support multiple - // requests/responses then it will be used - return singleResponse.getStatus(); - } - - // used by OCSPChecker - CertId getCertId() { - return singleResponse.getCertId(); - } - - Date getRevocationTime() { - return singleResponse.getRevocationTime(); - } - - CRLReason getRevocationReason() { - return singleResponse.getRevocationReason(); - } - - Map getSingleExtensions() { - return singleResponse.getSingleExtensions(); - } - - /* - * Map an OCSP response status code to a string. - */ - static private String responseToText(int status) { - switch (status) { - case 0: - return "Successful"; - case 1: - return "Malformed request"; - case 2: - return "Internal error"; - case 3: - return "Try again later"; - case 4: - return "Unused status code"; - case 5: - return "Request must be signed"; - case 6: - return "Request is unauthorized"; - default: - return ("Unknown status code: " + status); - } - } - - /* - * Map a certificate's revocation status code to a string. - */ - // used by OCSPChecker - static String certStatusToText(int certStatus) { - switch (certStatus) { - case 0: - return "Good"; - case 1: - return "Revoked"; - case 2: - return "Unknown"; - default: - return ("Unknown certificate status code: " + certStatus); - } + SingleResponse getSingleResponse(CertId certId) { + return singleResponseMap.get(certId); } /* * A class representing a single OCSP response. */ - private class SingleResponse { - private CertId certId; - private int certStatus; - private Date thisUpdate; - private Date nextUpdate; - private Date revocationTime; - private CRLReason revocationReason = CRLReason.UNSPECIFIED; - private HashMap singleExtensions; + final static class SingleResponse implements OCSP.RevocationStatus { + private final CertId certId; + private final CertStatus certStatus; + private final Date thisUpdate; + private final Date nextUpdate; + private final Date revocationTime; + private final CRLReason revocationReason; + private final Map singleExtensions; private SingleResponse(DerValue der) throws IOException { if (der.tag != DerValue.tag_Sequence) { @@ -568,35 +505,48 @@ class OCSPResponse { certId = new CertId(tmp.getDerValue().data); DerValue derVal = tmp.getDerValue(); short tag = (byte)(derVal.tag & 0x1f); - if (tag == CERT_STATUS_GOOD) { - certStatus = CERT_STATUS_GOOD; - } else if (tag == CERT_STATUS_REVOKED) { - certStatus = CERT_STATUS_REVOKED; + if (tag == CERT_STATUS_REVOKED) { + certStatus = CertStatus.REVOKED; revocationTime = derVal.data.getGeneralizedTime(); if (derVal.data.available() != 0) { - int reason = derVal.getEnumerated(); - // if reason out-of-range just leave as UNSPECIFIED - if (reason >= 0 && reason < values.length) { - revocationReason = values[reason]; + DerValue dv = derVal.data.getDerValue(); + tag = (byte)(dv.tag & 0x1f); + if (tag == 0) { + int reason = dv.data.getEnumerated(); + // if reason out-of-range just leave as UNSPECIFIED + if (reason >= 0 && reason < values.length) { + revocationReason = values[reason]; + } else { + revocationReason = CRLReason.UNSPECIFIED; + } + } else { + revocationReason = CRLReason.UNSPECIFIED; } + } else { + revocationReason = CRLReason.UNSPECIFIED; } // RevokedInfo if (DEBUG != null) { DEBUG.println("Revocation time: " + revocationTime); DEBUG.println("Revocation reason: " + revocationReason); } - - } else if (tag == CERT_STATUS_UNKNOWN) { - certStatus = CERT_STATUS_UNKNOWN; - } else { - throw new IOException("Invalid certificate status"); + revocationTime = null; + revocationReason = CRLReason.UNSPECIFIED; + if (tag == CERT_STATUS_GOOD) { + certStatus = CertStatus.GOOD; + } else if (tag == CERT_STATUS_UNKNOWN) { + certStatus = CertStatus.UNKNOWN; + } else { + throw new IOException("Invalid certificate status"); + } } thisUpdate = tmp.getGeneralizedTime(); if (tmp.available() == 0) { // we are done + nextUpdate = null; } else { derVal = tmp.getDerValue(); tag = (byte)(derVal.tag & 0x1f); @@ -610,6 +560,8 @@ class OCSPResponse { derVal = tmp.getDerValue(); tag = (byte)(derVal.tag & 0x1f); } + } else { + nextUpdate = null; } } // singleExtensions @@ -627,7 +579,11 @@ class OCSPResponse { DEBUG.println("OCSP single extension: " + ext); } } + } else { + singleExtensions = Collections.emptyMap(); } + } else { + singleExtensions = Collections.emptyMap(); } long now = System.currentTimeMillis(); @@ -657,7 +613,7 @@ class OCSPResponse { /* * Return the certificate's revocation status code */ - private int getStatus() { + @Override public CertStatus getCertStatus() { return certStatus; } @@ -665,28 +621,28 @@ class OCSPResponse { return certId; } - private Date getRevocationTime() { - return revocationTime; + @Override public Date getRevocationTime() { + return (Date) revocationTime.clone(); } - private CRLReason getRevocationReason() { + @Override public CRLReason getRevocationReason() { return revocationReason; } - private Map getSingleExtensions() { - return singleExtensions; + @Override + public Map getSingleExtensions() { + return Collections.unmodifiableMap(singleExtensions); } /** * Construct a string representation of a single OCSP response. */ - public String toString() { + @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("SingleResponse: \n"); sb.append(certId); - sb.append("\nCertStatus: "+ certStatusToText(getCertStatus(null)) + - "\n"); - if (certStatus == CERT_STATUS_REVOKED) { + sb.append("\nCertStatus: "+ certStatus + "\n"); + if (certStatus == CertStatus.REVOKED) { sb.append("revocationTime is " + revocationTime + "\n"); sb.append("revocationReason is " + revocationReason + "\n"); } diff --git a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java index 63335d2342c03d4c25e712b27d0dff51546da1f0..145879239accaa2eb97c68565fe25ee503a3b2a4 100644 --- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java +++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.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 @@ -28,8 +28,6 @@ package sun.security.provider.certpath; import java.io.IOException; import java.security.AccessController; import java.security.InvalidAlgorithmParameterException; -import java.security.PrivilegedAction; -import java.security.Security; import java.security.cert.CertPath; import java.security.cert.CertPathParameters; import java.security.cert.CertPathValidatorException; @@ -49,6 +47,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.Set; import javax.security.auth.x500.X500Principal; +import sun.security.action.GetBooleanSecurityPropertyAction; import sun.security.util.Debug; /** @@ -67,7 +66,8 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { private List userCheckers; private String sigProvider; private BasicChecker basicChecker; - private String ocspProperty; + private boolean ocspEnabled = false; + private boolean onlyEECert = false; /** * Default constructor. @@ -253,13 +253,12 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { if (pkixParam.isRevocationEnabled()) { // Examine OCSP security property - ocspProperty = AccessController.doPrivileged( - new PrivilegedAction() { - public String run() { - return - Security.getProperty(OCSPChecker.OCSP_ENABLE_PROP); - } - }); + ocspEnabled = AccessController.doPrivileged( + new GetBooleanSecurityPropertyAction + (OCSPChecker.OCSP_ENABLE_PROP)); + onlyEECert = AccessController.doPrivileged( + new GetBooleanSecurityPropertyAction + ("com.sun.security.onlyCheckRevocationOfEECert")); } } @@ -301,15 +300,15 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { if (pkixParam.isRevocationEnabled()) { // Use OCSP if it has been enabled - if ("true".equalsIgnoreCase(ocspProperty)) { + if (ocspEnabled) { OCSPChecker ocspChecker = - new OCSPChecker(cpOriginal, pkixParam); + new OCSPChecker(cpOriginal, pkixParam, onlyEECert); certPathCheckers.add(ocspChecker); } // Always use CRLs - CrlRevocationChecker revocationChecker = - new CrlRevocationChecker(anchor, pkixParam, certList); + CrlRevocationChecker revocationChecker = new + CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert); certPathCheckers.add(revocationChecker); } diff --git a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java index 0c439349d3cf47d1322105adb0f9709814688ed1..6723cb8c6b896d06692297cc2887e1089b4a08b1 100644 --- a/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java +++ b/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.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 @@ -26,6 +26,7 @@ package sun.security.provider.certpath; import java.io.IOException; +import java.security.AccessController; import java.security.GeneralSecurityException; import java.security.InvalidAlgorithmParameterException; import java.security.Principal; @@ -44,6 +45,7 @@ import java.util.LinkedList; import java.util.Set; import javax.security.auth.x500.X500Principal; +import sun.security.action.GetBooleanSecurityPropertyAction; import sun.security.x509.X500Name; import sun.security.x509.PKIXExtensions; import sun.security.util.Debug; @@ -85,6 +87,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { private PublicKey finalPublicKey; private X509CertSelector targetSel; private List orderedCertStores; + private boolean onlyEECert = false; /** * Create an instance of SunCertPathBuilder. @@ -97,6 +100,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { } catch (CertificateException e) { throw new CertPathBuilderException(e); } + onlyEECert = AccessController.doPrivileged( + new GetBooleanSecurityPropertyAction + ("com.sun.security.onlyCheckRevocationOfEECert")); } /** @@ -256,7 +262,6 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { /* * Private build reverse method. - * */ private void buildReverse(List> adjacencyList, LinkedList certPathList) throws Exception @@ -296,7 +301,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { currentState.updateState(anchor); // init the crl checker currentState.crlChecker = - new CrlRevocationChecker(null, buildParams); + new CrlRevocationChecker(null, buildParams, null, onlyEECert); try { depthFirstSearchReverse(null, currentState, new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList, @@ -341,10 +346,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { adjacencyList.add(new LinkedList()); // init the crl checker - currentState.crlChecker = new CrlRevocationChecker(null, buildParams); + currentState.crlChecker + = new CrlRevocationChecker(null, buildParams, null, onlyEECert); depthFirstSearchForward(targetSubjectDN, currentState, - new ForwardBuilder(buildParams, targetSubjectDN, searchAllCertStores), + new ForwardBuilder + (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert), adjacencyList, certPathList); } @@ -486,8 +493,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { userCheckers.add(mustCheck, basicChecker); mustCheck++; if (buildParams.isRevocationEnabled()) { - userCheckers.add(mustCheck, - new CrlRevocationChecker(anchor, buildParams)); + userCheckers.add(mustCheck, new CrlRevocationChecker + (anchor, buildParams, null, onlyEECert)); mustCheck++; } } diff --git a/src/share/classes/sun/security/x509/AccessDescription.java b/src/share/classes/sun/security/x509/AccessDescription.java index 1544ea953bec5864f786be79daf0459cd7614995..0911018110fe23a243a6e4b067c9bc4899c1848e 100644 --- a/src/share/classes/sun/security/x509/AccessDescription.java +++ b/src/share/classes/sun/security/x509/AccessDescription.java @@ -113,7 +113,7 @@ public final class AccessDescription { } else { method = accessMethod.toString(); } - return ("accessMethod: " + method + + return ("\n accessMethod: " + method + "\n accessLocation: " + accessLocation.toString() + "\n"); } } diff --git a/src/share/classes/sun/util/LocaleServiceProviderPool.java b/src/share/classes/sun/util/LocaleServiceProviderPool.java index 8fd21c9ce0a003ee4654a7edae946397a0575e51..9fcfe5b7abc0fc983b07a373ae1f9186fdcac551 100644 --- a/src/share/classes/sun/util/LocaleServiceProviderPool.java +++ b/src/share/classes/sun/util/LocaleServiceProviderPool.java @@ -39,8 +39,8 @@ import java.util.ServiceLoader; import java.util.ServiceConfigurationError; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Logger; import java.util.spi.LocaleServiceProvider; +import sun.util.logging.PlatformLogger; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; @@ -122,10 +122,15 @@ public final class LocaleServiceProviderPool { } }); } catch (PrivilegedActionException e) { - Logger.getLogger("sun.util.LocaleServiceProviderPool").config(e.toString()); + config(e.toString()); } } + private static void config(String message) { + PlatformLogger logger = PlatformLogger.getLogger("sun.util.LocaleServiceProviderPool"); + logger.config(message); + } + /** * Lazy loaded set of available locales. * Loading all locales is a very long operation. @@ -337,7 +342,7 @@ public final class LocaleServiceProviderPool { if (providersObj != null) { return providersObj; } else if (isObjectProvider) { - Logger.getLogger("sun.util.LocaleServiceProviderPool").config( + config( "A locale sensitive service provider returned null for a localized objects, which should not happen. provider: " + lsp + " locale: " + requested); } } diff --git a/src/share/classes/sun/util/logging/PlatformLogger.java b/src/share/classes/sun/util/logging/PlatformLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..e8523b81f8d6283907b2b8aaff5d133ad175b24f --- /dev/null +++ b/src/share/classes/sun/util/logging/PlatformLogger.java @@ -0,0 +1,635 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + + +package sun.util.logging; + +import java.lang.ref.WeakReference; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.text.MessageFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + +/** + * Platform logger provides an API for the JRE components to log + * messages. This enables the runtime components to eliminate the + * static dependency of the logging facility and also defers the + * java.util.logging initialization until it is enabled. + * In addition, the PlatformLogger API can be used if the logging + * module does not exist. + * + * If the logging facility is not enabled, the platform loggers + * will output log messages per the default logging configuration + * (see below). In this implementation, it does not log the + * the stack frame information issuing the log message. + * + * When the logging facility is enabled (at startup or runtime), + * the java.util.logging.Logger will be created for each platform + * logger and all log messages will be forwarded to the Logger + * to handle. + * + * Logging facility is "enabled" when one of the following + * conditions is met: + * 1) a system property "java.util.logging.config.class" or + * "java.util.logging.config.file" is set + * 2) java.util.logging.LogManager or java.util.logging.Logger + * is referenced that will trigger the logging initialization. + * + * Default logging configuration: + * global logging level = INFO + * handlers = java.util.logging.ConsoleHandler + * java.util.logging.ConsoleHandler.level = INFO + * java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter + * + * Limitation: + * /lib/logging.properties is the system-wide logging + * configuration defined in the specification and read in the + * default case to configure any java.util.logging.Logger instances. + * Platform loggers will not detect if /lib/logging.properties + * is modified. In other words, unless the java.util.logging API + * is used at runtime or the logging system properties is set, + * the platform loggers will use the default setting described above. + * The platform loggers are designed for JDK developers use and + * this limitation can be workaround with setting + * -Djava.util.logging.config.file system property. + * + * @since 1.7 + */ +public class PlatformLogger { + // Same values as java.util.logging.Level for easy mapping + public static final int OFF = Integer.MAX_VALUE; + public static final int SEVERE = 1000; + public static final int WARNING = 900; + public static final int INFO = 800; + public static final int CONFIG = 700; + public static final int FINE = 500; + public static final int FINER = 400; + public static final int FINEST = 300; + public static final int ALL = Integer.MIN_VALUE; + + private static final int defaultLevel = INFO; + private static boolean loggingEnabled; + static { + loggingEnabled = AccessController.doPrivileged( + new PrivilegedAction() { + public Boolean run() { + String cname = System.getProperty("java.util.logging.config.class"); + String fname = System.getProperty("java.util.logging.config.file"); + return (cname != null || fname != null); + } + }); + } + + // Table of known loggers. Maps names to PlatformLoggers. + private static Map> loggers = + new HashMap>(); + + /** + * Returns a PlatformLogger of a given name. + */ + public static synchronized PlatformLogger getLogger(String name) { + PlatformLogger log = null; + WeakReference ref = loggers.get(name); + if (ref != null) { + log = ref.get(); + } + if (log == null) { + log = new PlatformLogger(name); + loggers.put(name, new WeakReference(log)); + } + return log; + } + + /** + * Initialize java.util.logging.Logger objects for all platform loggers. + * This method is called from LogManager.readPrimordialConfiguration(). + */ + public static synchronized void redirectPlatformLoggers() { + if (loggingEnabled || !JavaLogger.supported) return; + + loggingEnabled = true; + for (Map.Entry> entry : loggers.entrySet()) { + WeakReference ref = entry.getValue(); + PlatformLogger plog = ref.get(); + if (plog != null) { + plog.newJavaLogger(); + } + } + } + + /** + * Creates a new JavaLogger that the platform logger uses + */ + private void newJavaLogger() { + logger = new JavaLogger(logger.name, logger.effectiveLevel); + } + + // logger may be replaced with a JavaLogger object + // when the logging facility is enabled + private volatile LoggerProxy logger; + + private PlatformLogger(String name) { + if (loggingEnabled) { + this.logger = new JavaLogger(name); + } else { + this.logger = new LoggerProxy(name); + } + } + + /** + * A convenience method to test if the logger is turned off. + * (i.e. its level is OFF). + */ + public boolean isEnabled() { + return logger.isEnabled(); + } + + /** + * Gets the name for this platform logger. + */ + public String getName() { + return logger.name; + } + + /** + * Returns true if a message of the given level would actually + * be logged by this logger. + */ + public boolean isLoggable(int level) { + return logger.isLoggable(level); + } + + /** + * Gets the current log level. Returns 0 if the current effective level + * is not set (equivalent to Logger.getLevel() returns null). + */ + public int getLevel() { + return logger.getLevel(); + } + + /** + * Sets the log level. + */ + public void setLevel(int newLevel) { + logger.setLevel(newLevel); + } + + /** + * Logs a SEVERE message. + */ + public void severe(String msg) { + logger.doLog(SEVERE, msg); + } + + public void severe(String msg, Throwable t) { + logger.doLog(SEVERE, msg, t); + } + + public void severe(String msg, Object... params) { + logger.doLog(SEVERE, msg, params); + } + + /** + * Logs a WARNING message. + */ + public void warning(String msg) { + logger.doLog(WARNING, msg); + } + + public void warning(String msg, Throwable t) { + logger.doLog(WARNING, msg, t); + } + + public void warning(String msg, Object... params) { + logger.doLog(WARNING, msg, params); + } + + /** + * Logs an INFO message. + */ + public void info(String msg) { + logger.doLog(INFO, msg); + } + + public void info(String msg, Throwable t) { + logger.doLog(INFO, msg, t); + } + + public void info(String msg, Object... params) { + logger.doLog(INFO, msg, params); + } + + /** + * Logs a CONFIG message. + */ + public void config(String msg) { + logger.doLog(CONFIG, msg); + } + + public void config(String msg, Throwable t) { + logger.doLog(CONFIG, msg, t); + } + + public void config(String msg, Object... params) { + logger.doLog(CONFIG, msg, params); + } + + /** + * Logs a FINE message. + */ + public void fine(String msg) { + logger.doLog(FINE, msg); + } + + public void fine(String msg, Throwable t) { + logger.doLog(FINE, msg, t); + } + + public void fine(String msg, Object... params) { + logger.doLog(FINE, msg, params); + } + + /** + * Logs a FINER message. + */ + public void finer(String msg) { + logger.doLog(FINER, msg); + } + + public void finer(String msg, Throwable t) { + logger.doLog(FINER, msg, t); + } + + public void finer(String msg, Object... params) { + logger.doLog(FINER, msg, params); + } + + /** + * Logs a FINEST message. + */ + public void finest(String msg) { + logger.doLog(FINEST, msg); + } + + public void finest(String msg, Throwable t) { + logger.doLog(FINEST, msg, t); + } + + public void finest(String msg, Object... params) { + logger.doLog(FINEST, msg, params); + } + + /** + * Default platform logging support - output messages to + * System.err - equivalent to ConsoleHandler with SimpleFormatter. + */ + static class LoggerProxy { + private static final PrintStream defaultStream = System.err; + private static final String lineSeparator = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("line.separator"); + } + }); + + final String name; + volatile int levelValue; + volatile int effectiveLevel = 0; // current effective level value + + LoggerProxy(String name) { + this(name, defaultLevel); + } + + LoggerProxy(String name, int level) { + this.name = name; + this.levelValue = level == 0 ? defaultLevel : level; + } + + boolean isEnabled() { + return levelValue != OFF; + } + + int getLevel() { + return effectiveLevel; + } + + void setLevel(int newLevel) { + levelValue = newLevel; + effectiveLevel = newLevel; + } + + void doLog(int level, String msg) { + if (level < levelValue || levelValue == OFF) { + return; + } + defaultStream.println(format(level, msg, null)); + } + + void doLog(int level, String msg, Throwable thrown) { + if (level < levelValue || levelValue == OFF) { + return; + } + defaultStream.println(format(level, msg, thrown)); + } + + void doLog(int level, String msg, Object... params) { + if (level < levelValue || levelValue == OFF) { + return; + } + String newMsg = formatMessage(msg, params); + defaultStream.println(format(level, newMsg, null)); + } + + public boolean isLoggable(int level) { + if (level < levelValue || levelValue == OFF) { + return false; + } + return true; + } + + private static final String format = "{0,date} {0,time}"; + + private Object args[] = new Object[1]; + private MessageFormat formatter; + private Date dat; + + // Copied from java.util.logging.Formatter.formatMessage + private String formatMessage(String format, Object... parameters) { + // Do the formatting. + try { + if (parameters == null || parameters.length == 0) { + // No parameters. Just return format string. + return format; + } + // Is it a java.text style format? + // Ideally we could match with + // Pattern.compile("\\{\\d").matcher(format).find()) + // However the cost is 14% higher, so we cheaply check for + // 1 of the first 4 parameters + if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 || + format.indexOf("{2") >=0|| format.indexOf("{3") >=0) { + return java.text.MessageFormat.format(format, parameters); + } + return format; + } catch (Exception ex) { + // Formatting failed: use format string. + return format; + } + } + + private synchronized String format(int level, String msg, Throwable thrown) { + StringBuffer sb = new StringBuffer(); + // Minimize memory allocations here. + if (dat == null) { + dat = new Date(); + formatter = new MessageFormat(format); + } + dat.setTime(System.currentTimeMillis()); + args[0] = dat; + StringBuffer text = new StringBuffer(); + formatter.format(args, text, null); + sb.append(text); + sb.append(" "); + sb.append(getCallerInfo()); + sb.append(lineSeparator); + sb.append(PlatformLogger.getLevelName(level)); + sb.append(": "); + sb.append(msg); + if (thrown != null) { + try { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + thrown.printStackTrace(pw); + pw.close(); + sb.append(sw.toString()); + } catch (Exception ex) { + throw new AssertionError(ex); + } + } + + return sb.toString(); + } + + // Returns the caller's class and method's name; best effort + // if cannot infer, return the logger's name. + private String getCallerInfo() { + String sourceClassName = null; + String sourceMethodName = null; + + JavaLangAccess access = SharedSecrets.getJavaLangAccess(); + Throwable throwable = new Throwable(); + int depth = access.getStackTraceDepth(throwable); + + String logClassName = "sun.util.logging.PlatformLogger"; + boolean lookingForLogger = true; + for (int ix = 0; ix < depth; ix++) { + // Calling getStackTraceElement directly prevents the VM + // from paying the cost of building the entire stack frame. + StackTraceElement frame = + access.getStackTraceElement(throwable, ix); + String cname = frame.getClassName(); + if (lookingForLogger) { + // Skip all frames until we have found the first logger frame. + if (cname.equals(logClassName)) { + lookingForLogger = false; + } + } else { + if (!cname.equals(logClassName)) { + // We've found the relevant frame. + sourceClassName = cname; + sourceMethodName = frame.getMethodName(); + break; + } + } + } + + if (sourceClassName != null) { + return sourceClassName + " " + sourceMethodName; + } else { + return name; + } + } + } + + /** + * JavaLogger forwards all the calls to its corresponding + * java.util.logging.Logger object. + */ + static class JavaLogger extends LoggerProxy { + private static final boolean supported; + private static final Class loggerClass; + private static final Class levelClass; + private static final Method getLoggerMethod; + private static final Method setLevelMethod; + private static final Method getLevelMethod; + private static final Method isLoggableMethod; + private static final Method logMethod; + private static final Method logThrowMethod; + private static final Method logParamsMethod; + private static final Map levelObjects = + new HashMap(); + + static { + loggerClass = getClass("java.util.logging.Logger"); + levelClass = getClass("java.util.logging.Level"); + getLoggerMethod = getMethod(loggerClass, "getLogger", String.class); + setLevelMethod = getMethod(loggerClass, "setLevel", levelClass); + getLevelMethod = getMethod(loggerClass, "getLevel"); + isLoggableMethod = getMethod(loggerClass, "isLoggable", levelClass); + logMethod = getMethod(loggerClass, "log", levelClass, String.class); + logThrowMethod = getMethod(loggerClass, "log", levelClass, String.class, Throwable.class); + logParamsMethod = getMethod(loggerClass, "log", levelClass, String.class, Object[].class); + supported = (loggerClass != null && levelClass != null && getLoggerMethod != null && + getLevelMethod != null && setLevelMethod != null && + logMethod != null && logThrowMethod != null && logParamsMethod != null); + if (supported) { + // initialize the map to Level objects + getLevelObjects(); + } + } + + private static Class getClass(String name) { + try { + return Class.forName(name, true, null); + } catch (ClassNotFoundException e) { + return null; + } + } + + private static Method getMethod(Class cls, String name, Class... parameterTypes) { + if (cls == null) return null; + + try { + return cls.getMethod(name, parameterTypes); + } catch (NoSuchMethodException e) { + throw new AssertionError(e); + } + } + + private static Object invoke(Method m, Object obj, Object... params) { + try { + return m.invoke(obj, params); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } catch (InvocationTargetException e) { + throw new AssertionError(e); + } + } + + private static void getLevelObjects() { + // get all java.util.logging.Level objects + Method parseLevelMethod = getMethod(levelClass, "parse", String.class); + int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL}; + for (int l : levelArray) { + Object o = invoke(parseLevelMethod, null, getLevelName(l)); + levelObjects.put(l, o); + } + } + + private final Object javaLogger; + JavaLogger(String name) { + this(name, 0); + } + + JavaLogger(String name, int level) { + super(name, level); + this.javaLogger = invoke(getLoggerMethod, null, name); + if (level != 0) { + // level has been updated and so set the Logger's level + invoke(setLevelMethod, javaLogger, levelObjects.get(level)); + } + } + + /** + * Let Logger.log() do the filtering since if the level of a + * platform logger is altered directly from + * java.util.logging.Logger.setLevel(), the levelValue will + * not be updated. + */ + void doLog(int level, String msg) { + invoke(logMethod, javaLogger, levelObjects.get(level), msg); + } + + void doLog(int level, String msg, Throwable t) { + invoke(logThrowMethod, javaLogger, levelObjects.get(level), msg, t); + } + + void doLog(int level, String msg, Object... params) { + invoke(logParamsMethod, javaLogger, levelObjects.get(level), msg, params); + } + + boolean isEnabled() { + Object level = invoke(getLevelMethod, javaLogger); + return level == null || level.equals(levelObjects.get(OFF)) == false; + } + + int getLevel() { + Object level = invoke(getLevelMethod, javaLogger); + if (level != null) { + for (Map.Entry l : levelObjects.entrySet()) { + if (level == l.getValue()) { + return l.getKey(); + } + } + } + return 0; + } + + void setLevel(int newLevel) { + levelValue = newLevel; + invoke(setLevelMethod, javaLogger, levelObjects.get(newLevel)); + } + + public boolean isLoggable(int level) { + return (Boolean) invoke(isLoggableMethod, javaLogger, levelObjects.get(level)); + } + } + + + private static String getLevelName(int level) { + switch (level) { + case OFF : return "OFF"; + case SEVERE : return "SEVERE"; + case WARNING : return "WARNING"; + case INFO : return "INFO"; + case CONFIG : return "CONFIG"; + case FINE : return "FINE"; + case FINER : return "FINER"; + case FINEST : return "FINEST"; + case ALL : return "ALL"; + default : return "UNKNOWN"; + } + } + +} diff --git a/src/share/demo/jvmti/waiters/Agent.cpp b/src/share/demo/jvmti/waiters/Agent.cpp index 30786133d50236e7de6c4171b453d6891786a23d..f4da70281fd75e817ad38fd939b8dcbf379fc0e3 100644 --- a/src/share/demo/jvmti/waiters/Agent.cpp +++ b/src/share/demo/jvmti/waiters/Agent.cpp @@ -72,36 +72,30 @@ Agent::get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object) { jvmtiError err; Monitor *m; + jlong tag; - /* We use tags to track these, the tag is the Monitor pointer */ - err = jvmti->RawMonitorEnter(lock); { - check_jvmti_error(jvmti, err, "raw monitor enter"); - - /* The raw monitor enter/exit protects us from creating two - * instances for the same object. - */ - jlong tag; - - m = NULL; - tag = (jlong)0; - err = jvmti->GetTag(object, &tag); - check_jvmti_error(jvmti, err, "get tag"); - /*LINTED*/ - m = (Monitor *)(void *)(ptrdiff_t)tag; - if ( m == NULL ) { - m = new Monitor(jvmti, env, object); - /*LINTED*/ - tag = (jlong)(ptrdiff_t)(void *)m; - err = jvmti->SetTag(object, tag); - check_jvmti_error(jvmti, err, "set tag"); - /* Save monitor on list */ + m = NULL; + tag = (jlong)0; + err = jvmti->GetTag(object, &tag); + check_jvmti_error(jvmti, err, "get tag"); + /*LINTED*/ + m = (Monitor *)(void *)(ptrdiff_t)tag; + if ( m == NULL ) { + m = new Monitor(jvmti, env, object); + /* Save monitor on list */ + if (monitor_count == monitor_list_size) { + monitor_list_size += monitor_list_grow_size; monitor_list = (Monitor**)realloc((void*)monitor_list, - (monitor_count+1)*(int)sizeof(Monitor*)); - monitor_list[monitor_count++] = m; + (monitor_list_size)*(int)sizeof(Monitor*)); } - } err = jvmti->RawMonitorExit(lock); - check_jvmti_error(jvmti, err, "raw monitor exit"); - + monitor_list[monitor_count] = m; + m->set_slot(monitor_count); + monitor_count++; + /*LINTED*/ + tag = (jlong)(ptrdiff_t)(void *)m; + err = jvmti->SetTag(object, tag); + check_jvmti_error(jvmti, err, "set tag"); + } return m; } @@ -112,12 +106,11 @@ Agent::Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread) stdout_message("Agent created..\n"); stdout_message("VMInit...\n"); - /* Create a Monitor lock to use */ - err = jvmti->CreateRawMonitor("waiters Agent lock", &lock); - check_jvmti_error(jvmti, err, "create raw monitor"); /* Start monitor list */ monitor_count = 0; - monitor_list = (Monitor**)malloc((int)sizeof(Monitor*)); + monitor_list_size = initial_monitor_list_size; + monitor_list = (Monitor**) + malloc(monitor_list_size*(int)sizeof(Monitor*)); } Agent::~Agent() @@ -134,9 +127,6 @@ void Agent::vm_death(jvmtiEnv *jvmti, JNIEnv *env) delete monitor_list[i]; } free(monitor_list); - /* Destroy the Monitor lock to use */ - err = jvmti->DestroyRawMonitor(lock); - check_jvmti_error(jvmti, err, "destroy raw monitor"); /* Print death message */ stdout_message("VMDeath...\n"); } @@ -215,8 +205,16 @@ void Agent::object_free(jvmtiEnv* jvmti, jlong tag) /* We just cast the tag to a C++ pointer and delete it. * we know it can only be a Monitor *. */ - Monitor *m; + Monitor *m; /*LINTED*/ m = (Monitor *)(ptrdiff_t)tag; + if (monitor_count > 1) { + /* Move the last element to this Monitor's slot */ + int slot = m->get_slot(); + Monitor *last = monitor_list[monitor_count-1]; + monitor_list[slot] = last; + last->set_slot(slot); + } + monitor_count--; delete m; } diff --git a/src/share/demo/jvmti/waiters/Agent.hpp b/src/share/demo/jvmti/waiters/Agent.hpp index 9885baf8ba35a6d4749139bd7c8236abd3d2a811..65fe1227362500f7b82d0703b3062ff24584510c 100644 --- a/src/share/demo/jvmti/waiters/Agent.hpp +++ b/src/share/demo/jvmti/waiters/Agent.hpp @@ -34,8 +34,12 @@ class Agent { private: - jrawMonitorID lock; + enum { + initial_monitor_list_size = 64, + monitor_list_grow_size = 16 + }; Monitor **monitor_list; + unsigned monitor_list_size; unsigned monitor_count; Thread *get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread); Monitor *get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object); diff --git a/src/share/demo/jvmti/waiters/Monitor.cpp b/src/share/demo/jvmti/waiters/Monitor.cpp index a5efc5b23b30b660b7b7b3d4d58bbec9ad14e902..acd092a142af03341c283d965ba1416e94ad2978 100644 --- a/src/share/demo/jvmti/waiters/Monitor.cpp +++ b/src/share/demo/jvmti/waiters/Monitor.cpp @@ -73,6 +73,16 @@ Monitor::~Monitor() name, contends, waits, timeouts); } +int Monitor::get_slot() +{ + return slot; +} + +void Monitor::set_slot(int aslot) +{ + slot = aslot; +} + void Monitor::contended() { contends++; diff --git a/src/share/demo/jvmti/waiters/Monitor.hpp b/src/share/demo/jvmti/waiters/Monitor.hpp index 95b49560abdc23d12365512adc681aef0e40fca3..af6dedda5b9f65ee4f519fd1685e6296ff879dd8 100644 --- a/src/share/demo/jvmti/waiters/Monitor.hpp +++ b/src/share/demo/jvmti/waiters/Monitor.hpp @@ -35,6 +35,7 @@ class Monitor { private: char name[64]; + int slot; unsigned contends; unsigned waits; unsigned timeouts; @@ -42,6 +43,8 @@ class Monitor { public: Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object); ~Monitor(); + int get_slot(); + void set_slot(int i); void contended(); void waited(); void timeout(); diff --git a/src/share/javavm/export/jvm.h b/src/share/javavm/export/jvm.h index df8f27e6602eaf6d68f43018fcb3b15ce653fe6e..4f141d21fb8dc0202e4aed41c94cc677d293fd19 100644 --- a/src/share/javavm/export/jvm.h +++ b/src/share/javavm/export/jvm.h @@ -374,6 +374,12 @@ JVM_FindPrimitiveClass(JNIEnv *env, const char *utf); JNIEXPORT void JNICALL JVM_ResolveClass(JNIEnv *env, jclass cls); +/* + * Find a class from a boot class loader. Returns NULL if class not found. + */ +JNIEXPORT jclass JNICALL +JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); + /* * Find a class from a given class loader. Throw ClassNotFoundException * or NoClassDefFoundError depending on the value of the last diff --git a/src/share/lib/net.properties b/src/share/lib/net.properties index e941d50e3f49fdaf5e26359c07695c0d3cc11a42..da78a84d511d3a137736d6f0438c3c1892515b38 100644 --- a/src/share/lib/net.properties +++ b/src/share/lib/net.properties @@ -32,7 +32,7 @@ java.net.useSystemProxies=false # # http.proxyHost= # http.proxyPort=80 -# http.nonProxyHosts=localhost|127.0.0.1 +http.nonProxyHosts=localhost|127.*|[::1] # # HTTPS Proxy Settings. proxyHost is the name of the proxy server # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default @@ -49,7 +49,7 @@ java.net.useSystemProxies=false # # ftp.proxyHost= # ftp.proxyPort=80 -# ftp.nonProxyHosts=localhost|127.0.0.1 +ftp.nonProxyHosts=localhost|127.*|[::1] # # Gopher Proxy settings. proxyHost is the name of the proxy server # (e.g. proxy.mydomain.com), proxyPort is the port number to use (default diff --git a/src/share/native/java/lang/ClassLoader.c b/src/share/native/java/lang/ClassLoader.c index bedf87ce7e6571ad4fa3cce43edf456ff4581d6b..b080fef2e53be7b744e7b01a9801301e24a31c4e 100644 --- a/src/share/native/java/lang/ClassLoader.c +++ b/src/share/native/java/lang/ClassLoader.c @@ -237,6 +237,9 @@ Java_java_lang_ClassLoader_resolveClass0(JNIEnv *env, jobject this, JVM_ResolveClass(env, cls); } +/* + * Returns NULL if class not found. + */ JNIEXPORT jclass JNICALL Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, jstring classname) @@ -246,7 +249,6 @@ Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, char buf[128]; if (classname == NULL) { - JNU_ThrowClassNotFoundException(env, 0); return 0; } @@ -258,11 +260,10 @@ Java_java_lang_ClassLoader_findBootstrapClass(JNIEnv *env, jobject loader, VerifyFixClassname(clname); if (!VerifyClassname(clname, JNI_TRUE)) { /* expects slashed name */ - JNU_ThrowClassNotFoundException(env, clname); goto done; } - cls = JVM_FindClassFromClassLoader(env, clname, JNI_FALSE, 0, JNI_FALSE); + cls = JVM_FindClassFromBootLoader(env, clname); done: if (clname != buf) { diff --git a/src/share/native/sun/security/ec/ECC_JNI.cpp b/src/share/native/sun/security/ec/ECC_JNI.cpp index fb227e82cac8668080991a85d68da4e0ec8cfc94..e847391a09b289bda6fa0eb5f5a365ae0d4b5b3f 100644 --- a/src/share/native/sun/security/ec/ECC_JNI.cpp +++ b/src/share/native/sun/security/ec/ECC_JNI.cpp @@ -24,7 +24,7 @@ */ #include -#include "ecc_impl.h" +#include "impl/ecc_impl.h" #define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException" #define INVALID_ALGORITHM_PARAMETER_EXCEPTION \ diff --git a/src/share/native/sun/security/ec/ec.c b/src/share/native/sun/security/ec/impl/ec.c similarity index 100% rename from src/share/native/sun/security/ec/ec.c rename to src/share/native/sun/security/ec/impl/ec.c diff --git a/src/share/native/sun/security/ec/impl/ec.h b/src/share/native/sun/security/ec/impl/ec.h new file mode 100644 index 0000000000000000000000000000000000000000..d472670913bddd81d1c993f708411879c1ad91d0 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec2.h b/src/share/native/sun/security/ec/impl/ec2.h new file mode 100644 index 0000000000000000000000000000000000000000..c1b2d7965e5d300c4d65aa96c09f62fb38907c9b --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec2_163.c b/src/share/native/sun/security/ec/impl/ec2_163.c new file mode 100644 index 0000000000000000000000000000000000000000..ecdb51210639e3963bad368bbb7915d1143fded9 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec2_193.c b/src/share/native/sun/security/ec/impl/ec2_193.c new file mode 100644 index 0000000000000000000000000000000000000000..f6187d356125cda91c70cfb16e6fb3c5830905d3 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec2_233.c b/src/share/native/sun/security/ec/impl/ec2_233.c new file mode 100644 index 0000000000000000000000000000000000000000..2b29c46ea762e7bcc48389f83cfd41947886db5c --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec2_aff.c b/src/share/native/sun/security/ec/impl/ec2_aff.c new file mode 100644 index 0000000000000000000000000000000000000000..bb52cbc97f987a0912163a3ce22a832bbf51556d --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec2_mont.c b/src/share/native/sun/security/ec/impl/ec2_mont.c new file mode 100644 index 0000000000000000000000000000000000000000..5cef20f5303c3c2da0fb126bfa7f8863c48453d7 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ec_naf.c b/src/share/native/sun/security/ec/impl/ec_naf.c new file mode 100644 index 0000000000000000000000000000000000000000..1d110904d295af34ad282021b1f1fb5662ff613e --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecc_impl.h b/src/share/native/sun/security/ec/impl/ecc_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..95fc93b3e7168ff8e15369449caa285373b2ef35 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/ecc_impl.h @@ -0,0 +1,275 @@ +/* ********************************************************************* + * + * Sun elects to have this file available under and governed by the + * Mozilla Public License Version 1.1 ("MPL") (see + * http://www.mozilla.org/MPL/ for full license text). For the avoidance + * of doubt and subject to the following, Sun also elects to allow + * licensees to use this file under the MPL, the GNU General Public + * License version 2 only or the Lesser General Public License version + * 2.1 only. Any references to the "GNU General Public License version 2 + * or later" or "GPL" in the following shall be construed to mean the + * GNU General Public License version 2 only. Any references to the "GNU + * Lesser General Public License version 2.1 or later" or "LGPL" in the + * following shall be construed to mean the GNU Lesser General Public + * License version 2.1 only. However, the following notice accompanied + * the original version of this file: + * + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Dr Vipul Gupta 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. +*/ +#define RNG_GenerateGlobalRandomBytes(p,l) SECFailure +#endif +#define CHECK_MPI_OK(func) if (MP_OKAY > (err = func)) goto cleanup +#define MP_TO_SEC_ERROR(err) + +#define SECITEM_TO_MPINT(it, mp) \ + CHECK_MPI_OK(mp_read_unsigned_octets((mp), (it).data, (it).len)) + +extern int ecc_knzero_random_generator(uint8_t *, size_t); +extern ulong_t soft_nzero_random_generator(uint8_t *, ulong_t); + +extern SECStatus EC_DecodeParams(const SECItem *, ECParams **, int); +extern SECItem * SECITEM_AllocItem(PRArenaPool *, SECItem *, unsigned int, int); +extern SECStatus SECITEM_CopyItem(PRArenaPool *, SECItem *, const SECItem *, + int); +extern void SECITEM_FreeItem(SECItem *, boolean_t); +/* This function has been modified to accept an array of random bytes */ +extern SECStatus EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey, + const unsigned char* random, int randomlen, int); +/* This function has been modified to accept an array of random bytes */ +extern SECStatus ECDSA_SignDigest(ECPrivateKey *, SECItem *, const SECItem *, + const unsigned char* random, int randomlen, int); +extern SECStatus ECDSA_VerifyDigest(ECPublicKey *, const SECItem *, + const SECItem *, int); +extern SECStatus ECDH_Derive(SECItem *, ECParams *, SECItem *, boolean_t, + SECItem *, int); + +#ifdef __cplusplus +} +#endif + +#endif /* _ECC_IMPL_H */ diff --git a/src/share/native/sun/security/ec/impl/ecdecode.c b/src/share/native/sun/security/ec/impl/ecdecode.c new file mode 100644 index 0000000000000000000000000000000000000000..d610f3b1b5af279c40cf81ff9e75d0046a4807bf --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl-curve.h b/src/share/native/sun/security/ec/impl/ecl-curve.h new file mode 100644 index 0000000000000000000000000000000000000000..bb7f9a7d46600fa39f29e88cb51ccdd0ffa46df4 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl-exp.h b/src/share/native/sun/security/ec/impl/ecl-exp.h new file mode 100644 index 0000000000000000000000000000000000000000..ce9a2cf803ce64cfb6e39a3e44a42997926bc56f --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl-priv.h b/src/share/native/sun/security/ec/impl/ecl-priv.h new file mode 100644 index 0000000000000000000000000000000000000000..12caaf70577959e4e6d14430a1e3226bc19828e6 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl.c b/src/share/native/sun/security/ec/impl/ecl.c new file mode 100644 index 0000000000000000000000000000000000000000..7089a6d0e9d2c043e0a9a0a654ed2aff41a3e8b3 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl.h b/src/share/native/sun/security/ec/impl/ecl.h new file mode 100644 index 0000000000000000000000000000000000000000..9dcdbc677ced32605047b4fc1abe809807713e09 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl_curve.c b/src/share/native/sun/security/ec/impl/ecl_curve.c new file mode 100644 index 0000000000000000000000000000000000000000..d2d2d82291c25ab1238545a47b56d4e4d2b40b5b --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl_gf.c b/src/share/native/sun/security/ec/impl/ecl_gf.c new file mode 100644 index 0000000000000000000000000000000000000000..a651fa84e7c220a07e5049355a00634e9f171bc7 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecl_mult.c b/src/share/native/sun/security/ec/impl/ecl_mult.c new file mode 100644 index 0000000000000000000000000000000000000000..c5a01fabad328f3812cbcd81fa9097c11337b776 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp.h b/src/share/native/sun/security/ec/impl/ecp.h new file mode 100644 index 0000000000000000000000000000000000000000..5e045ba63201babbdfd271ea3095846e3c20aec3 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_192.c b/src/share/native/sun/security/ec/impl/ecp_192.c new file mode 100644 index 0000000000000000000000000000000000000000..f2c62a40e909014b2cb25641ebbf675535ce0dbd --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_224.c b/src/share/native/sun/security/ec/impl/ecp_224.c new file mode 100644 index 0000000000000000000000000000000000000000..1ea82fd78d749a8ba1e6ec2211eaf1f27de75f93 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_256.c b/src/share/native/sun/security/ec/impl/ecp_256.c new file mode 100644 index 0000000000000000000000000000000000000000..6f4de5be0ee46e6c17b308fdf579fe7b5fb82662 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_384.c b/src/share/native/sun/security/ec/impl/ecp_384.c new file mode 100644 index 0000000000000000000000000000000000000000..93b9259da6ba77105ba168c84eeaa858f235cb72 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_521.c b/src/share/native/sun/security/ec/impl/ecp_521.c new file mode 100644 index 0000000000000000000000000000000000000000..68dca16a77429091ec12219a00faa4624af27a42 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_aff.c b/src/share/native/sun/security/ec/impl/ecp_aff.c new file mode 100644 index 0000000000000000000000000000000000000000..f8d88d4dcbc5a201510524f858f7c3b4938bd751 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_jac.c b/src/share/native/sun/security/ec/impl/ecp_jac.c new file mode 100644 index 0000000000000000000000000000000000000000..47c0e195dc16abb84044c9368cef470f3d554916 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_jm.c b/src/share/native/sun/security/ec/impl/ecp_jm.c new file mode 100644 index 0000000000000000000000000000000000000000..a5e38db21da2eeab76181b672de1a123b0da6bdf --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/ecp_mont.c b/src/share/native/sun/security/ec/impl/ecp_mont.c new file mode 100644 index 0000000000000000000000000000000000000000..6b4dbb29e25c95e960853eafab736ee4dfaae547 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/logtab.h b/src/share/native/sun/security/ec/impl/logtab.h new file mode 100644 index 0000000000000000000000000000000000000000..6efa01995600c937a2c7f688f2a617b2d9859bf3 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mp_gf2m-priv.h b/src/share/native/sun/security/ec/impl/mp_gf2m-priv.h new file mode 100644 index 0000000000000000000000000000000000000000..7a4505807fc73370dbd356eefc2ed0409dffe734 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mp_gf2m.c b/src/share/native/sun/security/ec/impl/mp_gf2m.c new file mode 100644 index 0000000000000000000000000000000000000000..74b64789c96be78da9ff2d06179fd2d23df5dce2 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mp_gf2m.h b/src/share/native/sun/security/ec/impl/mp_gf2m.h new file mode 100644 index 0000000000000000000000000000000000000000..b09f3d343771eecc179ad89faa68317842243ff3 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mpi-config.h b/src/share/native/sun/security/ec/impl/mpi-config.h new file mode 100644 index 0000000000000000000000000000000000000000..3618677a90aab2b77b40f1d62effd00cd781587d --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mpi-priv.h b/src/share/native/sun/security/ec/impl/mpi-priv.h new file mode 100644 index 0000000000000000000000000000000000000000..b2b07ec32108a7f8078adbb8db613d81089e4cb7 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mpi.c b/src/share/native/sun/security/ec/impl/mpi.c new file mode 100644 index 0000000000000000000000000000000000000000..9f771882b015040c6c571fd7676ea4902c300c94 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mpi.h b/src/share/native/sun/security/ec/impl/mpi.h new file mode 100644 index 0000000000000000000000000000000000000000..5f70b763209b1c1e5427c2dd664f3ad270d86d97 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mplogic.c b/src/share/native/sun/security/ec/impl/mplogic.c new file mode 100644 index 0000000000000000000000000000000000000000..6a5f00a1c36e525908cd793c55aa63f9eb78d051 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mplogic.h b/src/share/native/sun/security/ec/impl/mplogic.h new file mode 100644 index 0000000000000000000000000000000000000000..97ddb49c7ea8d73be860690a455e2bcc346f6e94 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mpmontg.c b/src/share/native/sun/security/ec/impl/mpmontg.c new file mode 100644 index 0000000000000000000000000000000000000000..df17f42732163e24f2ac984ebde9e0894c774be9 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/mpprime.h b/src/share/native/sun/security/ec/impl/mpprime.h new file mode 100644 index 0000000000000000000000000000000000000000..78bcb18352ab42a78811360216d2961ac02b686a --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/oid.c b/src/share/native/sun/security/ec/impl/oid.c new file mode 100644 index 0000000000000000000000000000000000000000..f3ced99bcb529472e9b751f40b6b69082a523d63 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/secitem.c b/src/share/native/sun/security/ec/impl/secitem.c new file mode 100644 index 0000000000000000000000000000000000000000..d9daacc8bc412d58a181024eca6e933c130804df --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/share/native/sun/security/ec/impl/secoidt.h b/src/share/native/sun/security/ec/impl/secoidt.h new file mode 100644 index 0000000000000000000000000000000000000000..0935388cdb8e1f093fce9cd2dd67e1f6949931d8 --- /dev/null +++ b/src/share/native/sun/security/ec/impl/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/src/solaris/bin/java_md.c b/src/solaris/bin/java_md.c index 2e574ec2cec5d4638486054fc006dba71d71e7a0..73efc1090fddb70c1e82ef639f8bcf9cef8ebe76 100644 --- a/src/solaris/bin/java_md.c +++ b/src/solaris/bin/java_md.c @@ -1324,12 +1324,12 @@ FindBootStrapClass(JNIEnv *env, const char* classname) { if (findBootClass == NULL) { findBootClass = (FindClassFromBootLoader_t *)dlsym(RTLD_DEFAULT, - "JVM_FindClassFromClassLoader"); + "JVM_FindClassFromBootLoader"); if (findBootClass == NULL) { JLI_ReportErrorMessage(DLL_ERROR4, - "JVM_FindClassFromClassLoader"); + "JVM_FindClassFromBootLoader"); return NULL; } } - return findBootClass(env, classname, JNI_FALSE, (jobject)NULL, JNI_FALSE); + return findBootClass(env, classname); } diff --git a/src/solaris/classes/sun/net/www/protocol/http/NTLMAuthentication.java b/src/solaris/classes/sun/net/www/protocol/http/NTLMAuthentication.java index 5abd79ed9ef4b8501ca98f2628798c8b0c0a278d..07899928f42a414d100bc339008263d674169c7f 100644 --- a/src/solaris/classes/sun/net/www/protocol/http/NTLMAuthentication.java +++ b/src/solaris/classes/sun/net/www/protocol/http/NTLMAuthentication.java @@ -25,18 +25,23 @@ package sun.net.www.protocol.http; -import java.util.Arrays; -import java.util.StringTokenizer; -import java.util.Random; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.InetAddress; +import java.net.PasswordAuthentication; +import java.net.UnknownHostException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.DESKeySpec; import sun.net.www.HeaderParser; -import java.io.*; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.security.*; -import java.net.*; - /** * NTLMAuthentication: * @@ -66,8 +71,6 @@ import java.net.*; class NTLMAuthentication extends AuthenticationInfo { private static final long serialVersionUID = -2403849171106437142L; - static char NTLM_AUTH = 'N'; - private byte[] type1; private byte[] type3; @@ -142,7 +145,10 @@ class NTLMAuthentication extends AuthenticationInfo { * from a system property: "http.auth.ntlm.domain". */ public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH, url, ""); + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, + AuthScheme.NTLM, + url, + ""); init (pw); } @@ -166,7 +172,11 @@ class NTLMAuthentication extends AuthenticationInfo { */ public NTLMAuthentication(boolean isProxy, String host, int port, PasswordAuthentication pw) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH,host, port, ""); + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, + AuthScheme.NTLM, + host, + port, + ""); init (pw); } diff --git a/src/windows/bin/java_md.c b/src/windows/bin/java_md.c index df5e6988c5e592ea84d83259b0e491f6fa4bb29d..a4fa4ccd63a122dbd85ce15b9c063c573a6e31ec 100644 --- a/src/windows/bin/java_md.c +++ b/src/windows/bin/java_md.c @@ -1093,12 +1093,6 @@ void SetJavaLauncherPlatformProps() {} */ static FindClassFromBootLoader_t *findBootClass = NULL; -#ifdef _M_AMD64 -#define JVM_BCLOADER "JVM_FindClassFromClassLoader" -#else -#define JVM_BCLOADER "_JVM_FindClassFromClassLoader@20" -#endif /* _M_AMD64 */ - jclass FindBootStrapClass(JNIEnv *env, const char *classname) { HMODULE hJvm; @@ -1108,13 +1102,13 @@ jclass FindBootStrapClass(JNIEnv *env, const char *classname) if (hJvm == NULL) return NULL; /* need to use the demangled entry point */ findBootClass = (FindClassFromBootLoader_t *)GetProcAddress(hJvm, - JVM_BCLOADER); + "JVM_FindClassFromBootLoader"); if (findBootClass == NULL) { - JLI_ReportErrorMessage(DLL_ERROR4, JVM_BCLOADER); + JLI_ReportErrorMessage(DLL_ERROR4, "JVM_FindClassFromBootLoader"); return NULL; } } - return findBootClass(env, classname, JNI_FALSE, (jobject)NULL, JNI_FALSE); + return findBootClass(env, classname); } void diff --git a/src/windows/classes/java/util/prefs/WindowsPreferences.java b/src/windows/classes/java/util/prefs/WindowsPreferences.java index b9ee8f49b283bd4e9d278582cb522401cd235d5e..c9034277360e915d36c3e384d006ff32a1ab9a7a 100644 --- a/src/windows/classes/java/util/prefs/WindowsPreferences.java +++ b/src/windows/classes/java/util/prefs/WindowsPreferences.java @@ -29,7 +29,7 @@ import java.util.Map; import java.util.TreeMap; import java.util.StringTokenizer; import java.io.ByteArrayOutputStream; -import java.util.logging.Logger; +import sun.util.logging.PlatformLogger; /** * Windows registry based implementation of Preferences. @@ -48,7 +48,7 @@ class WindowsPreferences extends AbstractPreferences{ /** * Logger for error messages */ - private static Logger logger; + private static PlatformLogger logger; /** * Windows registry path to Preferences's root nodes. @@ -1102,9 +1102,9 @@ class WindowsPreferences extends AbstractPreferences{ // assert false; } - private static synchronized Logger logger() { + private static synchronized PlatformLogger logger() { if (logger == null) { - logger = Logger.getLogger("java.util.prefs"); + logger = PlatformLogger.getLogger("java.util.prefs"); } return logger; } diff --git a/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java b/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java index a4334b42f12b9e7fc310ea121356116a94a50899..788a4d0ff21d6e99cd9150510f3baf39cec6cb5e 100644 --- a/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java +++ b/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java @@ -67,6 +67,9 @@ public class D3DGraphicsDevice extends Win32GraphicsDevice { if (d3dAvailable) { // we don't use pixel formats for the d3d pipeline pfDisabled = true; + sun.misc.PerfCounter.getD3DAvailable().set(1); + } else { + sun.misc.PerfCounter.getD3DAvailable().set(0); } } diff --git a/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java b/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java index 12ffdf402ffbc941ec4b07d23dc520336caa047d..e14381f9ce59c77b1854d07c9da36c4f6afac03e 100644 --- a/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java +++ b/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java @@ -25,18 +25,13 @@ package sun.net.www.protocol.http; -import java.util.Arrays; -import java.util.StringTokenizer; -import java.util.Random; - +import java.io.IOException; +import java.net.InetAddress; +import java.net.PasswordAuthentication; +import java.net.UnknownHostException; +import java.net.URL; import sun.net.www.HeaderParser; -import java.io.*; -import javax.crypto.*; -import javax.crypto.spec.*; -import java.security.*; -import java.net.*; - /** * NTLMAuthentication: * @@ -47,7 +42,6 @@ class NTLMAuthentication extends AuthenticationInfo { private static final long serialVersionUID = 100L; - static final char NTLM_AUTH = 'N'; private String hostname; private static String defaultDomain; /* Domain to use if not specified by user */ @@ -88,7 +82,10 @@ class NTLMAuthentication extends AuthenticationInfo { * from a system property: "http.auth.ntlm.domain". */ public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH, url, ""); + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION, + AuthScheme.NTLM, + url, + ""); init (pw); } @@ -119,7 +116,11 @@ class NTLMAuthentication extends AuthenticationInfo { */ public NTLMAuthentication(boolean isProxy, String host, int port, PasswordAuthentication pw) { - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, NTLM_AUTH,host, port, ""); + super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION, + AuthScheme.NTLM, + host, + port, + ""); init (pw); } diff --git a/test/com/sun/jdi/BreakpointWithFullGC.sh b/test/com/sun/jdi/BreakpointWithFullGC.sh new file mode 100644 index 0000000000000000000000000000000000000000..74106760c7935e109c8dafabdc13b174cb240cde --- /dev/null +++ b/test/com/sun/jdi/BreakpointWithFullGC.sh @@ -0,0 +1,128 @@ +#!/bin/sh + +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + +# @test +# @bug 6862295 +# @summary Verify breakpoints still work after a full GC. +# @author dcubed (based on the test program posted to the following +# Eclipse thread https://bugs.eclipse.org/bugs/show_bug.cgi?id=279137) +# +# @run shell BreakpointWithFullGC.sh + +compileOptions=-g +# Hijacking the mode parameter to make sure we use a small amount +# of memory and can see what GC is doing. +mode="-Xmx32m -verbose:gc" +# Force use of a GC framework collector to see the original failure. +#mode="$mode -XX:+UseSerialGC" + +# Uncomment this to see the JDI trace +#jdbOptions=-dbgtrace + +createJavaFile() +{ + cat < $1.java.1 + +import java.util.ArrayList; +import java.util.List; + +public class $1 { + public static List objList = new ArrayList(); + + private static void init(int numObjs) { + for (int i = 0; i < numObjs; i++) { + objList.add(new Object()); + } + } + + public static void main(String[] args) { + for (int i = 0; i < 10; i++) { + System.out.println("top of loop"); // @1 breakpoint + init(1000000); + objList.clear(); + System.out.println("bottom of loop"); // @1 breakpoint + } + System.out.println("end of test"); // @1 breakpoint + } +} + +EOF +} + +# This is called to feed cmds to jdb. +dojdbCmds() +{ + setBkpts @1 + + # get to the first loop breakpoint + runToBkpt + # 19 "cont" commands gets us through all the loop breakpoints. + # Use for-loop instead of while-loop to avoid creating processes + # for '[' and 'expr'. + for ii in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19; do + contToBkpt + done + # get to the last breakpoint + contToBkpt +} + + +mysetup() +{ + if [ -z "$TESTSRC" ] ; then + TESTSRC=. + fi + + for ii in . $TESTSRC $TESTSRC/.. ; do + if [ -r "$ii/ShellScaffold.sh" ] ; then + . $ii/ShellScaffold.sh + break + fi + done +} + +# You could replace this next line with the contents +# of ShellScaffold.sh and this script will run just the same. +mysetup + +runit + +# make sure we hit the first breakpoint at least once +jdbFailIfNotPresent 'System\..*top of loop' + +# make sure we hit the second breakpoint at least once +jdbFailIfNotPresent 'System\..*bottom of loop' + +# make sure we hit the last breakpoint +jdbFailIfNotPresent 'System\..*end of test' + +# make sure we had at least one full GC +debuggeeFailIfNotPresent 'Full GC' + +# check for error message due to thread ID change +debuggeeFailIfPresent \ + 'Exception in thread "event-handler" java.lang.NullPointerException' + +pass diff --git a/test/java/lang/ProcessBuilder/Basic.java b/test/java/lang/ProcessBuilder/Basic.java index 745fab468b9d4376a2b5362422900c8a025e089a..afb8ea8210e92b7bb8d6d26f3675ea5ee7a18528 100644 --- a/test/java/lang/ProcessBuilder/Basic.java +++ b/test/java/lang/ProcessBuilder/Basic.java @@ -25,7 +25,7 @@ * @test * @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689 * 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313 - * 6464154 6523983 6206031 4960438 6631352 6631966 + * 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958 * @summary Basic tests for Process and Environment Variable code * @run main/othervm Basic * @author Martin Buchholz @@ -302,6 +302,14 @@ public class Basic { printUTF8(val == null ? "null" : val); } else if (action.equals("System.getenv()")) { printUTF8(getenvAsString(System.getenv())); + } else if (action.equals("ArrayOOME")) { + Object dummy; + switch(new Random().nextInt(3)) { + case 0: dummy = new Integer[Integer.MAX_VALUE]; break; + case 1: dummy = new double[Integer.MAX_VALUE]; break; + case 2: dummy = new byte[Integer.MAX_VALUE][]; break; + default: throw new InternalError(); + } } else if (action.equals("pwd")) { printUTF8(new File(System.getProperty("user.dir")) .getCanonicalPath()); @@ -1472,6 +1480,22 @@ public class Basic { } } catch (Throwable t) { unexpected(t); } + //---------------------------------------------------------------- + // OOME in child allocating maximally sized array + // Test for hotspot/jvmti bug 6850957 + //---------------------------------------------------------------- + try { + List list = new ArrayList(javaChildArgs); + list.add(1, String.format("-XX:OnOutOfMemoryError=%s -version", + javaExe)); + list.add("ArrayOOME"); + ProcessResults r = run(new ProcessBuilder(list)); + check(r.out().contains("java.lang.OutOfMemoryError:")); + check(r.out().contains(javaExe)); + check(r.err().contains(System.getProperty("java.version"))); + equal(r.exitValue(), 1); + } catch (Throwable t) { unexpected(t); } + //---------------------------------------------------------------- // Windows has tricky semi-case-insensitive semantics //---------------------------------------------------------------- diff --git a/test/java/net/ProxySelector/B6737819.java b/test/java/net/ProxySelector/B6737819.java new file mode 100644 index 0000000000000000000000000000000000000000..360f1ae4aefe24e0d101ea283a6eeaefe09f5ecd --- /dev/null +++ b/test/java/net/ProxySelector/B6737819.java @@ -0,0 +1,63 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ +/* + * @test + * @bug 6737819 + * @summary sun.misc.net.DefaultProxySelector doesn't use proxy setting to localhost + */ + +import java.net.ProxySelector; +import java.net.Proxy; +import java.net.URI; + +public class B6737819 { + private static String[] uris = { + "http://localhost/index.html", + "http://127.0.0.1/index.html", + "http://127.2/index.html", + "http://[::1]/index.html" + }; + public static void main(String[] args) throws Exception { + System.setProperty("http.proxyHost", "myproxy"); + System.setProperty("http.proxyPort", "8080"); + ProxySelector sel = ProxySelector.getDefault(); + java.util.List l; + // Default value for http.nonProxyHots should exclude all this uris + // from going through the HTTP proxy + for (String s : uris) { + l = sel.select(new URI(s)); + if (l.size() == 1 && l.get(0).type() != Proxy.Type.DIRECT) { + throw new RuntimeException("ProxySelector returned the wrong proxy for " + s); + } + } + // Let's override the default nonProxyHosts and make sure we now get a + // HTTP proxy + System.setProperty("http.nonProxyHosts", ""); + for (String s : uris) { + l = sel.select(new URI(s)); + if (l.size() == 1 && l.get(0).type() != Proxy.Type.HTTP) { + throw new RuntimeException("ProxySelector returned the wrong proxy for " + s); + } + } + } +} diff --git a/test/java/nio/file/Files/WalkWithSecurity.java b/test/java/nio/file/Files/WalkWithSecurity.java new file mode 100644 index 0000000000000000000000000000000000000000..5b2ab56447426f6ba81c3467fe45692540d24f20 --- /dev/null +++ b/test/java/nio/file/Files/WalkWithSecurity.java @@ -0,0 +1,132 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* @test + * @bug 6876541 + * @summary Test Files.walkFileTree in the presence of a security manager + * @build WalkWithSecurity + * @run main/othervm WalkWithSecurity grantAll.policy pass + * @run main/othervm WalkWithSecurity denyAll.policy fail + * @run main/othervm WalkWithSecurity grantTopOnly.policy top_only + */ + +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; +import java.io.IOException; + +public class WalkWithSecurity { + + public static void main(String[] args) throws IOException { + String policyFile = args[0]; + ExpectedResult expectedResult = ExpectedResult.valueOf(args[1].toUpperCase()); + + String here = System.getProperty("user.dir"); + String testSrc = System.getProperty("test.src"); + if (testSrc == null) + throw new RuntimeException("This test must be run by jtreg"); + Path dir = Paths.get(testSrc); + + // Sanity check the environment + if (Paths.get(here).isSameFile(dir)) + throw new RuntimeException("Working directory cannot be " + dir); + DirectoryStream stream = dir.newDirectoryStream(); + try { + if (!stream.iterator().hasNext()) + throw new RuntimeException(testSrc + " is empty"); + } finally { + stream.close(); + } + + // Install security manager with the given policy file + System.setProperty("java.security.policy", + dir.resolve(policyFile).toString()); + System.setSecurityManager(new SecurityManager()); + + // Walk the source tree + CountingVisitor visitor = new CountingVisitor(); + SecurityException exception = null; + try { + Files.walkFileTree(dir, visitor); + } catch (SecurityException se) { + exception = se; + } + + // Check result + switch (expectedResult) { + case PASS: + if (exception != null) { + exception.printStackTrace(); + throw new RuntimeException("SecurityException not expected"); + } + if (visitor.count() == 0) + throw new RuntimeException("No files visited"); + break; + case FAIL: + if (exception == null) + throw new RuntimeException("SecurityException expected"); + if (visitor.count() > 0) + throw new RuntimeException("Files were visited"); + break; + case TOP_ONLY: + if (exception != null) { + exception.printStackTrace(); + throw new RuntimeException("SecurityException not expected"); + } + if (visitor.count() == 0) + throw new RuntimeException("Starting file not visited"); + if (visitor.count() > 1) + throw new RuntimeException("More than starting file visited"); + break; + default: + throw new RuntimeException("Should not get here"); + } + } + + static enum ExpectedResult { + PASS, + FAIL, + TOP_ONLY; + } + + static class CountingVisitor extends SimpleFileVisitor { + private int count; + + int count() { + return count; + } + + @Override + public FileVisitResult preVisitDirectory(Path dir) { + System.out.println(dir); + count++; + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + System.out.println(file); + count++; + return FileVisitResult.CONTINUE; + } + } +} diff --git a/test/java/nio/file/Files/denyAll.policy b/test/java/nio/file/Files/denyAll.policy new file mode 100644 index 0000000000000000000000000000000000000000..32500947791001ea25267a6f5c54d95ec0075172 --- /dev/null +++ b/test/java/nio/file/Files/denyAll.policy @@ -0,0 +1,3 @@ +// policy file that does not grant any permissions +grant { +}; diff --git a/test/java/nio/file/Files/grantAll.policy b/test/java/nio/file/Files/grantAll.policy new file mode 100644 index 0000000000000000000000000000000000000000..85bc0d0fb51f23eea23c226cb8a1f7f79af92901 --- /dev/null +++ b/test/java/nio/file/Files/grantAll.policy @@ -0,0 +1,5 @@ +// policy file that grants read access to source directory and all descendants +grant { + permission java.io.FilePermission "${test.src}", "read"; + permission java.io.FilePermission "${test.src}${file.separator}-", "read"; +}; diff --git a/test/java/nio/file/Files/grantTopOnly.policy b/test/java/nio/file/Files/grantTopOnly.policy new file mode 100644 index 0000000000000000000000000000000000000000..fca1539416feb5a502dfacbff39fe0bc7e14a763 --- /dev/null +++ b/test/java/nio/file/Files/grantTopOnly.policy @@ -0,0 +1,4 @@ +// policy file that grants read access to source directory +grant { + permission java.io.FilePermission "${test.src}", "read"; +}; diff --git a/test/sun/security/ec/TestEC.java b/test/sun/security/ec/TestEC.java index 12694a03c649fbd2e3ac1a1b2bec8c94cf6abc63..5429e51394a7e8150b4a7afe2cdd9e5bd5197458 100644 --- a/test/sun/security/ec/TestEC.java +++ b/test/sun/security/ec/TestEC.java @@ -27,6 +27,8 @@ * @summary Provide out-of-the-box support for ECC algorithms * @library ../pkcs11 * @library ../pkcs11/ec + * @library ../pkcs11/sslecc + * @compile -XDignore.symbol.file TestEC.java * @run main TestEC */ @@ -35,12 +37,15 @@ 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 + * NOTE: the following 6 files were copied here from the PKCS11 EC Test area * and must be kept in sync with the originals: * * ../pkcs11/ec/p12passwords.txt + * ../pkcs11/ec/certs/sunlabscerts.pem * ../pkcs11/ec/pkcs12/secp256r1server-secp384r1ca.p12 * ../pkcs11/ec/pkcs12/sect193r1server-rsa1024ca.p12 + * ../pkcs11/sslecc/keystore + * ../pkcs11/sslecc/truststore */ public class TestEC { @@ -49,18 +54,23 @@ public class TestEC { Provider p = new sun.security.ec.SunEC(); System.out.println("Running tests with " + p.getName() + " provider...\n"); - long start = System.currentTimeMillis(); + + /* + * The entry point used for each test is its instance method + * called main (not its static method called main). + */ new TestECDH().main(p); new TestECDSA().main(p); new TestCurves().main(p); new TestKeyFactory().main(p); new TestECGenSpec().main(p); new ReadPKCS12().main(p); - //new ReadCertificates().main(p); - long stop = System.currentTimeMillis(); + new ReadCertificates().main(p); + new ClientJSSEServerJSSE().main(p); + long stop = System.currentTimeMillis(); System.out.println("\nCompleted tests with " + p.getName() + - " provider (" + (stop - start) + " ms)."); + " provider (" + ((stop - start) / 1000.0) + " seconds)."); } } diff --git a/test/sun/security/ec/certs/sunlabscerts.pem b/test/sun/security/ec/certs/sunlabscerts.pem new file mode 100644 index 0000000000000000000000000000000000000000..5dfb352408a8d12cface9f80b043cc532b34b443 --- /dev/null +++ b/test/sun/security/ec/certs/sunlabscerts.pem @@ -0,0 +1,1317 @@ +-----BEGIN CERTIFICATE----- +MIIDyDCCAzGgAwIBAgIJAJh6e4zfP9lXMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAk +BgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMR8wHQYDVQQLDBZU +ZXN0IFNlcnZlciAoUlNBIDEwMjQpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFs +c3R1ZmYuY29tMB4XDTA1MTIwNjIxMjk1OFoXDTEwMDExNDIxMjk1OFowgZ8xCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEm +MCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHzAdBgNVBAsM +FlRlc3QgU2VydmVyIChSU0EgMTAyNCkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50 +YWxzdHVmZi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJrKL3D9xOca +b5C5m1yeIFXvwufm5m06RnQdLWaj5Epg9+6tM3uZNn9B0r4k7MKYPbzBqyQO9ZSm +sulV9U3nWLhjChOrrNCIxzAUIR1//11QVKfjv3k8Ts7N5g5kIIiG8GUXh1WCNYhN +SvPo0BpNJ3FFwMMCZu0VpAP0j9krqWjfAgMBAAGjggEIMIIBBDAdBgNVHQ4EFgQU +FrXN7dxlrB1ccI0ZOi+NzYpz6UIwgdQGA1UdIwSBzDCByYAUFrXN7dxlrB1ccI0Z +Oi+NzYpz6UKhgaWkgaIwgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQG +A1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBM +YWJvcmF0b3JpZXMxHzAdBgNVBAsMFlRlc3QgU2VydmVyIChSU0EgMTAyNCkxIjAg +BgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5jb22CCQCYenuM3z/ZVzAMBgNV +HRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAAEQHmeWmoe+s784Qi1oK04eNeI3 +m3Iw06IWjdKH5xatQqj9VjvngLWnmY26PYlF6PK3cAktuempXVA2rZ3Dv5pkgAdQ +f3LXGHBKfAEsSjSSpxIsQA6Q+Yk7zqht5hSPOtUXHcWUx9EMvh7HnjmEEdR80fw/ +txvN4xm8V+flmK/T +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICxjCCAi8CCQCg3U8Mc7XCZzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwNTlaFw0xMDAxMTQyMTMwNTlaMIGuMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0 +IFNlcnZlciAocnNhMTAyNHNlcnZlci1yc2ExMDI0Y2EpMSIwIAYDVQQDDBlkZXYu +ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQCZCOorl//TxbVdj8X+fb9xhMlApe9sAU/jlHRtrv+7FflqCLMmhcR8s90LTCjq +gcX0mGm7fIusBff4/hjaKlmrto0YLNg8c8Zvev5CD+0HQHtbGUfx3TGOHv7gvG31 +nt88ZOzyIlPe2khcDTmb613zxFZhgJBs3bCsQz0TK3bR/wIDAQABMA0GCSqGSIb3 +DQEBBQUAA4GBABHP8xO3ouLm6SgZefjJnmbURTpjosE7oR15T1Fpf6o0WARaTeYO +07H/GdDFUgV3RTA/zNMimfq6XqJB5r5WBziVkLLuixzS7nNaAci6o5b2UaU7shUc +z3k0O4Dclybb4J1dYeAIwXUGqLAzI1NCgjRoGirFWT+O+02tT1KCiSl3 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDRzCCAi8CCQCg3U8Mc7XCaDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMxMDBaFw0xMDAxMTQyMTMxMDBaMIGuMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0 +IFNlcnZlciAocnNhMTAyNHNlcnZlci1yc2EyMDQ4Y2EpMSIwIAYDVQQDDBlkZXYu +ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB +gQC5EyeXl7YTi5NPgJiIZHNSrG9qlAVoM5BYKqAVtFwHCbLYB7ZWyN2BuEfUSf8p +KSKkq28DkNTqnyz6Rg57kHzO3+kca0+iHlqFpbcP6uuN4ubOGZCuEDT0Ti7VXRtc +a8hGNrOEzZKA6DCl9csfrN0jHB5VBfJ4qTJCEi8fXNQbzwIDAQABMA0GCSqGSIb3 +DQEBBQUAA4IBAQC05575dPOqJ6Qk2rs7wHu4tGE15OR2jnXSZXXDObRUHetykmfQ +YbUq9/z9f3k4R53GAisgDwbVUb3EUsXofy7eMTUD89A7MiZ99SvebPilDQE3djqM +D0uA9a96LG6fAarc1MdpbMPcFiFFiwwlqJVtx4TNlektFbFQRzrrbMSF/ISLzdWK +fR3XD5qpwiCQbSug9Zm7cornUk8cK/Fs571wErOrdPo47aw1C8NjspLhux/JtHM9 +hNuAqona/4lX5lMVNpnSkWaT+B281+ysm1uEK8lvsDSUuLy+fZvokCrhQPFLoI+h +l5HGNqXdyIu1POCl6yqd6+BKNnfA5Qy+Bp87 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICbDCCAioCCQCg3U8Mc7XCYTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA0OVoXDTEwMDExNDIxMzA0OVowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2ExMDI0c2VydmVyLXNlY3AxNjByMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAyvWS +/5LJKlEJNR+jEWB1VMQVC09227El9V80yZ8WYqL0RdvWvDHN/vN1HKlFni/X5pwK +Def0vpXEDueeUgs9nQd+WDI/HOHTZ6BwUu2x2JParIBm9+dylWiBqhV+9LI/TyIr +4KMKjcnTMlCKZvzrIplIvcf+Gu/OFG46q3PUIFcCAwEAATAJBgcqhkjOPQQBAzEA +MC4CFQCslg/BEN7fygz0CIIWO+1n/yenNwIVAMivW2BhQhk1TEPw5Zs3QgXEw187 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIChDCCAioCCQCg3U8Mc7XCYjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA1MVoXDTEwMDExNDIxMzA1MVowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2ExMDI0c2VydmVyLXNlY3AyNTZyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5v3h +NBYB07K2o8TMStAW5j5qDfy1XciU6Hx32qeoPwBdsvalmiAP+Scawfi7xPWGCMTK +zBiRSRHVgFU+tsvpFhJ+7mnl0k7zQMdmuzJCH/IV8889TAobQbGsvSdMa5ry+FRo +u+2QoEAaOQik4RFZcZmw+46wbMbeNhesirEkG20CAwEAATAJBgcqhkjOPQQBA0kA +MEYCIQCMTGl7AImRhjsdQuEUaODQKFWGcZSFT0ZVe+ikWQCdcQIhANOPoSjaBDHa +kJVhR6MrTMHvnfAGL+EZpAqHGPMM12JD +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICpDCCAioCCQCg3U8Mc7XCYzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA1MloXDTEwMDExNDIxMzA1MlowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2ExMDI0c2VydmVyLXNlY3AzODRyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArsTW +yLsCTz6nEeBEHW1JvMFPFnFqvXWWJJsEHbJtPDU0FF3xurgfNX4T7BsPW5LNIneh +MJbKqSCRgw0q97zgVLhB1WBE6y5jkfYCTDA5QAuNOlqgTGrBg0WIANgsXjHFZ5kQ +46i98IzFOFHZFOdtj+i0T3GviZWKGCbjKShyWnMCAwEAATAJBgcqhkjOPQQBA2kA +MGYCMQD4L6X8M2oCiwQE0/HqNNI4zCt6gp2o8Uk2HWa5If59QhwlfjXQSdbvVGfW +T2XpnUACMQDJ6Ir8G4H9Mu9ktf64MhnYg6A22hV4nWZ5bpM3AiD+10q+30r+TWV4 +89YQz707Eok= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICyDCCAioCCQCg3U8Mc7XCZDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA1NFoXDTEwMDExNDIxMzA1NFowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2ExMDI0c2VydmVyLXNlY3A1MjFyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1Nmx +2TOGk8FQXJIzDM2+x4jVWocD2lRShsFQaMhltST4PWm+TbXBPSxpvS9oFW7eZE3J +50OqxMiZkmH8un44Iet7E6fi0iRhw0bl4uqG2JHtyMzSYR6niSy0yqgHVJVwM24Q +Z/39X17PD0NwCEiPBGFx9Xa5E2JP9KcnCbrj49sCAwEAATAJBgcqhkjOPQQBA4GM +ADCBiAJCAZ4Apzk6L7BLjKoln+NEl5a/I1TmNIPVR0HtcLwbdZQ/y9b0+vhENkkS +XIGTc/2Jx+OV/tc4JyNW7PNM/YPl5FDUAkIByKevbRtsBD0HuCVK6WOf+6uz+QFs +fgxz0XoMyWMuoUIM2ytx+Eq9UY13QgqCQ5FxYWJ6RtDiNhEovr5GMjqjG0Q= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICbDCCAioCCQCg3U8Mc7XCZTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA1NVoXDTEwMDExNDIxMzA1NVowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2ExMDI0c2VydmVyLXNlY3QxNjNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAy4Vh +Ju/NaZEhiu6wsh4fsKGvwdHwRKvmJwMk8wEk3/Vz92/9kPR5B/Co3XVGBmW4UJwD +0BcdPcMyr1TDHYOL7kS65MJGq0eFcBblA5hr2G3unZwgVwpS9GzMA7n8s3BtDGYN +UpUyt5u5C6mTqQoK39xVWWbke5tM90T3jr6MiN0CAwEAATAJBgcqhkjOPQQBAzEA +MC4CFQOcO1rEZFieKqpNL8E8T1wwchv2FQIVAQ4DEcV2AkLqSXxgt+h03NyWPeEN +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICcjCCAioCCQCg3U8Mc7XCZjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA1N1oXDTEwMDExNDIxMzA1N1owgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2ExMDI0c2VydmVyLXNlY3QxOTNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAws4d +5PHRj1UOeuc60MnkGhmwJ/RD7Vmaq8NUJwliTHnAscTlZuv5Irv9cYHhAka2p8WJ +mo8xZxlUQMIUxIx/9ocZEYAKrv/vjWo05iaDQowJOUHM77usJnTZbDrVfeuOBqFo +6G2scl6RBGdCUOGUBVdRT6sEWQnYm/wIcTxj9OcCAwEAATAJBgcqhkjOPQQBAzcA +MDQCGHDRiFsRMDB+Y4+Mnjs4jWHHKyjqoOYFlwIYemZsC0uC1/oI/ZFUuERW7TEe +BPpqMQgX +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICyzCCAjQCCQClVpDHKllBjTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcGA1UECwwgVGVzdCBT +ZXJ2ZXIgKHJzYTEwMjRzZXJ2ZXItc2VsZikxIjAgBgNVBAMMGWRldi5leHBlcmlt +ZW50YWxzdHVmZi5jb20wHhcNMDUxMjA2MjEzMTAxWhcNMTAwMTE0MjEzMTAxWjCB +qTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBW +aWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcG +A1UECwwgVGVzdCBTZXJ2ZXIgKHJzYTEwMjRzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A +MIGJAoGBALx55L25d1DjV6X6z/rqebCJvhD0IfWqUU6ekiADnDgmOhFT8gutI4Xh +2AlBhIyticLU5IMP/MYud0OPnavaH3dcNRsfkJkfmZRULqIDjWnVmtmBhV8th9TM +KaH7V1TOqxqMfGuzFq9uwL8p5i2f8fLQjZ9sNNj7qeuW5XI05cv1AgMBAAEwDQYJ +KoZIhvcNAQEFBQADgYEAG3UcMUmwpTKUwNA6P0i0073ptjmzhRIeDdpf1d69X99Y +Wrnf2H6xA2boa8gBkVFjCaLBakIq6px5IuGFZNB2+0yJqd8QE22DKk1Ikr5hBsEC +owhd0feRaNjO0u/kPFZU1XAVFyz2AGKdLUOw4OEV8tuSOXAmWoMZHwfoocy1JnQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEzTCCA7WgAwIBAgIJAMkNhmYP6nKsMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYD +VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAk +BgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMR8wHQYDVQQLDBZU +ZXN0IFNlcnZlciAoUlNBIDIwNDgpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFs +c3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAwOVoXDTEwMDExNDIxMzAwOVowgZ8xCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEm +MCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHzAdBgNVBAsM +FlRlc3QgU2VydmVyIChSU0EgMjA0OCkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50 +YWxzdHVmZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDO/6vZ +zPZAmeKP/fMAwKTRzCmy30TnoEZJybsk8QDlL9xaYIcEiIhf6eOV0/IYPcSwPakv +Ha5lT9aCTEEdcxACqAQlm2LOFZ79pUc0bGEmeFpHDZoO2w7+/RCYbGLkdWKTfj1D +kKG9PoWX5MelBZqkQuvE3+6eAr70IlQRA8uMA+Aq+Hl7KZys+eTX3eVWcNYZu94U +Z9wOKsRnRT4Yzf1G8aPJq4gIwxW4nBVAHqUc2N8bUzsHVqbTpcytU3KYT1YlcLGG +Ir1LulgjWws3Lncx1rZQuAIT5cyjCmW8wZ/O+GewzmbgV95lFsf8HCd0ZD4j65sS +/l0xB4zHnSBAegntAgMBAAGjggEIMIIBBDAdBgNVHQ4EFgQUS1aD1pb8BOGcjSyh +9IhovqLk1TcwgdQGA1UdIwSBzDCByYAUS1aD1pb8BOGcjSyh9IhovqLk1TehgaWk +gaIwgZ8xCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRh +aW4gVmlldzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMx +HzAdBgNVBAsMFlRlc3QgU2VydmVyIChSU0EgMjA0OCkxIjAgBgNVBAMMGWRldi5l +eHBlcmltZW50YWxzdHVmZi5jb22CCQDJDYZmD+pyrDAMBgNVHRMEBTADAQH/MA0G +CSqGSIb3DQEBBQUAA4IBAQBDl6f5HVzv0r0/DNAMy6vaKHrKXCJYVXLh7AZWLShP +3BfvekDRncLFjldTEqE1vqD4wndxpHVVwyZWWBWHVcw76AAtYnZp36ex5ZP56pHw +Mg308O+tYLgjdm5cDEzGzqNgavUIi/T/lMnWJrls1Zr/qnf7hzbvIAlMGJ4jcZGF +U1Z8T4mpFyroafXSbHEE/awX9DbyZL0ryXXtlTggxgLfzPqmSx4ZXurqv4LFdjlu +pZ/+/b6qU3JAlDMDMReb+iDBIllNGVZj88QTp3cC2CtwnYBYvLLWFtWoQpN2Ppz4 +X5xcdh4VuTICpk5kQSbzrij3GXZl0fDVuX4Z+5J1xodl +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSjCCArMCCQCg3U8Mc7XCbzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMyMjlaFw0xMDAxMTQyMTMyMjlaMIGuMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0 +IFNlcnZlciAocnNhMjA0OHNlcnZlci1yc2ExMDI0Y2EpMSIwIAYDVQQDDBlkZXYu +ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEA7I6hIU6+t1DQABGWtaqyhUjieQTzoaN3dZzmzTcUXY62F+IedLuVrxcQ +3YJU8+jcM6rl+/eIa90rNcKpxjrdzx676CqFCHO3/aHF1iCMmQF368ezfs2lDPTF +mobrn6KMNe71SM8bQ8MHFmRxY1wWk7GKIuz8OQnJOHD1nXQisjv1GBZ7HssaEPGd +m8c1rKCvzqrC4Nj/U+cKV0VeWtJod5inIx5RT/5FYW4QdBwuhovoKumPxpImYz6Y +SuFAce2hTMjxmvFXD0V1+VfWsYUe0/TilRgOv5l9iWo4haGBftYFWW8w0iqOB4+q +cPqcKozI7Tjs9r3Rby0zTdjB6vZi9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAAUd +cnt8YHDUvIroDiLQQsH+p2mDD+ra10K3C9H0Lsvt6cb3/2jn6PupFVJzwkEEankS +Lo/pOe+bO5uSA4C2FQAymrYZX5Hh1guK/Has+Sf0K+HKPx28QPGg1EoS2KAbUf1t +RBX2jtq8Suz3iS9u77PbpB7aMNAEBihr2jAyfSka +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDyzCCArMCCQCg3U8Mc7XCcDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMyMzVaFw0xMDAxMTQyMTMyMzVaMIGuMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMS4wLAYDVQQLDCVUZXN0 +IFNlcnZlciAocnNhMjA0OHNlcnZlci1yc2EyMDQ4Y2EpMSIwIAYDVQQDDBlkZXYu +ZXhwZXJpbWVudGFsc3R1ZmYuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAxHxrsAwLznaK+dmgQxUzmWTsNLhuKk+yBkpJZQDQDjkdxVrime1DxPAZ +MDi4OL+9YCIDS3ZWG0uLH49Atq08/2TB+aYDm0YBjrq3BRphTBrNNpntezSgP/nz +R2hOBvBgSvFqorTLzRF9THq18CrSJJB/OPFzvl6mYK8dtS4CnOfdUs0Pv8SwdxhJ +X6qsO0NJclrfBYBodGW1PiY62NPX0h2mLcg4OmD3gThfjUvXnsdjLJYV6hZFT+YC +vPJNTxTGebfnJr4sRGdqRUyBrjiqZtXwGpIBCSg/YpnUOfDSxJNA2Wd/WFJJv8Fq +kBh2oDRqlFNC/Z+HjGqKj0gFowTq3QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBp +iFO+5KbnHfRBStgxZdTBrr+HEezeFlxeE04bM7kSWII2SiQbAWSG5Rkb518m5x65 +q23KqUK+YJiy7k0zoKInvG/qLf1D5osFlwaAll7AKBadn/R8x822xSJCydHgD64V +b3u89zBY5Jtl+EzTA+n+UWRsurlLL1K9ockWZrDiZn6gGO5/ucR8OkZ192sxqKRr +iQbN12LWSmUCYPwba8nvDdm1ymAbnFOg1oQJ9HvxmFI3GaGjdmNo9rlaoNS/xQ35 +iTtJyi1MK2d+O2JPD5cS5otGfFnQiTWIngBiuEoOwzw7x8eWsOQaBPVnNSlMdU+z +Zrc6M1OSOUh2+DqvAoBp +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC8DCCAq4CCQCg3U8Mc7XCaTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzExM1oXDTEwMDExNDIxMzExM1owgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2EyMDQ4c2VydmVyLXNlY3AxNjByMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMPD0turqL6uNjGfquQy3MTv90+RvDCvCQXGnxdJa6QcOOHnv/4ua9g/TOO2cVuc +UuF3EnMSDg+HIo8qJhdKcOa4nnp1IxAnPsQs1K9vq8eqtuSuFMZUoUKy969ThPqd +UTYyZpOn87XMftm76nz92q2gDPLj7ZxD1QOv0MpMHjXJMSRHWEhsoCpYBdFT5Nl5 +28bK0AWTv4nw2RmQryn+UMblAqnJBNiIWzVHBUa1UNMBt2lnO12w6EpSGmkx9+Op +rv8kcfJgXnUkH/l7krHUADplp4yxO1hIzdH5Xsd+Hxrnl85vGjNJyuNOlFJ1Eh0x +AJTT6m1ypPKAs+zF1nWJaJECAwEAATAJBgcqhkjOPQQBAzEAMC4CFQCsQDzAbX4C +uri94k3X0mUTxCrweAIVAON/UYsS+fYp74XS5ucP8I31tl8n +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDCDCCAq4CCQCg3U8Mc7XCajAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzEyOFoXDTEwMDExNDIxMzEyOFowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2EyMDQ4c2VydmVyLXNlY3AyNTZyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALYeH/U234MovGN9iM3mr3kah93WJY64Dg8kGHg4zaUeKSmZVBgj/IlaCbfsRzXp +0xtsBCXAHGlZosiIInQzfxVNS/XIUOI3B5h+n3wMl61BsC2R/pmHyEg8eFp6Jiwv +1HMW9xKYF4qGgH396HczXPxOov3iJvtHHLElzYXDwCqy+x4D1PzXQLEkaGQzXsY4 +xhqskq1qg4pacNvow1eJair9zk5ebrV9t39icdTMkrtwgNBYAM/RU5DBxjdHDb/p +Ef26uOmpEfgopcRpoZlDY7mpBozK49Ocsx+PCAx74A1kj8M2i7s+edlLMxIl66Co ++ELzqZW7YjwtyrOakPNb1m0CAwEAATAJBgcqhkjOPQQBA0kAMEYCIQCwL9kS1Dza +3G7UiC3Hxo2f/kfp9621l8dLV5Uh+yhxagIhAIj28sZe3blr+MkrJHZjkYsAMY1e +JijPcsnXEr0uGamb +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDJzCCAq4CCQCg3U8Mc7XCazAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzE0NloXDTEwMDExNDIxMzE0NlowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2EyMDQ4c2VydmVyLXNlY3AzODRyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AK0JI2U8gdr/OdkEIeWTRnwnmfXJYyIvTQjsMIK/v2o9jpCh5rRiEJfF/JuypP5O +yHg6F1Qs6P/XafvxC/jsEe6VLbkwvT8THCKKMEvy6WyJuq58U5N5Zy2VEdMi+Q8C +XI4QrL6igOEW2W4wgYHgh6qxUee0kUeqY7DJJwvgTVTTHVTWpub/yrY+5LOAiQis +6eHxgp7xfUKKt64nk7pPdEdXeJ80PuCbau27/lQMhT8mBdE9YPkzX8dpS6ivYWFk +6VCv/qTz0qxQZF9BHHLJeStRgcGIQOV3Udm/EsjRfcTipDwVdxhHxJxpAOQ/xO+m +kJRKFitovc90AV9K2TtlG5UCAwEAATAJBgcqhkjOPQQBA2gAMGUCMHzhiyCuCuN6 +UxwoWA0q0nytE4H9t/2PnFGtAgmrzhnb4aWHw4xs5EJbTjGbqfVgBQIxAOIU5d2o +nnpT/vmlvyijgAHFXAE8qHsKi2XTI7bPy9PDrv2FCS7lLAw8+mNF2mJCug== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDSzCCAq4CCQCg3U8Mc7XCbDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzE1MloXDTEwMDExNDIxMzE1MlowgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2EyMDQ4c2VydmVyLXNlY3A1MjFyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AKB2axKYh2X1jRjtLpQIqhjLeIv55HiqlhF2dElrdTQP/qGN9TAYG9m0hAEzLKE/ +djgYMrsp0M9QfSxlNcLYjOtmYVLz57v1BQnDZI7/DS4jWOKfcnlvJSPbwE7LBoLQ +KKfmXmDWvMwmTBtIEs4nxPph2UuROc5exd1samwS6doAcUm09wqP60aM3lK+9ml3 +/Ukd0coK9824cWa5m4OUcqPtbS8u3LcYJqFb7q7N8q0yYBwuU4kUVpGRlKz5baEv +43qr5l+Fyib/pNEEAO1YhEW+7WjmvOAW4F/GSTI7SHce3Q4+3EoMoORM9nF9t482 +ojDsCe8emGFsGq0eS6MwYY0CAwEAATAJBgcqhkjOPQQBA4GLADCBhwJBdd9GUYv4 +BCF0NKQ583v33GreTlqD2Z0iXnni5du9A+8qJgG1wZlAGAosqXpZCi7i+3q2DVxI +hCU67LcsUi59GJMCQgDTLuJI2gkKvqNufZXIR5vR7/RUd4EddkLw2whv4NMfwLJM +532DeZIH+BtbyfjWYFujjoR/rhhcvtU0+lXsRT4xPQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC7zCCAq4CCQCg3U8Mc7XCbTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzE1N1oXDTEwMDExNDIxMzE1N1owgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2EyMDQ4c2VydmVyLXNlY3QxNjNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJ/8bNSkM/3fhVhEiFtu2r1fam1CVdbHE1tW1MjF2HOHBt2kz2LwLrJZq8ae9NkF +82qSw7TB7b5EWWa+o7y6we8So8VenTXnk1oxRRh1tJi2AMFgqpx+LVh4EVqnhfAp +r7UrtrnM+eAxOyGUVaTMgJKIkhDcfdIS3zHEL1i4tlbmLYRhWUE+wyogZ56FyWhR +mIpfWv9yV8pMaF1VDEBEN/Yl/6w5f8DG4bQnvkOhL51GVb9GdUBKXI/0bybKTgr3 +Ku/T4q1ppHJSSFohM4Riju4EAgrJ2f3p0ebhX0dtTV7SuCH6vgTpOmSqTIGQ5cHh +sGFV4/9Aoky/grDx9hp9D4sCAwEAATAJBgcqhkjOPQQBAzAAMC0CFA1Rg/uMcGW2 +lXuIUjKOiWxBhox7AhUDz3eNq7ir06Ukk5DxFpjGWA4kx2s= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC9zCCAq4CCQCg3U8Mc7XCbjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzIxM1oXDTEwMDExNDIxMzIxM1owgbAxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMDAuBgNVBAsMJ1Rlc3QgU2VydmVy +IChyc2EyMDQ4c2VydmVyLXNlY3QxOTNyMWNhKTEiMCAGA1UEAwwZZGV2LmV4cGVy +aW1lbnRhbHN0dWZmLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALY3OYbAL3fEdoDHiak/3aj7141wmsobDVXPbNR1QFoHDrUqpgdQR3zHGY+BPjDD +qvo0xzzIUE40Hg49R3ya6WyECH8ozl9WJ+JS+lH63RYlHDWOJfzjylF6ihiqixj7 +Twjk1j9ZBPjjiGUA/6RlikxsRhoQTDU/pDD6bSn+yosimpePbOao1BDPfntYFejw +JWPlgC307o++ZKLcGjZH/9IfaKvgiBgl48rVDlQjFNLRkehufk1lviz5CdGph4uF +D8qoO83mIH/wGJ9kWVjv0nvcEOGeGfaM1mDBwsuzVPXqtvUQHOnCfc18B8y8Fw8g +bdoNde6lzDo6IMttKQEa+LMCAwEAATAJBgcqhkjOPQQBAzgAMDUCGQCV2p48seE6 +bqHpTgNOe3WdVuZe9dQYJgECGFG66yqtsjvMSg7snsWmMU/S2a8jvMywLg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID0DCCArgCCQDHAy9pv/zMBzANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcGA1UECwwgVGVzdCBT +ZXJ2ZXIgKHJzYTIwNDhzZXJ2ZXItc2VsZikxIjAgBgNVBAMMGWRldi5leHBlcmlt +ZW50YWxzdHVmZi5jb20wHhcNMDUxMjA2MjEzMjM5WhcNMTAwMTE0MjEzMjM5WjCB +qTELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBW +aWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEpMCcG +A1UECwwgVGVzdCBTZXJ2ZXIgKHJzYTIwNDhzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQDt8MTCSkfQyPw/EjB/lzT1yHMDVuniAFLkxe8GzJYOUEbZQTRt +3gIZ56kX65DDW4R7VCcrFtDbF+PBVwwuBR3YT5adV0mbI0k2jBkteBe2N7CrQMAn +3m5Mmb3pcxLZOHSSH2HJXJzDGY7YCY4UfdUjNCFro56NeSKylTF1TdVpPkDPzbEm +BliscaJZ56WB9AKujbVx2apEaNcpaEXnJ5XbEmtccC463TPXX6Su8haccdXrfDFV +mLe+kwe1w8B/nQbVGWw/v9lysIdx6i1FmWtsU8lJp+kwzg47RiCeb68cumJxvJHp +/WoZGHFE15CYEp4N7lbF/UuiyWsn1VqHfkqnAgMBAAEwDQYJKoZIhvcNAQEFBQAD +ggEBAF0+NeYI0T+ZiDhR4B9kOMZfeQGYov+m2d/Y3Ly3rV35NJ6PbuGpb/VbYSxP +m0l6PhLB/c0V0pyg7MwgwtumhAxlnR5te0wNyYXzuO2oVBoO/8JmsQT8jnCFoANG +9KNrI+A6ed0V7V1u4Uz3YFbD33FWIDWIR+nfDe07FNl7th/8jzpZAhqudtj372jy +Andyzedx/kI4yePpjkHf8F0/MocI691C3rPW8uhSYloPfmaTftYoGl7+E1Xc85bW +JMvnUqwPptOzIVrd2Ei4/4jQDxmI05gDKxZ8aMZddJFkLPKMIFAMwEzo75fCJCBr +7Qo20ez/vMV+XAWGbHr1qLYhHzU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAzCCAsKgAwIBAgIJAIsK5NQHdHWbMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE +CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg +Q0EgKHNlY3AxNjByMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j +b20wHhcNMDUxMjA2MjEyOTUzWhcNMTAwMTE0MjEyOTUzWjCBnDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD +QSAoc2VjcDE2MHIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv +bTA+MBAGByqGSM49AgEGBSuBBAAIAyoABEomOz9/rS0q4OSF2hP23h8Cobi6nftl +PlvgqVcjp+vnica6wXZ8TYOjggEFMIIBATAdBgNVHQ4EFgQUfdItvmVsDmZPpKZD +nEvW2UkF1GEwgdEGA1UdIwSByTCBxoAUfdItvmVsDmZPpKZDnEvW2UkF1GGhgaKk +gZ8wgZwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRh +aW4gVmlldzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMx +HDAaBgNVBAsME1Rlc3QgQ0EgKHNlY3AxNjByMSkxIjAgBgNVBAMMGWRldi5leHBl +cmltZW50YWxzdHVmZi5jb22CCQCLCuTUB3R1mzAMBgNVHRMEBTADAQH/MAkGByqG +SM49BAEDMAAwLQIUGxw8NFGW58flX5kQ+9sTr62kN/UCFQClrPQNlpt7uW9Q5qMB +WRpd1SDyIQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICZjCCAc8CCQCg3U8Mc7XCNzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMTNaFw0xMDAxMTQyMTMwMTNaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDE2MHIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wPjAQBgcqhkjOPQIBBgUrgQQACAMqAAT9 +re7ILR102TfjTOu5h9XN7kIs42BEGeVyFHGqc9El4PEOy8Q4h5waMA0GCSqGSIb3 +DQEBBQUAA4GBAG0/n0eT7HK/1cgn4Qa6czMBpms0ca22r/V11Aj+h2mAqJNuz4aU +7q1r+W94hblFrzAlGSZqRIHykFL/yr6/xzStCB3gd9OslvXIjgrGatzuhAttuO8A +mA6VmPYG2aT5Ih9Bdg/HKuWdkSIeZTDJKMZli/CNWdtl/YcjsmyJDPUX +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC5zCCAc8CCQCg3U8Mc7XCODANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMTRaFw0xMDAxMTQyMTMwMTRaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDE2MHIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wPjAQBgcqhkjOPQIBBgUrgQQACAMqAAT+ +gt3/qI+svlfcqv3G+ldM/9cBveia+Z4S+UUurYsZR3joZVEUSm2JMA0GCSqGSIb3 +DQEBBQUAA4IBAQAGZFmNoRJUjpqoVkZWOP7ZDgjAgQqKFYI3Mm0QGNPvIEq1VCcj +LQnx9PY2B1oMKZJQQ/1KsNqnEMm8jlFXq+O25/QuD1/jv37ME2sn8rZe6vsdKLr6 +4SB/GU4mHID4eNDttT4WepT8OfRBO2EY8MWv+97tkUIr9saxjVMYrp4nK0vJ2Yql +LY0Jw3PgZ11y+WDKwkTWQkOx0SaZhKGRKZelbZZ2xcrV5XUtOFj2Ze27RMARRmmG +SEnSPUg95eaKjpFbjMiPvTACcYJfnpRKN+ev/dQ0lJa1mZEnsXkaNqzb3q7F91Fm +/NQ0Qi0OLeNZWeUUo1q3xhA3L2YvRyvz3425 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICDDCCAcoCCQCg3U8Mc7XCMTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxMFoXDTEwMDExNDIxMzAxMFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEeIPEikmn +11U+4+r1Q1MikFns3u/81SlifvD9FK7i2eHXsm4pJbz66DAJBgcqhkjOPQQBAzEA +MC4CFQD+m6pQXn1FPgD5NS62SFJwZxTe+QIVAOGRJ9XxBZ8CfPMEDDmNkzEyw5I+ +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICIzCCAcoCCQCg3U8Mc7XCMjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxMFoXDTEwMDExNDIxMzAxMFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEsNpgI810 +hR1H/L88VDCIsDJbvQVU/WBqSi+dTVX0E1lITw4S8oJwSDAJBgcqhkjOPQQBA0gA +MEUCIQDTPITeYMLlsJT8jh2CyDHjEskSGLb62OaM4a0iq7wiPwIgbM9hJwczrPcw +3uCNgCT990nAdET61HPVfWOBwDJi7tU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICQjCCAcoCCQCg3U8Mc7XCMzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxMVoXDTEwMDExNDIxMzAxMVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAE/E51tE6b +bbeYQtaomWTWdwqTlW/8UbNDlC/LDHFXhYhNNJJzGdHoLzAJBgcqhkjOPQQBA2cA +MGQCMHjfuIklGYjJgYQYBBDNraRptWiaPe7dsI58LZdeJIwJcQcesTpPjjLDszS9 +jfTUNgIwZiD6FVi1yVTckFvPIGqNwzz46KrpKEO1JWR05DkawDnYoUzOoZjEtDhI +fktezP7a +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICZzCCAcoCCQCg3U8Mc7XCNDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxMVoXDTEwMDExNDIxMzAxMVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMTYwcjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAExrjEN9Rb +kS59txyKYNnlunaAY8PGDBeWy/t5JItcB8BdYNNaQ6Td1jAJBgcqhkjOPQQBA4GL +ADCBhwJBDPCBtcw+W8IBo9x6F9ajBOlstHeR9lV6dE3sLyJhpV9sn697LHA6fQ6u +s4x0aT8OJLod+62DFwDX40ATPoT3RoACQgHscuDNMVpOCx8mdka2mvD442Tcb76w +Qc5DQSd+d0Rw0c9zAvPwObwSttNaaNmuT4v3DturgBVQGdb02bmQIuDNrA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICDDCCAcoCCQCg3U8Mc7XCNTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxMloXDTEwMDExNDIxMzAxMlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMTYwcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEuQ9FFr/a +O6E1WAQ0LtG1wH8nczXWLqJc7f+sgDgzrub2NjvOvfcQ5DAJBgcqhkjOPQQBAzEA +MC4CFQGBzvmRQ4HhuGwqOnKztHmUS9viEwIVAKZCrx0tZO03y9nSpGBRXeTB+bb2 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICEzCCAcoCCQCg3U8Mc7XCNjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxM1oXDTEwMDExNDIxMzAxM1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMTYwcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMD4wEAYHKoZIzj0CAQYFK4EEAAgDKgAEp8qqFVSZ +48NmZKnPWpaJXybje/F2E0wDq8rNOX+LC73zfK3ZC7xDvDAJBgcqhkjOPQQBAzgA +MDUCGQCQP6SvfPS/AVHix6tG38uduEl53DG97JACGBWSckcbWsXYXDhKo3LrNy0h +9uBgV9Gs5Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICEzCCAdICCQDt+YU/aZ6s4TAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl +ciAoc2VjcDE2MHIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu +dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAxNFoXDTEwMDExNDIxMzAxNFowgasx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll +dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV +BAsMIlRlc3QgU2VydmVyIChzZWNwMTYwcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wPjAQBgcqhkjOPQIBBgUrgQQACAMq +AATr4Hx367/3ldBBiTV/6WfVuaRjVYUrFtcXLqsF04z3yL3dw4TcwSnQMAkGByqG +SM49BAEDMAAwLQIVAICB0ciEiBjudkS5M+TgDRowS9wqAhQxdt3pJoNMch0sBGvy +ZvpPEqW4lA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDNTCCAt2gAwIBAgIJAMWAX1EW46gEMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE +CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg +Q0EgKHNlY3AyNTZyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j +b20wHhcNMDUxMjA2MjEyOTUzWhcNMTAwMTE0MjEyOTUzWjCBnDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD +QSAoc2VjcDI1NnIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv +bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABNzAD4317T6bb1oio1J2awuyb2wS +F7okuHwbFhfTuXgvLsQcAWh34Md5SJ711rN7an+sEr0RVyE6h6zgQkD8DUyjggEF +MIIBATAdBgNVHQ4EFgQUSPfZCnqQodFg6YlBySBCsrjQ7hYwgdEGA1UdIwSByTCB +xoAUSPfZCnqQodFg6YlBySBCsrjQ7hahgaKkgZ8wgZwxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3QgQ0EgKHNl +Y3AyNTZyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5jb22CCQDF +gF9RFuOoBDAMBgNVHRMEBTADAQH/MAkGByqGSM49BAEDRwAwRAIgeXLod9K7A3VG +Rw/3wMXrnxNUA+K4yzfAf1OlCy8923kCIGqu3+9B5lZgHWvHiWBkjpkBqegBp5t1 +7YyV4K1ALxcH +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgTCCAeoCCQCg3U8Mc7XCPzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMThaFw0xMDAxMTQyMTMwMThaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDI1NnIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AARnBDetfBY6JJYtJ6BTttMX/edfb+Lc/DCwTneZzjE5lUaM+LzNwNt02H/+XD27 +hhTDJWXP5r26qZzuBkwpi2UJMA0GCSqGSIb3DQEBBQUAA4GBAF1uQyY7WpxJkkht +Ru87ib8WISy/liosB1ijy2bcPHjcpKRSW+LH2+A2+mQYiasfOkLck+9pS7efhFtT +b1A/3BkI9tMGhvMgop8860Khkl6pRETNu/nlVIQ2xzdRdpvJCmFPa67YK25/cn0O +XN6PHMPJF1JVyJhppvjmV/u6TS2N +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDAjCCAeoCCQCg3U8Mc7XCQDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMTlaFw0xMDAxMTQyMTMwMTlaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDI1NnIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AAQmlPt4PtwUBkFqDl1dc+5XqpiPYJ8t0oVklz86WljYLHXNWl20Wd+t+/4akyc+ +3L9Wr2OzkZyXWv4nA4UteyFiMA0GCSqGSIb3DQEBBQUAA4IBAQBWbbxxLkiwz7eo +uN7Jfa+I9xMNFwPhCc7api63Z6Q6P1tcdTxtl6xQefdiFc550H+tOWb+sn3EmBFo +r8XIPAb73dG+41Vp2bSajkY9povAT/UHFYt9rwr9bQfWtJktd939A/hQix4YImzV +7cw8b+SAoEWuWifScDKDlFQvs4zxUAOxFeXbOrb3X1oGDjE93TEx7+x9DBNMDSu3 +hN11j9cyMotJCWB5OFYzCf3ibwwo0usiz768Wu1C3RvauET+xbcE3NkxM6rsQxI1 +lNXM1NNbm7/nOm+zK2lTH7g4Qui8owSgwR0uwEHhmrAHIug0uHC7GbrIn4yibkrq +xkZaaUr3 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICJTCCAeUCCQCg3U8Mc7XCOTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxNVoXDTEwMDExNDIxMzAxNVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAErJOw +EmmdQcay7oSZTNySdc2m4/iwftH3KfY3wDA5qVusJ85AJUYPbwEvqloKpOTdCZI7 +P4za7x7COTuZAzVFVzAJBgcqhkjOPQQBAy8AMCwCFG5V4voKrcE0UlK1osPuHXZD +N2f5AhQR9TzLTT7D1Ee270xtQ+Bwcq9mBA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICPjCCAeUCCQCg3U8Mc7XCOjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxNVoXDTEwMDExNDIxMzAxNVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAERwmM +YUHXpp9LfbDmk33yWOjAf9flz43IHqFq2xa6bczvcht7ZDka7UmSOVQ8A8d2FdjG +BlqAnEKvCHlxqw41SjAJBgcqhkjOPQQBA0gAMEUCIH++MmRaY7IhySci6HGfsACD +otlDDt6kvpJOCTXQS0G8AiEAwNA+4/wVeEvtjendgLX7icNK33L53fK9CqiZovfi +w7o= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICXjCCAeUCCQCg3U8Mc7XCOzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxNloXDTEwMDExNDIxMzAxNlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEXjcN +bCMqCgsKw4WhdPm6ankP3pHHg/bKWiJXJ6BI4QQYGsNBXPb8YvwP6Q1tFPSyjSJo +VRUVmWGn9X7FzQAGQzAJBgcqhkjOPQQBA2gAMGUCMG4SIhLBYKht8fGzVRte/4lJ +Aj+hMTbCuNa36BMOoez16SskyhCtar46QkFIGnmoQgIxAKIxzKgH4dBAdRGu7fsU +OawK3AvNYm9Xb8bn7js+KjB4pJdYBZw4Q3kHB2cBgX+hvg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgjCCAeUCCQCg3U8Mc7XCPDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxNloXDTEwMDExNDIxMzAxNlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMjU2cjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEH/cQ +KncxMblNmy+gpvCcfxdnC96RTzVT5ZdbeTBlmsRLXxWlrORx4+URCmHGpFdFzpmb +Hfc8rPAIQNGiQucuQDAJBgcqhkjOPQQBA4GLADCBhwJCANGrCUSZ/X2XMwFavryU +JGEOQFLMAAsEWVMUYbJifwNyeQVuwNV7cJjE5UGEzFDLbazmdrPVmDeSt4nQYCYN +zy/nAkEhOcJqFzXb2PW1E2MK7qGOswGNr1EifKIF5Tn//nCmpfDSH7G7VXH2IqPC +X6P0wdhzr72Gy3YmjXoj/CTZ/fK6Vg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICJjCCAeUCCQCg3U8Mc7XCPTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxN1oXDTEwMDExNDIxMzAxN1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMjU2cjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHEs0 +EFQnApDDnOBH0DZtSu7mDqzv3BEwm43BWfjQbuvWtKZxTzCc6Pv3dxLgdblE3Fl5 +MK/8Gk3ugDZwe563KzAJBgcqhkjOPQQBAzAAMC0CFQD8O8WJ7okGjHRs/J6rWo+n +FNrwCgIUcFcuAK3K1tfYuE3QGm4smu2n8iM= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICLzCCAeUCCQCg3U8Mc7XCPjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAxOFoXDTEwMDExNDIxMzAxOFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMjU2cjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6I/f +uxD+wYynPua+enF00uSb3hHLi105QljhMjfpXRyMt7jW7N0N44AeQLqvUuX/Ou0B +zXDtE8R5tbU5n1p9vjAJBgcqhkjOPQQBAzkAMDYCGQCRU8ROxYXzP4UclxGtca7W +b03WyYZAva8CGQCTE3650WcJy0ka07FL3RuScknp/D4SZh0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICRTCCAe0CCQCwSXFmzpBH6zAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl +ciAoc2VjcDI1NnIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu +dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAxOVoXDTEwMDExNDIxMzAxOVowgasx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll +dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV +BAsMIlRlc3QgU2VydmVyIChzZWNwMjU2cjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAAQtDOsv5pQz7RzsMK68LUeAIDtdJddk55oLsrd2+93FHIr1CiqOwr/3sH3V +USapRS4Xlb7VvtkFmCGLMna0TEdiMAkGByqGSM49BAEDRwAwRAIgGqI3kC9COsLQ +nUnZmwVaNp6le9PQwro6m6b0r6MgaOgCIFH1x+AgAV+HvbGkPTjIW+Cp1oUcbMgd +iDnA5kk037nh +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDczCCAvqgAwIBAgIJAMKpQMf1IUoCMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE +CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg +Q0EgKHNlY3AzODRyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j +b20wHhcNMDUxMjA2MjEyOTU0WhcNMTAwMTE0MjEyOTU0WjCBnDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD +QSAoc2VjcDM4NHIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv +bTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMaXMYyVYpN6QWe+5TpTN8r9jbAPUEO/ +YuR23HOX5Kq1bP0GoF96uXx53X0V0EOncf/navTd9e7oF4BOgkCsHe0bD2p8b82I +IbQ953K3DDT6eIW4TXF7YvS/xF9ByIx/iaOCAQUwggEBMB0GA1UdDgQWBBTqywJZ +V6bCSeOnSQ3riDM0TDfIMTCB0QYDVR0jBIHJMIHGgBTqywJZV6bCSeOnSQ3riDM0 +TDfIMaGBoqSBnzCBnDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQH +DA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9y +YXRvcmllczEcMBoGA1UECwwTVGVzdCBDQSAoc2VjcDM4NHIxKTEiMCAGA1UEAwwZ +ZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNvbYIJAMKpQMf1IUoCMAwGA1UdEwQFMAMB +Af8wCQYHKoZIzj0EAQNoADBlAjBb8D7U8OiqO8ZU9gUrkMo0Y23AN58o3TSapRge +7qiAuUOVraWioNrrNVpC2z2YI2YCMQC53bKQvlqIQ+GbGMY6C5v+F/zESmVie06v +ba7qe2vIl6OIBiPOP5c5gCj4Nj1g3uI= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICnjCCAgcCCQCg3U8Mc7XCRzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMjVaFw0xMDAxMTQyMTMwMjVaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDM4NHIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAR+ ++z6+8do8BpOuYXtGlnKN6jwDj1MdbcUM9sqJBdvVnBJdHfOCL+nVGSvyTY5BUxJ7 +FT5XG+9H0+juJlC7iUu7guxwXdhkChnOQ28buUqsWYH0yHiKJe5F/Re2ESERPi8w +DQYJKoZIhvcNAQEFBQADgYEAPPio0j09V6vXhN3GYwa3ARjboJIO53kTNa65UGgC +qvdLNufcBRldt2vezR0NKj3CTY+/uD+lNwTp+HdnIGkz0hHA722nv0VZGX2MWdMs +/2/D36kJA89IIPLKkQjzmmjIQ9wNDSAt31j9b/TiUfeodaEZZR/iST5UHDvkSIZE +EHs= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDHzCCAgcCCQCg3U8Mc7XCSDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMjVaFw0xMDAxMTQyMTMwMjVaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDM4NHIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASw +i3q++pOW/2tqHTpGB6X85pKO+oCQa/1KSQhKCjVExJxwfQlClNkHgerFUnMr1Zvu +e468EX7/r4gdnMQn+8FPWcYZ+2PYLHaNa4zmLPZq1YJRq5gjIU96uE9nJLoCJO8w +DQYJKoZIhvcNAQEFBQADggEBAE5R94CP/nqChXrMPmHThRReMGXc65FOXtXrQvNb +YKa26EKHy50fqh0sZkfIMqF8CVYhpMM96f7xJgHBJ1GY20Ayp4Om+nmC1U6in5yk +G+LO1H5uDwn3be9tLXW9Jiif/FSDJvY7GhWMys9W9QpojHrNT1eVGPu5zmZxfvDn +nPlrxOxx2yVSkc04zAfBibKd+iNBLI9x1hEWv9gVILow/nsF+HEceGqCKrKtw3CB +vRek+mUZCUDD6gKsN0LeGnRbEFTjyYp3iqbA7/zaCsXi0C9RowKD/uhQmmsduxFT ++mRBNP2Ni4BGJoFGt6ynkhQMKMcZOgCfG9qu9xFpRa2wn+s= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICRDCCAgICCQCg3U8Mc7XCQTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyMFoXDTEwMDExNDIxMzAyMFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEeU60tao/ +d69lrHxMAx6xC9aIXgbFzDxSl39sQORDuiv7YgqxSNxusAnCCER5YT7i0WfH2LEh +kSO16D40edXpxFXXctF6uOT9KK84oCT2ciV1QbArI1ROExKum1U/qYd3MAkGByqG +SM49BAEDMQAwLgIVAJNssWK3wbZ17bXdaVCc2oydMEqBAhUApNb51n/19FEejcXt +msPefDlmlWA= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICWzCCAgICCQCg3U8Mc7XCQjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyMVoXDTEwMDExNDIxMzAyMVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEUKGBne87 +l7cssaiEtxw1EOATJFv/yHz1811mfKPqCJjpVi5NVLt5q2b7DfWvi4839ywNdD5l +ne3mzh6WT20lH52LkS/sMj2shtx0NAIWQM+SJMi7BrBRtymaXtRZQQxdMAkGByqG +SM49BAEDSAAwRQIgBmcyaM69Ryota/XMkDJzkW8a3zCZahsE5DlTrg+Y+VkCIQD1 +Sp6MuZy6JzwtASW/l/Z313mvQduVpzdtezQtvhXqMw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICfDCCAgICCQCg3U8Mc7XCQzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyMloXDTEwMDExNDIxMzAyMlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAELraTwEbQ +rTk40nU76I/MUWvDrX4HEhnNt2Wor50zzHpNtcWlDh64xyDIUO6IgwPumY93PMUR +E2ObEw1zm2jLx+ld32CHZhVD3NFg1eyUzxUWXlnV5YyMQg4kM+Q4RfSoMAkGByqG +SM49BAEDaQAwZgIxAJp22vZKPO/FetlqwLIcghqoy0rueCskFQC53fhU0zAybTiI +zDLzM3AwwwIjHHIvOQIxALyleafaqz+Uh10WWnhenZ4wEcGtnvMq7NOLA26DttBq +Hda4UJnBkRFBo5+N0m+l6Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICoDCCAgICCQCg3U8Mc7XCRDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyMloXDTEwMDExNDIxMzAyMlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMzg0cjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEtyVcUCcJ +RsoFtoxLIFg32suhU2Vsm3HjI5+uMg/04EdQWsSZ20b2aPZ0G9eOI//t4LT9ha7D +Q8XjDRQl4+MMpcQZPz05CPeM3V+51ORa0TsU5H55mkaI6jzyqjBqU1zMMAkGByqG +SM49BAEDgYwAMIGIAkIApq6d1qKZ5OzFIEJQ2eqFa4TRW2BH18BhK/5+LHv4hI5Q +yIFU0wvnWufrlDpPd0sHZs4Rtyv7DXKLalafI0rt8wMCQgF3KIktGZN0ppn42anJ +UgxeryI8lssrz6y7o1t8bgkCSpPUHFOJiaPcAMaCJIy9/pTkNqItAS6vD9OXvLCq +qkTIUg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICQzCCAgICCQCg3U8Mc7XCRTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyM1oXDTEwMDExNDIxMzAyM1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMzg0cjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEkRuBmaS+ +693na8/kbscQtkKYQyhZ1w+fRbK8vSoPey6GxxDsFU01DAZtxhAiFKDh5Eh1s8ur +goSjJFGjIJWSzgzK2NN6zrvlpuNFYeIbM4ALvRsYDAMJ+3tl3Vq30BWhMAkGByqG +SM49BAEDMAAwLQIUDc0O2pwXZTxjX/TO4dmxlMoBUUYCFQL051eCJ9zO3XAww5Rv +n2Obyhhq6w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICTDCCAgICCQCg3U8Mc7XCRjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyNFoXDTEwMDExNDIxMzAyNFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwMzg0cjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAENttarKTc +CJ4k1b8Fd14pSbGQprsbAFfxk7QhONku4iyam7bmVM5b9Q0SjfNzKIT8yW2swCdi +cFFOcMlpYFGbGNk9kV3mkMhHi5qgbw4iv6/U3WiT7kxfbJjNzWAcGQOQMAkGByqG +SM49BAEDOQAwNgIZAIDGXPjGWx96qYTgjUzg80VsiRV5TINzjQIZAIoa/jec5ioW +ZAvx7piEzY3fRw/YpRMF1A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgjCCAgoCCQCROG+IEgiARDAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl +ciAoc2VjcDM4NHIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu +dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAyNloXDTEwMDExNDIxMzAyNlowgasx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll +dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV +BAsMIlRlc3QgU2VydmVyIChzZWNwMzg0cjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AASCHyVEN+D1kiuu8teqNLvuT/r0cNoE7RyKEt9wpkOMB9NdcFEzVClX9A0AmovZ ++OGwM4ltWN40BFkImyHmwzGRwZEJYdgmFtZOwRKJaMWadbqpto5PtuB+SpFhtQmO +dDMwCQYHKoZIzj0EAQNnADBkAjBCpsIVKSYpyYXCWfeYVf5odGJ7ZAgnT7iYstM3 +HZBfdXA6t8zjXICA2ICOqrR1xUoCMDm7poy6GrsHEOMsBoVS5T9U0p3ouMyOhkIm +0EykkGk1wK+9Z6QM/DLP8lLJB0IrDA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDvjCCAyCgAwIBAgIJANErVg+ok6iAMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE +CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg +Q0EgKHNlY3A1MjFyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j +b20wHhcNMDUxMjA2MjEyOTU1WhcNMTAwMTE0MjEyOTU1WjCBnDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD +QSAoc2VjcDUyMXIxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv +bTCBmzAQBgcqhkjOPQIBBgUrgQQAIwOBhgAEADNScfIghIZGN1TI9A6iM8F+LrAg +xrInc7nmKIBtdYYfsFWwT4P6bQqNrOZixrSmTiZXSGWhzaj+gGAdF8vfr81YAVNe +1hkuP3iC/4iaRk9vyMDHNvKDHQeUxFNIL2UTAfSTl0vYmL1C5KkpYU3+qBVFTLpa +7uImk1s3wQIkTTHyFLLMo4IBBTCCAQEwHQYDVR0OBBYEFAwP2eZOjIq6F87PsSjp +qniRzxZpMIHRBgNVHSMEgckwgcaAFAwP2eZOjIq6F87PsSjpqniRzxZpoYGipIGf +MIGcMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWlu +IFZpZXcxJjAkBgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRww +GgYDVQQLDBNUZXN0IENBIChzZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJp +bWVudGFsc3R1ZmYuY29tggkA0StWD6iTqIAwDAYDVR0TBAUwAwEB/zAJBgcqhkjO +PQQBA4GMADCBiAJCAYD/Rk9FMPk0ZzNrXCHKRdXkjBqfsoB5VYRjFIQnIz8+xEAC +KqHjdmYd4djR6l6NA4olKQn+LUwE2hmtom6res2GAkIBPDlBcwGzoDxU4CQQb/rP +cFEMaA5I4fpGdSNYtIJDkXNluVHAPkv+uK9lrhsjuvpVbh76+mM3B9bg4Tq6+Pxb +KN0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICxDCCAi0CCQCg3U8Mc7XCTzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMzRaFw0xMDAxMTQyMTMwMzRaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDUyMXIxc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYA +BAB+Wp/To8yXNzzp1Iw12ACR2Zc2s8o19H3E8cgC26eDcDYzlAf67/ldZyQ0WDzI +xUlxeJjmNcdiavR5usOo/2lE2AEK1tWu/xVhZZZHWiNQ0vZdZ43BHtBPcqdHRZKv +RRZWrP1pd9ubq1UDzegZdFQ5JwwQjPXz4jpOfTYO5TrmftxZjzANBgkqhkiG9w0B +AQUFAAOBgQAMYv77n1SJ+MDneFbJ2ssBd6aw+hbVqwBVopd0YC+i1Kt5bDe649d/ +vMAtnEmOF8G9/ugg5XVoB0M+6DINC/a5HYYZEYAW/g3Q44XaZCJWOvEVYhFAeUNb +BigmNP4yGv3vP+1rqwEqhb9quxYF2n1e3BuBbi9HkIf2Gp0sMP3pcA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDRTCCAi0CCQCg3U8Mc7XCUDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwMzVaFw0xMDAxMTQyMTMwMzVaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjcDUyMXIxc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMDgYYA +BABjwtNCj8IRxv8e0qyePjKGqOvlcPDzx54bcokXDVHxWOL3OEljqi8qWxJm+Mzg +Xhr888VBZdWjF8iXGgtGPEyNRwF635gdYvpcJoz+I1Jg5XzJYo+kLpf/xt5V44/P +EizJQyx/aJ4thsf2gCfFg/zWpDQbcjrwjz10fzLW7rkt7otbAjANBgkqhkiG9w0B +AQUFAAOCAQEAK88ka6Xlvl/Bg2W9TyAh6zPEtDHU3WPN10LxU4ghbStUGx/YupTr +LSg7nLOQo9CI8LKb+tpTaMPmCSTH5Cfwh+f7Uw20wbvPBg06GiBdQjuK3Dvk64B6 +41s4Y75J0wpXJfgezARRlLe0VLAWwH9ZnZRiqtndF527dPBi8EF3qc8X1sGaQ8tn +EVCd2ifptLgp+eI78QdKsgDFpjDOSJNbLDI1yQcm/0EafyJLKd+xH3EBkaaiw+OV +ctYsD3ebQ6tldDnopgbisTmtwvHGqzVGTG8DDX1El2YhVe4bwZTtLBjcbtJxDg/V +0FLkpRjQ/sDqMbDMb6CUoHRa8Urq13e0Cg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICaDCCAigCCQCg3U8Mc7XCSTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyN1oXDTEwMDExNDIxMzAyN1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBQ/O2 +98Fp8ZlEDVNNUHEHYrdrhmofdEsOMsyaabFAWp4cexMjGYgOZaD4/sCYjc1N9sXp +1LqIlBVeAfQ5BCSdqJYAaUQrvL/4evYANvIiymw/peV60y6Vchz/XuKH3M4RVCxa +8d7eeobwzCbM2PjR1loiInAhdFrKJHF2z3M84MPgQJswCQYHKoZIzj0EAQMvADAs +AhQ7SDvm2UNjV6SQf5HoMMrh+K1V4wIUBIIDOf2vtxEmVLXZvaoJGbOf9Vs= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICgTCCAigCCQCg3U8Mc7XCSjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyOFoXDTEwMDExNDIxMzAyOFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAqYn6 +hGbL5dTx1gnWnUBp40JXPKxlrAi4p6ofvM6Kd1HwtQLgeNpIqi1TtxXPc4HkHu9F +gqV5pOJhEUAF9ABqeigBCGHqHtp7eqq8ZKVfIdQKDUTGsHZe1mkQA9JHqBwi35Mo +TOkUlws3aEFtXyfZcjgUd7PYzOM5Ry/m56RiZGdMu+EwCQYHKoZIzj0EAQNIADBF +AiEAzxdUODAqmgqDDM13NLrIREDlN8BlRgFUW4AFxOg87Y4CICW2qf+ioupQuvWE +da8fLQVnCbVbLUKFZlJd02uIsud7 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICojCCAigCCQCg3U8Mc7XCSzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAyOVoXDTEwMDExNDIxMzAyOVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAx9bl +XZ1Voix3FACqRqpURu5ZjoPPMIY93jbYEL6wZdDU4FFbXOiTYt2At+aQPi8Rjy8a +DI3CxXQ5PCPrCPip8gwABVTtjfQzwJwbqIlZuE/HZL6ZmRkz1iCOmWhk4qDqGUpw +/k78Wgl4GYPBdsZOxzSa0g+XIQEW3MeLGzpEH86zKY8wCQYHKoZIzj0EAQNpADBm +AjEAv1WKxcvLV9MQWHIu1rWic1soAGPIt30b/7Q8VZB7HnRTBtOQUteQevoHHxjo +DZWaAjEA43j2Sh07TKD1c6lglFFONNNuR7orVCapEgoXNgcMceF8cwIuYyCqW75A +EneclLfr +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICxjCCAigCCQCg3U8Mc7XCTDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzMFoXDTEwMDExNDIxMzAzMFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwNTIxcjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQAyY+l +SUAwJE5hPEUCwuccerdfzoZMp3c9Hkw/fnvVjQpA0Vvb0piBJ39MRCGYi63RbaRs +QexmUq3XGdbL8mwoV0YB5niOZ9cg6YeqXRAnkcS/GboHNjtYQWysta+D+dfX8S1g +YBuXdNZrbGdAj9UP7+gz/9WrPOctz6gwyeiKLKsvosMwCQYHKoZIzj0EAQOBjAAw +gYgCQgErxOvqzrTt5eHrdH4ZxUn4AM9dBAqX33jKXBKNuRgmyYIxoIO2c2tqkdxC +rXmeudFZmFGEEBor5bg2RMI6pkcoWwJCAe6TIx0KcaF6D1wW9tlmRXZ+888SS6Fq +BdVwn4a8/6TrTxQGmDD6qVTwGco76umjHnam50Kcvg6iBAjfSUmwj/56 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICajCCAigCCQCg3U8Mc7XCTTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzMloXDTEwMDExNDIxMzAzMlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwNTIxcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB3xU0 +hOYQMnJ7L+TLdSkB7ruVnjWo6iwLe0N2GlpCc5jSmBfhGr0NyoKrNY1Zy+VcnGCu +vYgT/aqN7nOnZ86qoQQAq8o2wpdlTbeyzzE26txGTVi+7IN3sVB7DFmqI/R6ngKK +GdkmE6ZOBBcyipzOc/eXRpqoRaIRA+FP2LAPdBnsuNkwCQYHKoZIzj0EAQMxADAu +AhUBOyoJaoo5E6UZ8ICdSZAsL7FpwcMCFQJ1wcD/KuK0g+2WMgpCAuElR+dZIg== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICcDCCAigCCQCg3U8Mc7XCTjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzM1oXDTEwMDExNDIxMzAzM1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWNwNTIxcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQBvNN+ +2syVq0vx/Qj1W5IYpeUdyswTzyBNdz0LveNcNEV07jql3o25dPHNGZcVcCvPFw2H +2zpaWV8t0YHjHETM3mEBxgyxwpbM3dkdCuM0VlKEA+rUY64QU8/f0WYU+1cFPBBi +fMOuMKXfb1JNK93W9A9jzmFSVJJVauXYs6JURy60Z+8wCQYHKoZIzj0EAQM3ADA0 +AhgoBo+CqnLTn7UxFzNYtHabS0zMzBzBhN0CGAaNavBCHkk1eX0xmp+7BIxHnWOl +bbeeYQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICzjCCAjACCQCYUruIqLYp5jAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl +ciAoc2VjcDUyMXIxc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu +dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzAzNloXDTEwMDExNDIxMzAzNlowgasx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll +dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV +BAsMIlRlc3QgU2VydmVyIChzZWNwNTIxcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wgZswEAYHKoZIzj0CAQYFK4EEACMD +gYYABAH3WSHvJZH8mqyGfVxtoyF5pCUVJZTnebvRphld+jK1PFKlzglYN22J8yN9 +l7Ca2h2OjuuEVj3fZAwSAInZtZQzxAEHFMZEVAzoHUPjx9qEAJiNjXcVV79cvrvc +Q8SbYBF3vGB0su2Qydig+VEjmkyklGhxFLQE8fo7fEZh+FfwGG3x6TAJBgcqhkjO +PQQBA4GMADCBiAJCAYLsxXVifQfzuyZRMNqzldUcASTgs1L/MMtJcEvYtFpeaGXd +Nn1jIynPkC3rgjbejtLe4OypPymrkVE0Bjn3rKU/AkIB1TtXqfmYkTdOO/AUriRl +GSatOobx7QQ+CyOtziObl1UPe7hDYGX8quZPxWnx6MgtO4I4sSZWA7/0C6N61XSq +NPs= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDBjCCAsSgAwIBAgIJAJUfXqNiGl4gMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE +CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg +Q0EgKHNlY3QxNjNyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j +b20wHhcNMDUxMjA2MjEyOTU2WhcNMTAwMTE0MjEyOTU2WjCBnDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD +QSAoc2VjdDE2M3IxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv +bTBAMBAGByqGSM49AgEGBSuBBAACAywABATc2/gR5Sk1spq3ktZK4UCWH8ILGQJy +xhua4tLSekXuk3joLxw7GVD/K6OCAQUwggEBMB0GA1UdDgQWBBTRQhIcGNnfzY1r +7mAO0j6l4jrt1jCB0QYDVR0jBIHJMIHGgBTRQhIcGNnfzY1r7mAO0j6l4jrt1qGB +oqSBnzCBnDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3Vu +dGFpbiBWaWV3MSYwJAYDVQQKDB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmll +czEcMBoGA1UECwwTVGVzdCBDQSAoc2VjdDE2M3IxKTEiMCAGA1UEAwwZZGV2LmV4 +cGVyaW1lbnRhbHN0dWZmLmNvbYIJAJUfXqNiGl4gMAwGA1UdEwQFMAMBAf8wCQYH +KoZIzj0EAQMxADAuAhUD5UVJP72K01PbvDeANWleHbjxd48CFQN6Qt34E0JeefbC +NVkYG6pXLegBvQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICaDCCAdECCQCg3U8Mc7XCVzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwNDBaFw0xMDAxMTQyMTMwNDBaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjdDE2M3Ixc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wQDAQBgcqhkjOPQIBBgUrgQQAAgMsAAQE +/r8twiEWpvxX4VUSmCw1JJNHF9IDvIxktMTtZqcK2/57GElqT5Hmi1swDQYJKoZI +hvcNAQEFBQADgYEAHmeOaUdqT4x1o7UCpXTW8D2+XCTCFMpPENH0plL7ALUj5R2D +av2TvKKSwpbyOJa26Rx5KEMNntGpSN1X4+a+wPHZ87J3wmtU7B6nEaHIkFM/iGRQ +M2Ip+lBhebd1e+itwIRnpFcNt5dD276F30928E6kxwSge2uoQJySFV+Xuho= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC6TCCAdECCQCg3U8Mc7XCWDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwNDFaFw0xMDAxMTQyMTMwNDFaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjdDE2M3Ixc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wQDAQBgcqhkjOPQIBBgUrgQQAAgMsAAQD +jbQ3J7+yvmgc++WxXN52nfRQWnkFc1DUqspljUJyusmdPI1+8ki7FcMwDQYJKoZI +hvcNAQEFBQADggEBAAF3SF1Wmlk6F/IeQs0hlLHF/ik0xWngsO/Qgqrax6MGLdPW +jjJDE1UY6mjNXo8kuV9nIr4+27RN1q3hlSaVC47BX9kZNOs+nO/8h4mFXSV3osq4 +7RrJ5RJ/seXk6s7QItfmZslv7LR/FrzTF7pDv385WwwRXpfhCIY3X24bSt7dgK4j +CkXf6GV9WTrICmNRBeV8/LJAbETU6XPhBXpIlYO0sasSfbCd/j4voIUhwZgPXdGx +iNVWcwgntcOwx4wXJOoWoiiU/j+eS6YDrsxqgdV3j0+JYWQNUvFhrotI/HjbZ8RU +rUiYpAcbghxkent0pcmkcHbJJcj/8/AzQcp+iYg= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICDTCCAcwCCQCg3U8Mc7XCUTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzN1oXDTEwMDExNDIxMzAzN1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEBW5dGOJD +CIYYqj8GEUDWGalB2d6wAQzBC6qR3h5seNsC212ApAdfYdTUMAkGByqGSM49BAED +MAAwLQIVANtclGRvcbIOV+XiYhSBeiuj/XAZAhQjQSZ21bwoOnKjnybeDYMhqEIG +1w== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICJTCCAcwCCQCg3U8Mc7XCUjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzN1oXDTEwMDExNDIxMzAzN1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEAEvhHRk9 +YT/OvjnDdKuUpfv4RLbvA+ea8m5+4zH4agPsJFjEgC+Tl2AoMAkGByqGSM49BAED +SAAwRQIgEE8zOqy0HkGCnAqdj0xUdpN43vyhBy08G6wx5tWFYekCIQDk0Rc/a8Mz +id0zWgeo4cFUv75+S86WaSSxnkbgKD/PfA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICRDCCAcwCCQCg3U8Mc7XCUzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzOFoXDTEwMDExNDIxMzAzOFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEBLc5EQ+F +QABNsN7pyoOE60q/aokmAgE6Su1TfwZKvAGjxcAF4+l/I015MAkGByqGSM49BAED +ZwAwZAIwD2i5VWRPgSSx/Q2JgJTN96q/T/rmDW+IzyqEU78KwzVIhf8zUIjQH5Pv +az+KrObIAjBNUjCd2rUJorAOrDcf/s8d7KFBnxoiRjNCRKO6SiPvI8Cc4jaXfja5 +XZJjzk8P/nc= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICajCCAcwCCQCg3U8Mc7XCVDAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwNTIxcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzOFoXDTEwMDExNDIxMzAzOFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTYzcjFzZXJ2ZXItc2VjcDUyMXIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEAcPPApQN +hrXdgu0Rxv5SSy9Exry/Ag78xFNPzTR9mJxS1X8tN1wfiJOBMAkGByqGSM49BAED +gYwAMIGIAkIA1Fm7h0vZAywp1Wf3xNI3wm29lK0BSWOVO6fQyWYmKghKi325Tkbw +MbyO3D9YXC2K1G7zQrG5GXA1Jo82ndhpsKUCQgHK67lXzYtfCndSWDrPftXEqn0T +epSGI3I5vxlJuvx2UW1fvZt098Ku4bR8ixKVgDHo8TuEEsJJg+johh0oZHQj7Q== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICDTCCAcwCCQCg3U8Mc7XCVTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzOVoXDTEwMDExNDIxMzAzOVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTYzcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEBd4sp9FM +F2RQWVjZqhqKPRhVhcOrB20Iqn3MfUIXpKnZWBugJZYgQVIvMAkGByqGSM49BAED +MAAwLQIUAwzB/r2hCllysJwxwC4VKKF90igCFQCO0ik9fYlw5RInDzDH/f7xjOOS +gw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICFTCCAcwCCQCg3U8Mc7XCVjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzAzOVoXDTEwMDExNDIxMzAzOVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTYzcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEAwEAYHKoZIzj0CAQYFK4EEAAIDLAAEAgD1SibB +UQJtSvkK42sdggot73fzBk2J+aj3WSvDHwMXsYslaPQG71lYMAkGByqGSM49BAED +OAAwNQIZANBEfel7WcTKFV0q3UTeod1T3K7ClZQpQgIYZe6dll2Llj3A2S6eRB1G +qjDJaejrFGxR +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICFjCCAdQCCQCKZ9MLoj/3JDAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl +ciAoc2VjdDE2M3Ixc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu +dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzA0MVoXDTEwMDExNDIxMzA0MVowgasx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll +dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV +BAsMIlRlc3QgU2VydmVyIChzZWN0MTYzcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wQDAQBgcqhkjOPQIBBgUrgQQAAgMs +AAQAbsGEXvpTlsxcf5b1S0Uv+CW6aDIAD1SB5MwpErkmq6eCFPVF2c3iIZ4wCQYH +KoZIzj0EAQMxADAuAhUAhh4DeqrebKZ7IoIO+gYcs1tT4IsCFQD51UVBnZrYhqHT +tKfswmapHLXMzA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDFTCCAsygAwIBAgIJAI4aIMim8fazMAkGByqGSM49BAEwgZwxCzAJBgNVBAYT +AlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UE +CgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxHDAaBgNVBAsME1Rlc3Qg +Q0EgKHNlY3QxOTNyMSkxIjAgBgNVBAMMGWRldi5leHBlcmltZW50YWxzdHVmZi5j +b20wHhcNMDUxMjA2MjEyOTU2WhcNMTAwMTE0MjEyOTU2WjCBnDELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEcMBoGA1UECwwTVGVzdCBD +QSAoc2VjdDE5M3IxKTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZmLmNv +bTBIMBAGByqGSM49AgEGBSuBBAAYAzQABADC/YtwwrsyHusPx05mHRMV3Rjw5dcw +LLUAIh3jrWVGFFLWZl0QCs2xBnGF6KfjKnOdo4IBBTCCAQEwHQYDVR0OBBYEFHVx +jVCVss3ZetdFkR0auNgmLXljMIHRBgNVHSMEgckwgcaAFHVxjVCVss3ZetdFkR0a +uNgmLXljoYGipIGfMIGcMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNV +BAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1biBNaWNyb3N5c3RlbXMgTGFi +b3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChzZWN0MTkzcjEpMSIwIAYDVQQD +DBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tggkAjhogyKbx9rMwDAYDVR0TBAUw +AwEB/zAJBgcqhkjOPQQBAzgAMDUCGFVX2d9M0NbxeusbaUjMcWwviXPQpNEHvwIZ +AOPKXDtDGAwkb42kO7ms7rzN7R4LN788MA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICcDCCAdkCCQCg3U8Mc7XCXzANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAxMDI0KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwNDVaFw0xMDAxMTQyMTMwNDVaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjdDE5M3Ixc2VydmVyLXJzYTEwMjRjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wSDAQBgcqhkjOPQIBBgUrgQQAGAM0AAQA +vZA91W5lNk3Ru3pALBexkJpZ9K0WjZrLASMO9wZGvbukocKAPYTfDYdcSwdwqHuU +RzANBgkqhkiG9w0BAQUFAAOBgQB/Gcwd09VVyOWJq9cIA5tga/ZBYwgXv+T3eAUU +Ert7tGQgD/eysWYvTB+Vu9zUvGyWWtUfzoFMP1R2MeuxnDMiXyhhQ+7UKl3P7AQy +P060oo1DP7RWK8D8oz8IFeP6ttaiRgetE3hnHUwbxnO30bdiN61EdWBT0Dp+0LuP +Yg6Ndw== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIC8TCCAdkCCQCg3U8Mc7XCYDANBgkqhkiG9w0BAQUFADCBnzELMAkGA1UEBhMC +VVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSYwJAYDVQQK +DB1TdW4gTWljcm9zeXN0ZW1zIExhYm9yYXRvcmllczEfMB0GA1UECwwWVGVzdCBT +ZXJ2ZXIgKFJTQSAyMDQ4KTEiMCAGA1UEAwwZZGV2LmV4cGVyaW1lbnRhbHN0dWZm +LmNvbTAeFw0wNTEyMDYyMTMwNDZaFw0xMDAxMTQyMTMwNDZaMIGwMQswCQYDVQQG +EwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNV +BAoMHVN1biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMTAwLgYDVQQLDCdUZXN0 +IFNlcnZlciAoc2VjdDE5M3Ixc2VydmVyLXJzYTIwNDhjYSkxIjAgBgNVBAMMGWRl +di5leHBlcmltZW50YWxzdHVmZi5jb20wSDAQBgcqhkjOPQIBBgUrgQQAGAM0AAQA +qMKb0SJmrWoWnZxXZh5jhRZnF9vRyljvARAR7/z2+gU/qkOTcxuE9RYxgqHtDVRE +fjANBgkqhkiG9w0BAQUFAAOCAQEAScWVdynbg9B9VCtF4Ct8sXMRRYuwCLUt5Yp/ +rtLXmhUuZR0qCvuCMoDo2+HdQNcwEZr7teH2jZ9gYcfq1GWouwA36rafR8e4GQ4P +egySyKLYkZ7sKhrKacN4k1XItlxHsWWtVRs79smAVgpVIu5IA2Pm5BZEuIUPCIAF +3gSHM6Y0UHWGazxaToUEiPh7jVh5eUA8wAdhKFhiLtrIlZo9u2BCXmPiwBj71fSY +iyEArag7u/n5pfoBYzwiiAFLddQiuwaxe8jPt0+RJI5Dhs0IzX6L/Xzu06qkKPjF +9AX5PkBWj5GAjPCU/8t3O2wrMBvCw7G7epMXNXjTqJf6no5sig== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICFTCCAdQCCQCg3U8Mc7XCWTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMTYwcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA0MloXDTEwMDExNDIxMzA0MlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTkzcjFzZXJ2ZXItc2VjcDE2MHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEANui7TQR +XIBnrqvvP9zgztIKdqeIwISmzQBKKwC3FMR/Ma/MJCuBuXANUV3Xbi/rwwswCQYH +KoZIzj0EAQMwADAtAhUAhNmGbEAG/eht1YE9KUUf7v/k9ywCFDO9YqZLm7mvDe2Q +Vp2EWIS8AFw0 +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICLjCCAdQCCQCg3U8Mc7XCWjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMjU2cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA0MloXDTEwMDExNDIxMzA0MlowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTkzcjFzZXJ2ZXItc2VjcDI1NnIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEAE/bjnPS +yBqy8ageF1ZpfzHTAoEzcV5UywAlrF6AsP5UDVbbxWzEYENodBbIAyu5gmswCQYH +KoZIzj0EAQNJADBGAiEAyOvzEV5o/+YRAkIQY/+Le1n3wzUvr9QMwVlOg/yZMvsC +IQCFFD9AOt0tQTxWsDgGzCoVbz9MnnWzptIsGx4HXUm4YA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICTTCCAdQCCQCg3U8Mc7XCWzAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWNwMzg0cjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA0M1oXDTEwMDExNDIxMzA0M1owgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTkzcjFzZXJ2ZXItc2VjcDM4NHIxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEASNBKWzJ ++B+4G2UTsTqBM0cjsdS6C5cmHwC1oYKyagdGeWkSzI3wsNJri29OBB3wg1YwCQYH +KoZIzj0EAQNoADBlAjEAvCF43f3XJZHJ43dChTwVcMxrvrkEg33BCdkpab3ZzQGc +4z8YLxgXwNgQtoWakxepAjAT9zi78gOcvIOLt+cONUWX1Q3dwsqz7ELfB51+H9EC +njcMe07enAwPTGZhifhBqfQ= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICFjCCAdQCCQCg3U8Mc7XCXTAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTYzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA0NFoXDTEwMDExNDIxMzA0NFowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTkzcjFzZXJ2ZXItc2VjdDE2M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEAInznYj4 +XfwSdi2XrqLF6uQ1/sJoFEveBQCqz+XoSsXKgRmMCO2iMHVGctNbcz8RptMwCQYH +KoZIzj0EAQMxADAuAhUBfBAH/3ROR9VsZKAhW0fR6i/ud9gCFQCdjuAk1NhSTtAD +AcZ+gSnBmESa1g== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICHDCCAdQCCQCg3U8Mc7XCXjAJBgcqhkjOPQQBMIGcMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMRwwGgYDVQQLDBNUZXN0IENBIChz +ZWN0MTkzcjEpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVudGFsc3R1ZmYuY29tMB4X +DTA1MTIwNjIxMzA0NVoXDTEwMDExNDIxMzA0NVowgbIxCzAJBgNVBAYTAlVTMQsw +CQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEmMCQGA1UECgwdU3Vu +IE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxMjAwBgNVBAsMKVRlc3QgU2VydmVy +IChzZWN0MTkzcjFzZXJ2ZXItc2VjdDE5M3IxY2EpMSIwIAYDVQQDDBlkZXYuZXhw +ZXJpbWVudGFsc3R1ZmYuY29tMEgwEAYHKoZIzj0CAQYFK4EEABgDNAAEAGJbRZVS +qbKx8P+C60EaCmnuolgSDf7fqwE0oMSo8dtSmq1vSmqXjbQHWaze3zev50swCQYH +KoZIzj0EAQM3ADA0AhhsmuN8sbGYzItLtNqk/kXRvBSk+gOeKaECGBAT5pnVqKan +q4wuATzeJEv5LeT9H3GU1A== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIICJDCCAdwCCQCzW7zGCDpEhzAJBgcqhkjOPQQBMIGrMQswCQYDVQQGEwJVUzEL +MAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxJjAkBgNVBAoMHVN1 +biBNaWNyb3N5c3RlbXMgTGFib3JhdG9yaWVzMSswKQYDVQQLDCJUZXN0IFNlcnZl +ciAoc2VjdDE5M3Ixc2VydmVyLXNlbGYpMSIwIAYDVQQDDBlkZXYuZXhwZXJpbWVu +dGFsc3R1ZmYuY29tMB4XDTA1MTIwNjIxMzA0N1oXDTEwMDExNDIxMzA0N1owgasx +CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNTW91bnRhaW4gVmll +dzEmMCQGA1UECgwdU3VuIE1pY3Jvc3lzdGVtcyBMYWJvcmF0b3JpZXMxKzApBgNV +BAsMIlRlc3QgU2VydmVyIChzZWN0MTkzcjFzZXJ2ZXItc2VsZikxIjAgBgNVBAMM +GWRldi5leHBlcmltZW50YWxzdHVmZi5jb20wSDAQBgcqhkjOPQIBBgUrgQQAGAM0 +AAQAjhf42KmZLPPrcBCdsOJpU9uDCZDh7CD7Af3pMkj8friWXyIZBoKwChbkPOnT +wq4XMTAJBgcqhkjOPQQBAzcAMDQCGD0nycV04j9b/1/l1cnRJWtuaHUK2LPmdAIY +fDH6KdS9OQSXMHdiCLnK5mWYTDG0g0em +-----END CERTIFICATE----- diff --git a/test/sun/security/ec/keystore b/test/sun/security/ec/keystore new file mode 100644 index 0000000000000000000000000000000000000000..b59a2ab43c61b99c5d72a943aec13b090f111b62 Binary files /dev/null and b/test/sun/security/ec/keystore differ diff --git a/test/sun/security/ec/truststore b/test/sun/security/ec/truststore new file mode 100644 index 0000000000000000000000000000000000000000..643c7a84dabebc452e1aac303d7eafc206a8229f Binary files /dev/null and b/test/sun/security/ec/truststore differ diff --git a/test/sun/security/krb5/IPv6.java b/test/sun/security/krb5/IPv6.java new file mode 100644 index 0000000000000000000000000000000000000000..763745f8fba8295f5a62a63aca87f6e32d153314 --- /dev/null +++ b/test/sun/security/krb5/IPv6.java @@ -0,0 +1,127 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6877357 + * @summary IPv6 address does not work + */ + +import com.sun.security.auth.module.Krb5LoginModule; +import java.io.*; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.security.auth.Subject; + +public class IPv6 { + + public static void main(String[] args) throws Exception { + + String[][] kdcs = { + {"simple.host", null}, // These are legal settings + {"simple.host", ""}, + {"simple.host", "8080"}, + {"0.0.0.1", null}, + {"0.0.0.1", ""}, + {"0.0.0.1", "8080"}, + {"1::1", null}, + {"[1::1]", null}, + {"[1::1]", ""}, + {"[1::1]", "8080"}, + {"[1::1", null}, // Two illegal settings + {"[1::1]abc", null}, + }; + // Prepares a krb5.conf with every kind of KDC settings + PrintStream out = new PrintStream(new FileOutputStream("ipv6.conf")); + out.println("[libdefaults]"); + out.println("default_realm = V6"); + out.println("[realms]"); + out.println("V6 = {"); + for (String[] hp: kdcs) { + if (hp[1] != null) out.println(" kdc = "+hp[0]+":"+hp[1]); + else out.println(" kdc = " + hp[0]); + } + out.println("}"); + out.close(); + + System.setProperty("sun.security.krb5.debug", "true"); + System.setProperty("java.security.krb5.conf", "ipv6.conf"); + + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + PrintStream po = new PrintStream(bo); + PrintStream oldout = System.out; + System.setOut(po); + + try { + Subject subject = new Subject(); + Krb5LoginModule krb5 = new Krb5LoginModule(); + Map map = new HashMap(); + Map shared = new HashMap(); + + map.put("debug", "true"); + map.put("doNotPrompt", "true"); + map.put("useTicketCache", "false"); + map.put("useFirstPass", "true"); + shared.put("javax.security.auth.login.name", "any"); + shared.put("javax.security.auth.login.password", "any".toCharArray()); + krb5.initialize(subject, null, shared, map); + krb5.login(); + } catch (Exception e) { + // Ignore + } + + po.flush(); + + System.setOut(oldout); + String[] lines = new String(bo.toByteArray()).split("\n"); + int cc = 0; + Pattern r = Pattern.compile(".*KrbKdcReq send: kdc=(.*) UDP:(\\d+),.*"); + for (String line: lines) { + Matcher m = r.matcher(line.subSequence(0, line.length())); + if (m.matches()) { + System.out.println("------------------"); + System.out.println(line); + String h = m.group(1), p = m.group(2); + String eh = kdcs[cc][0], ep = kdcs[cc][1]; + if (eh.charAt(0) == '[') { + eh = eh.substring(1, eh.length()-1); + } + System.out.println("Expected: " + eh + " : " + ep); + System.out.println("Actual: " + h + " : " + p); + if (!eh.equals(h) || + (ep == null || ep.length() == 0) && !p.equals("88") || + (ep != null && ep.length() > 0) && !p.equals(ep)) { + throw new Exception("Mismatch"); + } + cc++; + } + } + if (cc != kdcs.length - 2) { // 2 illegal settings at the end + throw new Exception("Not traversed"); + } + } +} + + diff --git a/test/sun/security/pkcs11/ec/ReadCertificates.java b/test/sun/security/pkcs11/ec/ReadCertificates.java index 5955400dff3d1ce9d5422480a05e20f0069d17a4..cf05e0573a2d079b36fcfda14ed30ec37295144b 100644 --- a/test/sun/security/pkcs11/ec/ReadCertificates.java +++ b/test/sun/security/pkcs11/ec/ReadCertificates.java @@ -100,7 +100,15 @@ public class ReadCertificates extends PKCS11Test { X509Certificate issuer = certs.get(cert.getIssuerX500Principal()); System.out.println("Verifying " + cert.getSubjectX500Principal() + "..."); PublicKey key = issuer.getPublicKey(); - cert.verify(key, p.getName()); + // First try the provider under test (if it does not support the + // necessary algorithm then try any registered provider). + try { + cert.verify(key, p.getName()); + } catch (NoSuchAlgorithmException e) { + System.out.println("Warning: " + e.getMessage() + + ". Trying another provider..."); + cert.verify(key); + } } // try some random invalid signatures to make sure we get the correct diff --git a/test/sun/security/pkcs11/sslecc/CipherTest.java b/test/sun/security/pkcs11/sslecc/CipherTest.java index 6777eca501231821bd9882580db27f25a758d275..8d0dc3431e42ab145688abb31923be2908aa26ca 100644 --- a/test/sun/security/pkcs11/sslecc/CipherTest.java +++ b/test/sun/security/pkcs11/sslecc/CipherTest.java @@ -298,7 +298,7 @@ public class CipherTest { throws Exception { long time = System.currentTimeMillis(); String relPath; - if ((args.length > 0) && args[0].equals("sh")) { + if ((args != null) && (args.length > 0) && args[0].equals("sh")) { relPath = pathToStoresSH; } else { relPath = pathToStores; diff --git a/test/sun/util/logging/PlatformLoggerTest.java b/test/sun/util/logging/PlatformLoggerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0c5daf0422e9f40e7666821b691667a2c086525e --- /dev/null +++ b/test/sun/util/logging/PlatformLoggerTest.java @@ -0,0 +1,111 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * @test + * @bug 6882376 + * @summary Test if java.util.logging.Logger is created before and after + * logging is enabled. Also validate some basic PlatformLogger + * operations. + * + * @build PlatformLoggerTest + * @run main PlatformLoggerTest + */ + +import java.util.logging.*; +import sun.util.logging.PlatformLogger; + +public class PlatformLoggerTest { + private static final int defaultEffectiveLevel = 0; + public static void main(String[] args) throws Exception { + final String FOO_PLATFORM_LOGGER = "test.platformlogger.foo"; + final String BAR_PLATFORM_LOGGER = "test.platformlogger.bar"; + final String GOO_PLATFORM_LOGGER = "test.platformlogger.goo"; + final String BAR_LOGGER = "test.logger.bar"; + PlatformLogger goo = PlatformLogger.getLogger(GOO_PLATFORM_LOGGER); + + // Create a platform logger using the default + PlatformLogger foo = PlatformLogger.getLogger(FOO_PLATFORM_LOGGER); + checkPlatformLogger(foo, FOO_PLATFORM_LOGGER); + + // create a java.util.logging.Logger + // now java.util.logging.Logger should be created for each platform logger + Logger logger = Logger.getLogger(BAR_LOGGER); + logger.setLevel(Level.WARNING); + + PlatformLogger bar = PlatformLogger.getLogger(BAR_PLATFORM_LOGGER); + checkPlatformLogger(bar, BAR_PLATFORM_LOGGER); + + checkLogger(FOO_PLATFORM_LOGGER, Level.FINER); + checkLogger(BAR_PLATFORM_LOGGER, Level.FINER); + + checkLogger(GOO_PLATFORM_LOGGER, null); + checkLogger(BAR_LOGGER, Level.WARNING); + + foo.setLevel(PlatformLogger.SEVERE); + checkLogger(FOO_PLATFORM_LOGGER, Level.SEVERE); + } + + private static void checkPlatformLogger(PlatformLogger logger, String name) { + if (!logger.getName().equals(name)) { + throw new RuntimeException("Invalid logger's name " + + logger.getName() + " but expected " + name); + } + + if (logger.getLevel() != defaultEffectiveLevel) { + throw new RuntimeException("Invalid default level for logger " + + logger.getName()); + } + + if (logger.isLoggable(PlatformLogger.FINE) != false) { + throw new RuntimeException("isLoggerable(FINE) returns true for logger " + + logger.getName() + " but expected false"); + } + + logger.setLevel(PlatformLogger.FINER); + if (logger.getLevel() != Level.FINER.intValue()) { + throw new RuntimeException("Invalid level for logger " + + logger.getName() + " " + logger.getLevel()); + } + + if (logger.isLoggable(PlatformLogger.FINE) != true) { + throw new RuntimeException("isLoggerable(FINE) returns false for logger " + + logger.getName() + " but expected true"); + } + + logger.info("OK: Testing log message"); + } + + private static void checkLogger(String name, Level level) { + Logger logger = LogManager.getLogManager().getLogger(name); + if (logger == null) { + throw new RuntimeException("Logger " + name + + " does not exist"); + } + + if (logger.getLevel() != level) { + throw new RuntimeException("Invalid level for logger " + + logger.getName() + " " + logger.getLevel()); + } + } +} diff --git a/test/tools/launcher/6842838/CreateBadJar.java b/test/tools/launcher/6842838/CreateBadJar.java new file mode 100644 index 0000000000000000000000000000000000000000..dfdc9163de2962ecd8abef0a6b62466151d75cb5 --- /dev/null +++ b/test/tools/launcher/6842838/CreateBadJar.java @@ -0,0 +1,168 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/* + * Borrowing significantly from Martin Buchholz's CorruptedZipFiles.java + * + * Needed a way of testing the checks for corrupt zip/jar entry in + * inflate_file from file j2se/src/share/bin/parse_manifest.c + * and running them with the 64-bit launcher. e.g. + * sparcv9/bin/java -jar badjar.jar + * + * Run from a script driver Test6842838.sh as we want to specifically run + * bin/sparcv9/java, the 64-bit launcher. + * + * So this program will create a zip file and damage it in the way + * required to tickle this bug. + * + * It will cause a buffer overrun: but that will not always crash. + * Use libumem preloaded by the script driver in order to + * abort quickly when the overrun happens. That makes the test + * Solaris-specific. + */ + +import java.util.*; +import java.util.zip.*; +import java.io.*; +import static java.lang.System.*; +import static java.util.zip.ZipFile.*; + +public class CreateBadJar { + +public static void main(String [] arguments) { + + if (arguments.length != 2) { + throw new RuntimeException("Arguments: jarfilename entryname"); + } + String outFile = arguments[0]; + String entryName = arguments[1]; + + try { + // If the named file doesn't exist, create it. + // If it does, we are expecting it to contain the named entry, for + // alteration. + if (!new File(outFile).exists()) { + System.out.println("Creating file " + outFile); + + // Create the requested zip/jar file. + ZipOutputStream zos = null; + zos = new ZipOutputStream( + new FileOutputStream(outFile)); + + ZipEntry e = new ZipEntry(entryName); + zos.putNextEntry(e); + for (int j=0; j<50000; j++) { + zos.write((int)'a'); + } + zos.closeEntry(); + zos.close(); + zos = null; + } + + // Read it. + int len = (int)(new File(outFile).length()); + byte[] good = new byte[len]; + FileInputStream fis = new FileInputStream(outFile); + fis.read(good); + fis.close(); + fis = null; + + int endpos = len - ENDHDR; + int cenpos = u16(good, endpos+ENDOFF); + if (u32(good, cenpos) != CENSIG) throw new RuntimeException("Where's CENSIG?"); + + byte[] bad; + bad = good.clone(); + + // Corrupt it... + int pos = findInCEN(bad, cenpos, entryName); + + // What bad stuff are we doing to it? + // Store a 32-bit -1 in uncomp size. + bad[pos+0x18]=(byte)0xff; + bad[pos+0x19]=(byte)0xff; + bad[pos+0x1a]=(byte)0xff; + bad[pos+0x1b]=(byte)0xff; + + // Bad work complete, delete the original. + new File(outFile).delete(); + + // Write it. + FileOutputStream fos = new FileOutputStream(outFile); + fos.write(bad); + fos.close(); + fos = null; + + } catch (Exception e) { + e.printStackTrace(); + } + +} + + /* + * Scan Central Directory File Headers looking for the named entry. + */ + + static int findInCEN(byte[] bytes, int cenpos, String entryName) { + int pos = cenpos; + int nextPos = 0; + String filename = null; + do { + if (nextPos != 0) { + pos = nextPos; + } + System.out.println("entry at pos = " + pos); + if (u32(bytes, pos) != CENSIG) throw new RuntimeException ("entry not found in CEN or premature end..."); + + int csize = u32(bytes, pos+0x14); // +0x14 1 dword csize + int uncompsize = u32(bytes, pos+0x18); // +0x18 1 dword uncomp size + int filenameLength = u16(bytes, pos+0x1c); // +0x1c 1 word length of filename + int extraLength = u16(bytes, pos+0x1e); // +0x1e 1 world length of extra field + int commentLength = u16(bytes, pos+0x20); // +0x20 1 world length of file comment + filename = new String(bytes, pos+0x2e, filenameLength); // +0x2e chars of filename + int offset = u32(bytes, pos+0x2a); // +0x2a chars of filename + + System.out.println("filename = " + filename + "\ncsize = " + csize + + " uncomp.size = " + uncompsize +" file offset = " + offset); + nextPos = pos + 0x2e + filenameLength + extraLength + commentLength; + + } while (!filename.equals(entryName)); + + System.out.println("entry found at pos = " + pos); + return pos; + } + + static int u8(byte[] data, int offset) { + return data[offset]&0xff; + } + + static int u16(byte[] data, int offset) { + return u8(data,offset) + (u8(data,offset+1)<<8); + } + + static int u32(byte[] data, int offset) { + return u16(data,offset) + (u16(data,offset+2)<<16); + } + +} + diff --git a/test/tools/launcher/6842838/Test6842838.sh b/test/tools/launcher/6842838/Test6842838.sh new file mode 100644 index 0000000000000000000000000000000000000000..0d0ba756496e91d25062097818688ad0a099807f --- /dev/null +++ b/test/tools/launcher/6842838/Test6842838.sh @@ -0,0 +1,76 @@ +# +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, +# CA 95054 USA or visit www.sun.com if you need additional information or +# have any questions. +# + + +# @test Test6842838.sh +# @bug 6842838 +# @summary Test 6842838 64-bit launcher failure due to corrupt jar +# @compile CreateBadJar.java +# @run shell Test6842838.sh + +set -x + +if [ "${TESTJAVA}" = "" ]; then + PARENT=`dirname \`which java\`` + TESTJAVA=`dirname ${PARENT}` + printf "TESTJAVA not set. Test cannot execute. Failed.\n" +fi + +if [ "${TESTCLASSES}" = "" ]; then + printf "TESTCLASSES not set. Test cannot execute. Failed.\n" + exit 1 +fi + +# set platform-dependent variables +OS=`uname -s` +case "$OS" in + SunOS ) + NULL=/dev/null + PS=":" + FS="/" + JAVA_EXE=${TESTJAVA}${FS}bin${FS}sparcv9${FS}java + ;; + * ) + printf "Only testing on sparcv9 (use libumem to reliably catch buffer overrun)\n" + exit 0; + ;; +esac + +if [ ! -x ${JAVA_EXE} ]; then + printf "Warning: sparcv9 components not installed - skipping test.\n" + exit 0 +fi + +LIBUMEM=/lib/64/libumem.so +if [ ! -x ${LIBUMEM} ]; then + printf "Warning: libumem not installed - skipping test.\n" + exit 0 +fi + +BADFILE=newbadjar.jar +${JAVA_EXE} -version +${JAVA_EXE} -cp ${TESTCLASSES} CreateBadJar ${BADFILE} "META-INF/MANIFEST.MF" +LD_PRELOAD=${LIBUMEM} ${JAVA_EXE} -jar ${BADFILE} > test.out 2>&1 + +grep "Invalid or corrupt jarfile" test.out +exit $?