--- a/jdk/make/CreateJars.gmk Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/make/CreateJars.gmk Tue Oct 21 13:56:58 2014 -0700
@@ -111,6 +111,7 @@
# This value should exclude types destined for jars other than rt.jar and resources.jar.
# When building a Profile this value augments the profile specific exclusions
RT_JAR_EXCLUDES += \
+ com/oracle/security/ucrypto \
com/sun/codemodel \
com/sun/crypto/provider \
com/sun/istack/internal/tools \
--- a/jdk/make/CreateSecurityJars.gmk Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/make/CreateSecurityJars.gmk Tue Oct 21 13:56:58 2014 -0700
@@ -169,27 +169,25 @@
##########################################################################################
ifeq ($(OPENJDK_TARGET_OS), solaris)
- ifndef OPENJDK
- UCRYPTO_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/ucrypto.jar
- UCRYPTO_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/ucrypto.jar
+ UCRYPTO_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/ucrypto.jar
+ UCRYPTO_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/ucrypto.jar
- $(eval $(call SetupArchive,BUILD_UCRYPTO_JAR, , \
- SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.ucrypto, \
- SUFFIXES := .class, \
- INCLUDES := com/oracle/security/ucrypto, \
- JAR := $(UCRYPTO_JAR_UNSIGNED), \
- MANIFEST := $(JCE_MANIFEST), \
- SKIP_METAINF := true))
+ $(eval $(call SetupArchive,BUILD_UCRYPTO_JAR, , \
+ SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.ucrypto, \
+ SUFFIXES := .class, \
+ INCLUDES := com/oracle/security/ucrypto, \
+ JAR := $(UCRYPTO_JAR_UNSIGNED), \
+ MANIFEST := $(JCE_MANIFEST), \
+ SKIP_METAINF := true))
- $(UCRYPTO_JAR_UNSIGNED): $(JCE_MANIFEST)
+ $(UCRYPTO_JAR_UNSIGNED): $(JCE_MANIFEST)
- $(UCRYPTO_JAR_DST): $(UCRYPTO_JAR_UNSIGNED)
+ $(UCRYPTO_JAR_DST): $(UCRYPTO_JAR_UNSIGNED)
$(install-file)
- TARGETS += $(UCRYPTO_JAR_UNSIGNED) $(UCRYPTO_JAR_DST)
+ TARGETS += $(UCRYPTO_JAR_UNSIGNED) $(UCRYPTO_JAR_DST)
- endif
endif
all: $(TARGETS)
--- a/jdk/make/copy/Copy-java.base.gmk Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/make/copy/Copy-java.base.gmk Tue Oct 21 13:56:58 2014 -0700
@@ -170,10 +170,7 @@
ifeq ($(OPENJDK_TARGET_OS), windows)
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
-endif
-ifndef OPENJDK
- # if $(OPENJDK_TARGET_OS) is windows or solaris
- ifneq ($(findstring $(OPENJDK_TARGET_OS), windows solaris), )
+ ifndef OPENJDK
POLICY_SRC_LIST += $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/conf/security/java.policy
endif
endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/copy/Copy-jdk.crypto.ucrypto.gmk Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,49 @@
+#
+# Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include CopyCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+
+ UCRYPTO_CFG_SRC := $(JDK_TOPDIR)/src/jdk.crypto.ucrypto/solaris/conf/security/ucrypto-solaris.cfg
+ UCRYPTO_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/ucrypto-solaris.cfg
+
+ $(UCRYPTO_CFG_DST): $(UCRYPTO_CFG_SRC)
+ $(call install-file)
+
+ SECURITY_UCRYPTO_CONF_FILES += $(UCRYPTO_CFG_DST)
+
+endif
+
+################################################################################
+
+jdk.crypto.ucrypto: $(SECURITY_UCRYPTO_CONF_FILES)
+
+all: jdk.crypto.ucrypto
+
+.PHONY: all jdk.crypto.ucrypto
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,62 @@
+#
+# Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+# particular file as subject to the "Classpath" exception as provided
+# by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+#
+
+include $(SPEC)
+include $(JDK_TOPDIR)/make/lib/LibCommon.gmk
+
+################################################################################
+
+ifeq ($(OPENJDK_TARGET_OS), solaris)
+
+ LIBJ2UCRYPTO_SRC := $(JDK_TOPDIR)/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto
+
+ $(eval $(call SetupNativeCompilation,BUILD_LIBJ2UCRYPTO, \
+ LIBRARY := j2ucrypto, \
+ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
+ SRC := $(LIBJ2UCRYPTO_SRC), \
+ LANG := C, \
+ OPTIMIZATION := LOW, \
+ CFLAGS := $(CFLAGS_JDKLIB) \
+ $(addprefix -I, $(LIBJ2UCRYPTO_SRC)), \
+ MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libj2ucrypto/mapfile-vers, \
+ LDFLAGS := $(LDFLAGS_JDKLIB), \
+ LDFLAGS_SUFFIX := $(LIBDL), \
+ LDFLAGS_SUFFIX_solaris := -lc, \
+ OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libj2ucrypto, \
+ DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
+
+ $(BUILD_LIBJ2UCRYPTO): $(BUILD_LIBJAVA)
+
+ SECURITY_UCRYPTO_LIBRARIES += $(BUILD_LIBJ2UCRYPTO)
+
+endif
+
+################################################################################
+
+jdk.crypto.ucrypto: $(SECURITY_UCRYPTO_LIBRARIES)
+
+all: jdk.crypto.ucrypto
+
+.PHONY: all jdk.crypto.ucrypto
--- a/jdk/make/mapfiles/libnet/mapfile-vers Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/make/mapfiles/libnet/mapfile-vers Tue Oct 21 13:56:58 2014 -0700
@@ -110,6 +110,8 @@
NET_Bind;
NET_MapSocketOption;
NET_Wait;
+ NET_EnableFastTcpLoopback;
+ NET_ThrowNew;
ipv6_available;
initInetAddressIDs;
--- a/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/share/classes/java/security/ProtectionDomain.java Tue Oct 21 13:56:58 2014 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. 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,6 +25,7 @@
package java.security;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
@@ -447,24 +448,37 @@
/**
* Used for storing ProtectionDomains as keys in a Map.
*/
- final class Key {}
+ final static class Key {}
+
+ // A cache of ProtectionDomains and their Permissions
+ private static class PDCache implements ProtectionDomainCache {
+ // We must wrap the PermissionCollection in a WeakReference as there
+ // are some PermissionCollections which contain strong references
+ // back to a ProtectionDomain and otherwise would never be removed
+ // from the WeakHashMap
+ private final Map<Key, WeakReference<PermissionCollection>>
+ map = new WeakHashMap<>();
+
+ @Override
+ public synchronized void put(ProtectionDomain pd,
+ PermissionCollection pc) {
+ map.put(pd == null ? null : pd.key, new WeakReference<>(pc));
+ }
+
+ @Override
+ public synchronized PermissionCollection get(ProtectionDomain pd) {
+ WeakReference<PermissionCollection> ref =
+ map.get(pd == null ? null : pd.key);
+ return ref == null ? null : ref.get();
+ }
+ }
static {
SharedSecrets.setJavaSecurityProtectionDomainAccess(
new JavaSecurityProtectionDomainAccess() {
+ @Override
public ProtectionDomainCache getProtectionDomainCache() {
- return new ProtectionDomainCache() {
- private final Map<Key, PermissionCollection> map =
- Collections.synchronizedMap
- (new WeakHashMap<Key, PermissionCollection>());
- public void put(ProtectionDomain pd,
- PermissionCollection pc) {
- map.put((pd == null ? null : pd.key), pc);
- }
- public PermissionCollection get(ProtectionDomain pd) {
- return pd == null ? map.get(null) : map.get(pd.key);
- }
- };
+ return new PDCache();
}
});
}
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Tue Oct 21 13:56:58 2014 -0700
@@ -50,30 +50,8 @@
// set to true if exclusive binding is on for Windows
private static final boolean exclusiveBind;
- static {
- int availLevel = isExclusiveBindAvailable();
- if (availLevel >= 0) {
- String exclBindProp =
- java.security.AccessController.doPrivileged(
- new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(
- "sun.net.useExclusiveBind");
- }
- });
- if (exclBindProp != null) {
- exclusiveBind = exclBindProp.length() == 0 ?
- true : Boolean.parseBoolean(exclBindProp);
- } else if (availLevel == 1) {
- exclusiveBind = true;
- } else {
- exclusiveBind = false;
- }
- } else {
- exclusiveBind = false;
- }
- }
+ // set to true if the fast tcp loopback should be enabled on Windows
+ private static final boolean fastLoopback;
// -- Miscellaneous utilities --
@@ -391,6 +369,23 @@
}
}
+ public static boolean isFastTcpLoopbackRequested() {
+ String loopbackProp = java.security.AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return System.getProperty("jdk.net.useFastTcpLoopback");
+ }
+ });
+ boolean enable;
+ if ("".equals(loopbackProp)) {
+ enable = true;
+ } else {
+ enable = Boolean.parseBoolean(loopbackProp);
+ }
+ return enable;
+ }
+
// -- Socket operations --
private static native boolean isIPv6Available0();
@@ -413,15 +408,16 @@
throws IOException {
boolean preferIPv6 = isIPv6Available() &&
(family != StandardProtocolFamily.INET);
- return IOUtil.newFD(socket0(preferIPv6, stream, false));
+ return IOUtil.newFD(socket0(preferIPv6, stream, false, fastLoopback));
}
static FileDescriptor serverSocket(boolean stream) {
- return IOUtil.newFD(socket0(isIPv6Available(), stream, true));
+ return IOUtil.newFD(socket0(isIPv6Available(), stream, true, fastLoopback));
}
// Due to oddities SO_REUSEADDR on windows reuse is ignored
- private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse);
+ private static native int socket0(boolean preferIPv6, boolean stream, boolean reuse,
+ boolean fastLoopback);
public static void bind(FileDescriptor fd, InetAddress addr, int port)
throws IOException
@@ -634,4 +630,30 @@
POLLCONN = pollconnValue();
}
+ static {
+ int availLevel = isExclusiveBindAvailable();
+ if (availLevel >= 0) {
+ String exclBindProp =
+ java.security.AccessController.doPrivileged(
+ new PrivilegedAction<String>() {
+ @Override
+ public String run() {
+ return System.getProperty(
+ "sun.net.useExclusiveBind");
+ }
+ });
+ if (exclBindProp != null) {
+ exclusiveBind = exclBindProp.length() == 0 ?
+ true : Boolean.parseBoolean(exclBindProp);
+ } else if (availLevel == 1) {
+ exclusiveBind = true;
+ } else {
+ exclusiveBind = false;
+ }
+ } else {
+ exclusiveBind = false;
+ }
+
+ fastLoopback = isFastTcpLoopbackRequested();
+ }
}
--- a/jdk/src/java.base/share/conf/security/java.policy Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/share/conf/security/java.policy Tue Oct 21 13:56:58 2014 -0700
@@ -25,6 +25,18 @@
permission java.security.AllPermission;
};
+grant codeBase "file:${java.home}/lib/ext/ucrypto.jar" {
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.security.*";
+ permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch";
+ permission java.lang.RuntimePermission "loadLibrary.j2ucrypto";
+ // need "com.oracle.security.ucrypto.debug" for debugging
+ permission java.util.PropertyPermission "*", "read";
+ permission java.security.SecurityPermission "putProviderProperty.OracleUcrypto";
+ permission java.security.SecurityPermission "clearProviderProperties.OracleUcrypto";
+ permission java.security.SecurityPermission "removeProviderProperty.OracleUcrypto";
+ permission java.io.FilePermission "${java.home}/lib/security/ucrypto-solaris.cfg", "read";
+};
+
grant codeBase "file:${java.home}/lib/ext/sunec.jar" {
permission java.lang.RuntimePermission "accessClassInPackage.sun.security.*";
permission java.lang.RuntimePermission "loadLibrary.sunec";
--- a/jdk/src/java.base/share/native/libnet/net_util.h Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/share/native/libnet/net_util.h Tue Oct 21 13:56:58 2014 -0700
@@ -184,9 +184,13 @@
JNIEXPORT int JNICALL
NET_MapSocketOptionV6(jint cmd, int *level, int *optname);
+JNIEXPORT jint JNICALL
+NET_EnableFastTcpLoopback(int fd);
+
int getScopeID (struct sockaddr *);
int cmpScopeID (unsigned int, struct sockaddr *);
unsigned short in_cksum(unsigned short *addr, int len);
+
#endif /* NET_UTILS_H */
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Tue Oct 21 13:56:58 2014 -0700
@@ -790,6 +790,11 @@
#endif
}
+JNIEXPORT jint JNICALL
+NET_EnableFastTcpLoopback(int fd) {
+ return 0;
+}
+
/* In the case of an IPv4 Inetaddress this method will return an
* IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
* Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
--- a/jdk/src/java.base/unix/native/libnio/ch/Net.c Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c Tue Oct 21 13:56:58 2014 -0700
@@ -188,7 +188,7 @@
JNIEXPORT int JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
- jboolean stream, jboolean reuse)
+ jboolean stream, jboolean reuse, jboolean ignored)
{
int fd;
int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c Tue Oct 21 13:56:58 2014 -0700
@@ -29,6 +29,9 @@
#include "net_util.h"
#include "jni.h"
+// Taken from mstcpip.h in Windows SDK 8.0 or newer.
+#define SIO_LOOPBACK_FAST_PATH _WSAIOW(IOC_VENDOR,16)
+
#ifndef IPTOS_TOS_MASK
#define IPTOS_TOS_MASK 0x1e
#endif
@@ -844,6 +847,25 @@
}
}
+/**
+ * Enables SIO_LOOPBACK_FAST_PATH
+ */
+JNIEXPORT jint JNICALL
+NET_EnableFastTcpLoopback(int fd) {
+ int enabled = 1;
+ DWORD result_byte_count = -1;
+ int result = WSAIoctl(fd,
+ SIO_LOOPBACK_FAST_PATH,
+ &enabled,
+ sizeof(enabled),
+ NULL,
+ 0,
+ &result_byte_count,
+ NULL,
+ NULL);
+ return result == SOCKET_ERROR ? WSAGetLastError() : 0;
+}
+
/* If address types is IPv6, then IPv6 must be available. Otherwise
* no address can be generated. In the case of an IPv4 Inetaddress this
* method will return an IPv4 mapped address where IPv6 is available and
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c Tue Oct 21 13:56:58 2014 -0700
@@ -127,7 +127,7 @@
JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
- jboolean stream, jboolean reuse)
+ jboolean stream, jboolean reuse, jboolean fastLoopback)
{
SOCKET s;
int domain = (preferIPv6) ? AF_INET6 : AF_INET;
@@ -152,6 +152,20 @@
NET_ThrowNew(env, WSAGetLastError(), "socket");
}
+ if (stream && fastLoopback) {
+ static int loopback_available = 1;
+ if (loopback_available) {
+ int rv = NET_EnableFastTcpLoopback((jint)s);
+ if (rv) {
+ if (rv == WSAEOPNOTSUPP) {
+ loopback_available = 0;
+ } else {
+ NET_ThrowNew(env, rv, "fastLoopback");
+ }
+ }
+ }
+ }
+
return (jint)s;
}
--- a/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetWarning.java Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/src/java.sql.rowset/share/classes/javax/sql/rowset/RowSetWarning.java Tue Oct 21 13:56:58 2014 -0700
@@ -56,11 +56,6 @@
public class RowSetWarning extends SQLException {
/**
- * RowSetWarning object handle.
- */
- private RowSetWarning rwarning;
-
- /**
* Constructs a <code>RowSetWarning</code> object
* with the given value for the reason; SQLState defaults to null,
* and vendorCode defaults to 0.
@@ -128,7 +123,15 @@
* @see #setNextWarning
*/
public RowSetWarning getNextWarning() {
- return rwarning;
+ SQLException warning = getNextException();
+ if ( warning == null || warning instanceof RowSetWarning) {
+ return (RowSetWarning)warning;
+ } else {
+ // The chained value isn't a RowSetWarning.
+ // This is a programming error by whoever added it to
+ // the RowSetWarning chain. We throw a Java "Error".
+ throw new Error("RowSetWarning chain holds value that is not a RowSetWarning: ");
+ }
}
/**
@@ -141,7 +144,7 @@
* @see #getNextWarning
*/
public void setNextWarning(RowSetWarning warning) {
- rwarning = warning;
+ setNextException(warning);
}
static final long serialVersionUID = 6678332766434564774L;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/CipherContextRef.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.lang.ref.*;
+
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Internal class for context resource clean up.
+ *
+ * @since 1.9
+ */
+final class CipherContextRef extends PhantomReference<NativeCipher>
+ implements Comparable<CipherContextRef> {
+
+ private static ReferenceQueue<NativeCipher> refQueue =
+ new ReferenceQueue<NativeCipher>();
+
+ // Needed to keep these references from being GC'ed until when their
+ // referents are GC'ed so we can do post-mortem processing
+ private static Set<CipherContextRef> refList =
+ new ConcurrentSkipListSet<CipherContextRef>();
+
+ final long id;
+ final boolean encrypt;
+
+ private static void drainRefQueueBounded() {
+ while (true) {
+ CipherContextRef next = (CipherContextRef) refQueue.poll();
+ if (next == null) break;
+ next.dispose(true);
+ }
+ }
+
+ CipherContextRef(NativeCipher nc, long id, boolean encrypt) {
+ super(nc, refQueue);
+ this.id = id;
+ this.encrypt = encrypt;
+ refList.add(this);
+ UcryptoProvider.debug("Resource: trace CipherCtxt " + this.id);
+ drainRefQueueBounded();
+ }
+
+ public int compareTo(CipherContextRef other) {
+ if (this.id == other.id) {
+ return 0;
+ } else {
+ return (this.id < other.id) ? -1 : 1;
+ }
+ }
+
+ void dispose(boolean doCancel) {
+ refList.remove(this);
+ try {
+ if (doCancel) {
+ UcryptoProvider.debug("Resource: cancel CipherCtxt " + id);
+ int k = NativeCipher.nativeFinal(id, encrypt, null, 0);
+ if (k < 0) {
+ UcryptoProvider.debug
+ ("Resource: error cancelling CipherCtxt " + id +
+ " " + new UcryptoException(-k).getMessage());
+ }
+ } else {
+ UcryptoProvider.debug("Resource: untrace CipherCtxt " + id);
+ }
+ } finally {
+ this.clear();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/Config.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.io.*;
+import static java.io.StreamTokenizer.*;
+import java.math.BigInteger;
+import java.util.*;
+
+import java.security.*;
+
+import sun.security.action.GetPropertyAction;
+import sun.security.util.PropertyExpander;
+
+import sun.security.pkcs11.wrapper.*;
+
+/**
+ * Configuration container and file parsing.
+ *
+ * Currently, there is only one supported entry "disabledServices"
+ * for disabling crypto services. Its syntax is as follows:
+ *
+ * disabledServices = {
+ * <ServiceType>.<Algorithm>
+ * ...
+ * }
+ *
+ * where <Service> can be "MessageDigest", "Cipher", etc. and <Algorithm>
+ * reprepresents the value that's passed into the various getInstance() calls.
+ *
+ * @since 1.9
+ */
+final class Config {
+
+ // Reader and StringTokenizer used during parsing
+ private Reader reader;
+
+ private StreamTokenizer st;
+
+ private Set<String> parsedKeywords;
+
+ // set of disabled crypto services, e.g. MessageDigest.SHA1, or
+ // Cipher.AES/ECB/PKCS5Padding
+ private Set<String> disabledServices;
+
+ Config(String filename) throws IOException {
+ FileInputStream in = new FileInputStream(expand(filename));
+ reader = new BufferedReader(new InputStreamReader(in));
+ parsedKeywords = new HashSet<String>();
+ st = new StreamTokenizer(reader);
+ setupTokenizer();
+ parse();
+ }
+
+ String[] getDisabledServices() {
+ if (disabledServices != null) {
+ return disabledServices.toArray(new String[disabledServices.size()]);
+ } else {
+ return new String[0];
+ }
+ }
+
+ private static String expand(final String s) throws IOException {
+ try {
+ return PropertyExpander.expand(s);
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage());
+ }
+ }
+
+ private void setupTokenizer() {
+ st.resetSyntax();
+ st.wordChars('a', 'z');
+ st.wordChars('A', 'Z');
+ st.wordChars('0', '9');
+ st.wordChars(':', ':');
+ st.wordChars('.', '.');
+ st.wordChars('_', '_');
+ st.wordChars('-', '-');
+ st.wordChars('/', '/');
+ st.wordChars('\\', '\\');
+ st.wordChars('$', '$');
+ st.wordChars('{', '{'); // need {} for property subst
+ st.wordChars('}', '}');
+ st.wordChars('*', '*');
+ st.wordChars('+', '+');
+ st.wordChars('~', '~');
+ // XXX check ASCII table and add all other characters except special
+
+ // special: #="(),
+ st.whitespaceChars(0, ' ');
+ st.commentChar('#');
+ st.eolIsSignificant(true);
+ st.quoteChar('\"');
+ }
+
+ private ConfigException excToken(String msg) {
+ return new ConfigException(msg + " " + st);
+ }
+
+ private ConfigException excLine(String msg) {
+ return new ConfigException(msg + ", line " + st.lineno());
+ }
+
+ private void parse() throws IOException {
+ while (true) {
+ int token = nextToken();
+ if (token == TT_EOF) {
+ break;
+ }
+ if (token == TT_EOL) {
+ continue;
+ }
+ if (token != TT_WORD) {
+ throw excToken("Unexpected token:");
+ }
+ String word = st.sval;
+ if (word.equals("disabledServices")) {
+ parseDisabledServices(word);
+ } else {
+ throw new ConfigException
+ ("Unknown keyword '" + word + "', line " + st.lineno());
+ }
+ parsedKeywords.add(word);
+ }
+ reader.close();
+ reader = null;
+ st = null;
+ parsedKeywords = null;
+ }
+
+ //
+ // Parsing helper methods
+ //
+ private int nextToken() throws IOException {
+ int token = st.nextToken();
+ return token;
+ }
+
+ private void parseEquals() throws IOException {
+ int token = nextToken();
+ if (token != '=') {
+ throw excToken("Expected '=', read");
+ }
+ }
+
+ private void parseOpenBraces() throws IOException {
+ while (true) {
+ int token = nextToken();
+ if (token == TT_EOL) {
+ continue;
+ }
+ if ((token == TT_WORD) && st.sval.equals("{")) {
+ return;
+ }
+ throw excToken("Expected '{', read");
+ }
+ }
+
+ private boolean isCloseBraces(int token) {
+ return (token == TT_WORD) && st.sval.equals("}");
+ }
+
+ private void checkDup(String keyword) throws IOException {
+ if (parsedKeywords.contains(keyword)) {
+ throw excLine(keyword + " must only be specified once");
+ }
+ }
+
+ private void parseDisabledServices(String keyword) throws IOException {
+ checkDup(keyword);
+ disabledServices = new HashSet<String>();
+ parseEquals();
+ parseOpenBraces();
+ while (true) {
+ int token = nextToken();
+ if (isCloseBraces(token)) {
+ break;
+ }
+ if (token == TT_EOL) {
+ continue;
+ }
+ if (token != TT_WORD) {
+ throw excToken("Expected mechanism, read");
+ }
+ disabledServices.add(st.sval);
+ }
+ }
+}
+
+class ConfigException extends IOException {
+ private static final long serialVersionUID = 254492758127673194L;
+ ConfigException(String msg) {
+ super(msg);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/GCMParameters.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.security.AlgorithmParametersSpi;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import javax.crypto.spec.GCMParameterSpec;
+import sun.security.util.*;
+
+/**
+ * This class implements the parameter set used with GCM mode
+ * which is defined in RFC5084 as follows:
+ *
+ * <pre>
+ * GCMParameters ::= SEQUENCE {
+ * aes-nonce OCTET STRING, -- recommended size is 12 octets
+ * aes-ICVlen AES-GCM-ICVlen DEFAULT 12 }
+ *
+ * where
+ * AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16)
+ * NOTE: however, NIST 800-38D also lists 4 (32bit) and 8 (64bit)
+ * as possible AES-GCM-ICVlen values, so we allow all 6 values.
+ * </pre>
+ *
+ * @since 1.9
+ */
+public final class GCMParameters extends AlgorithmParametersSpi {
+
+ private byte[] iv; // i.e. aes-nonce
+ private int tLen; // i.e. aes-ICVlen, in bytes
+
+ public GCMParameters() {}
+
+ private void setValues(byte[] iv, int tLen) throws IOException {
+ if (iv == null) {
+ throw new IOException("IV cannot be null");
+ }
+ if (tLen != 4 && tLen != 8 && (tLen < 12 || tLen > 16)) {
+ throw new IOException("Unsupported tag length: " + tLen);
+ }
+ this.iv = iv;
+ this.tLen = tLen;
+ }
+
+ protected byte[] engineGetEncoded() throws IOException {
+ DerOutputStream out = new DerOutputStream();
+ DerOutputStream bytes = new DerOutputStream();
+
+ bytes.putOctetString(iv);
+ bytes.putInteger(tLen);
+ out.write(DerValue.tag_Sequence, bytes);
+ return out.toByteArray();
+ }
+
+ protected byte[] engineGetEncoded(String format) throws IOException {
+ // ignore format for now
+ return engineGetEncoded();
+ }
+
+ protected <T extends AlgorithmParameterSpec>
+ T engineGetParameterSpec(Class<T> paramSpec)
+ throws InvalidParameterSpecException {
+ if (GCMParameterSpec.class.isAssignableFrom(paramSpec)) {
+ return paramSpec.cast(new GCMParameterSpec(tLen*8, iv.clone()));
+ } else {
+ throw new InvalidParameterSpecException
+ ("Inappropriate parameter specification");
+ }
+ }
+
+ protected void engineInit(AlgorithmParameterSpec paramSpec)
+ throws InvalidParameterSpecException {
+ if (!(paramSpec instanceof GCMParameterSpec)) {
+ throw new InvalidParameterSpecException
+ ("Inappropriate parameter specification");
+ }
+ GCMParameterSpec gcmSpec = (GCMParameterSpec) paramSpec;
+ try {
+ setValues(gcmSpec.getIV(), gcmSpec.getTLen()/8);
+ } catch (IOException ioe) {
+ throw new InvalidParameterSpecException(ioe.getMessage());
+ }
+ }
+
+ protected void engineInit(byte[] encoded) throws IOException {
+ DerValue val = new DerValue(encoded);
+ if (val.tag == DerValue.tag_Sequence) {
+ val.data.reset();
+ setValues(val.data.getOctetString(), val.data.getInteger());
+ } else {
+ throw new IOException("GCM parameter parsing error: SEQ tag expected");
+ }
+ }
+
+ protected void engineInit(byte[] encoded, String format)
+ throws IOException {
+ // ignore format for now
+ engineInit(encoded);
+ }
+
+ protected String engineToString() {
+ return ("IV=" + Arrays.toString(iv) + ", tLen=" + tLen * 8);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.lang.ref.*;
+
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Cipher wrapper class utilizing ucrypto APIs. This class currently supports
+ * - AES/ECB/NOPADDING
+ * - AES/CBC/NOPADDING
+ * - AES/CTR/NOPADDING
+ * - AES/CFB128/NOPADDING
+ * (Support for GCM mode is inside the child class NativeGCMCipher)
+ *
+ * @since 1.9
+ */
+class NativeCipher extends CipherSpi {
+
+ // public implementation classes
+ public static final class AesEcbNoPadding extends NativeCipher {
+ public AesEcbNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_ECB);
+ }
+ }
+ public static final class AesCbcNoPadding extends NativeCipher {
+ public AesCbcNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_CBC);
+ }
+ }
+ public static final class AesCtrNoPadding extends NativeCipher {
+ public AesCtrNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_CTR);
+ }
+ }
+ public static final class AesCfb128NoPadding extends NativeCipher {
+ public AesCfb128NoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_CFB128);
+ }
+ }
+
+ // public implementation classes with fixed key sizes
+ public static final class Aes128EcbNoPadding extends NativeCipher {
+ public Aes128EcbNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_ECB, 16);
+ }
+ }
+ public static final class Aes128CbcNoPadding extends NativeCipher {
+ public Aes128CbcNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_CBC, 16);
+ }
+ }
+ public static final class Aes192EcbNoPadding extends NativeCipher {
+ public Aes192EcbNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_ECB, 24);
+ }
+ }
+ public static final class Aes192CbcNoPadding extends NativeCipher {
+ public Aes192CbcNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_CBC, 24);
+ }
+ }
+ public static final class Aes256EcbNoPadding extends NativeCipher {
+ public Aes256EcbNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_ECB, 32);
+ }
+ }
+ public static final class Aes256CbcNoPadding extends NativeCipher {
+ public Aes256CbcNoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_CBC, 32);
+ }
+ }
+
+ // ok as constants since AES is all we support
+ public static final int AES_BLOCK_SIZE = 16;
+ public static final String AES_KEY_ALGO = "AES";
+
+ // fields set in constructor
+ protected final UcryptoMech mech;
+ protected String keyAlgo;
+ protected int blockSize;
+ protected int fixedKeySize;
+
+ //
+ // fields (re)set in every init()
+ //
+ protected CipherContextRef pCtxt = null;
+ protected byte[] keyValue = null;
+ protected byte[] iv = null;
+ protected boolean initialized = false;
+ protected boolean encrypt = true;
+ protected int bytesBuffered = 0;
+
+ // private utility methods for key re-construction
+ private static final PublicKey constructPublicKey(byte[] encodedKey,
+ String encodedKeyAlgorithm)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ PublicKey key = null;
+ try {
+ KeyFactory keyFactory =
+ KeyFactory.getInstance(encodedKeyAlgorithm);
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(encodedKey);
+ key = keyFactory.generatePublic(keySpec);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new NoSuchAlgorithmException("No provider found for " +
+ encodedKeyAlgorithm +
+ " KeyFactory");
+ } catch (InvalidKeySpecException ikse) {
+ // Should never happen
+ throw new InvalidKeyException("Cannot construct public key", ikse);
+ }
+ return key;
+ }
+
+ private static final PrivateKey constructPrivateKey(byte[] encodedKey,
+ String encodedKeyAlgorithm)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ PrivateKey key = null;
+ try {
+ KeyFactory keyFactory =
+ KeyFactory.getInstance(encodedKeyAlgorithm);
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
+ key = keyFactory.generatePrivate(keySpec);
+ } catch (NoSuchAlgorithmException nsae) {
+ throw new NoSuchAlgorithmException("No provider found for " +
+ encodedKeyAlgorithm +
+ " KeyFactory");
+ } catch (InvalidKeySpecException ikse) {
+ // Should never happen
+ throw new InvalidKeyException("Cannot construct private key", ikse);
+ }
+ return key;
+ }
+
+ private static final SecretKey constructSecretKey(byte[] encodedKey,
+ String encodedKeyAlgorithm) {
+ return new SecretKeySpec(encodedKey, encodedKeyAlgorithm);
+ }
+
+ // package-private utility method for general key re-construction
+ static final Key constructKey(int keyType, byte[] encodedKey,
+ String encodedKeyAlgorithm)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+ Key result = null;
+ switch (keyType) {
+ case Cipher.SECRET_KEY:
+ result = constructSecretKey(encodedKey,
+ encodedKeyAlgorithm);
+ break;
+ case Cipher.PRIVATE_KEY:
+ result = constructPrivateKey(encodedKey,
+ encodedKeyAlgorithm);
+ break;
+ case Cipher.PUBLIC_KEY:
+ result = constructPublicKey(encodedKey,
+ encodedKeyAlgorithm);
+ break;
+ }
+ return result;
+ }
+
+ NativeCipher(UcryptoMech mech, int fixedKeySize) throws NoSuchAlgorithmException {
+ this.mech = mech;
+ // defaults to AES - the only supported symmetric cipher algo
+ this.blockSize = AES_BLOCK_SIZE;
+ this.keyAlgo = AES_KEY_ALGO;
+ this.fixedKeySize = fixedKeySize;
+ }
+
+ NativeCipher(UcryptoMech mech) throws NoSuchAlgorithmException {
+ this(mech, -1);
+ }
+
+ @Override
+ protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+ // Disallow change of mode for now since currently it's explicitly
+ // defined in transformation strings
+ throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineSetPadding(String padding)
+ throws NoSuchPaddingException {
+ // Disallow change of padding for now since currently it's explicitly
+ // defined in transformation strings
+ throw new NoSuchPaddingException("Unsupported padding " + padding);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineGetBlockSize() {
+ return blockSize;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineGetOutputSize(int inputLen) {
+ return getOutputSizeByOperation(inputLen, true);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineGetIV() {
+ return (iv != null? iv.clone() : null);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized AlgorithmParameters engineGetParameters() {
+ AlgorithmParameters params = null;
+ try {
+ if (iv != null) {
+ IvParameterSpec ivSpec = new IvParameterSpec(iv.clone());
+ params = AlgorithmParameters.getInstance(keyAlgo);
+ params.init(ivSpec);
+ }
+ } catch (GeneralSecurityException e) {
+ // NoSuchAlgorithmException, NoSuchProviderException
+ // InvalidParameterSpecException
+ throw new UcryptoException("Could not encode parameters", e);
+ }
+ return params;
+ }
+
+ @Override
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ return checkKey(key) * 8;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key,
+ SecureRandom random) throws InvalidKeyException {
+ try {
+ engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new InvalidKeyException("init() failed", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ checkKey(key);
+ if (opmode != Cipher.ENCRYPT_MODE &&
+ opmode != Cipher.DECRYPT_MODE &&
+ opmode != Cipher.WRAP_MODE &&
+ opmode != Cipher.UNWRAP_MODE) {
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported mode: " + opmode);
+ }
+ boolean doEncrypt =
+ (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
+
+ byte[] ivBytes = null;
+ if (mech == UcryptoMech.CRYPTO_AES_ECB) {
+ if (params != null) {
+ throw new InvalidAlgorithmParameterException
+ ("No Parameters for ECB mode");
+ }
+ } else {
+ if (params != null) {
+ if (!(params instanceof IvParameterSpec)) {
+ throw new InvalidAlgorithmParameterException
+ ("IvParameterSpec required");
+ } else {
+ ivBytes = ((IvParameterSpec) params).getIV();
+ if (ivBytes.length != blockSize) {
+ throw new InvalidAlgorithmParameterException
+ ("Wrong IV length: must be " + blockSize +
+ " bytes long");
+ }
+ }
+ } else {
+ if (encrypt) {
+ // generate IV if none supplied for encryption
+ ivBytes = new byte[blockSize];
+ new SecureRandom().nextBytes(ivBytes);
+ } else {
+ throw new InvalidAlgorithmParameterException
+ ("Parameters required for decryption");
+ }
+ }
+ }
+ init(doEncrypt, key.getEncoded().clone(), ivBytes);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key,
+ AlgorithmParameters params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ AlgorithmParameterSpec spec = null;
+ if (params != null) {
+ try {
+ spec = params.getParameterSpec(IvParameterSpec.class);
+ } catch (InvalidParameterSpecException iaps) {
+ throw new InvalidAlgorithmParameterException(iaps);
+ }
+ }
+ engineInit(opmode, key, spec, random);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineUpdate(byte[] in, int ofs, int len) {
+ byte[] out = new byte[getOutputSizeByOperation(len, false)];
+ int n = update(in, ofs, len, out, 0);
+ if (n == 0) {
+ return null;
+ } else if (out.length != n) {
+ out = Arrays.copyOf(out, n);
+ }
+ return out;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineUpdate(byte[] in, int inOfs, int inLen,
+ byte[] out, int outOfs) throws ShortBufferException {
+ int min = getOutputSizeByOperation(inLen, false);
+ if (out.length - outOfs < min) {
+ throw new ShortBufferException("min " + min + "-byte buffer needed");
+ }
+ return update(in, inOfs, inLen, out, outOfs);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineUpdateAAD(byte[] src, int ofs, int len)
+ throws IllegalStateException {
+ throw new IllegalStateException("No AAD can be supplied");
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineUpdateAAD(ByteBuffer src)
+ throws IllegalStateException {
+ throw new IllegalStateException("No AAD can be supplied");
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineDoFinal(byte[] in, int ofs, int len)
+ throws IllegalBlockSizeException, BadPaddingException {
+ byte[] out = new byte[getOutputSizeByOperation(len, true)];
+ try {
+ // delegate to the other engineDoFinal(...) method
+ int k = engineDoFinal(in, ofs, len, out, 0);
+ if (out.length != k) {
+ out = Arrays.copyOf(out, k);
+ }
+ return out;
+ } catch (ShortBufferException e) {
+ throw new UcryptoException("Internal Error", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineDoFinal(byte[] in, int inOfs, int inLen,
+ byte[] out, int outOfs)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ int k = 0;
+ int min = getOutputSizeByOperation(inLen, true);
+ if (out.length - outOfs < min) {
+ throw new ShortBufferException("min " + min + "-byte buffer needed");
+ }
+ if (inLen > 0) {
+ k = update(in, inOfs, inLen, out, outOfs);
+ outOfs += k;
+ }
+ k += doFinal(out, outOfs);
+ return k;
+ }
+
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineWrap(Key key)
+ throws IllegalBlockSizeException, InvalidKeyException {
+ byte[] result = null;
+ try {
+ byte[] encodedKey = key.getEncoded();
+ if ((encodedKey == null) || (encodedKey.length == 0)) {
+ throw new InvalidKeyException("Cannot get an encoding of " +
+ "the key to be wrapped");
+ }
+ result = engineDoFinal(encodedKey, 0, encodedKey.length);
+ } catch (BadPaddingException e) {
+ // Should never happen for key wrapping
+ throw new UcryptoException("Internal Error" , e);
+ }
+ return result;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized Key engineUnwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm, int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ byte[] encodedKey;
+ Key result = null;
+ try {
+ encodedKey = engineDoFinal(wrappedKey, 0,
+ wrappedKey.length);
+ } catch (Exception e) {
+ throw (InvalidKeyException)
+ (new InvalidKeyException()).initCause(e);
+ }
+
+ return constructKey(wrappedKeyType, encodedKey, wrappedKeyAlgorithm);
+ }
+
+ final int checkKey(Key key) throws InvalidKeyException {
+ if (key == null || key.getEncoded() == null) {
+ throw new InvalidKeyException("Key cannot be null");
+ } else {
+ // check key algorithm and format
+ if (!keyAlgo.equalsIgnoreCase(key.getAlgorithm())) {
+ throw new InvalidKeyException("Key algorithm must be " +
+ keyAlgo);
+ }
+ if (!"RAW".equalsIgnoreCase(key.getFormat())) {
+ throw new InvalidKeyException("Key format must be RAW");
+ }
+ int keyLen = key.getEncoded().length;
+ if (fixedKeySize == -1) {
+ // all 3 AES key lengths are allowed
+ if (keyLen != 16 && keyLen != 24 && keyLen != 32) {
+ throw new InvalidKeyException("Key size is not valid");
+ }
+ } else {
+ if (keyLen != fixedKeySize) {
+ throw new InvalidKeyException("Only " + fixedKeySize +
+ "-byte keys are accepted");
+ }
+ }
+ // return the validated key length in bytes
+ return keyLen;
+ }
+ }
+
+ protected void reset(boolean doCancel) {
+ initialized = false;
+ bytesBuffered = 0;
+ if (pCtxt != null) {
+ pCtxt.dispose(doCancel);
+ pCtxt = null;
+ }
+ }
+
+ /**
+ * calls ucrypto_encrypt_init(...) or ucrypto_decrypt_init(...)
+ * @return pointer to the context
+ */
+ protected native static long nativeInit(int mech, boolean encrypt,
+ byte[] key, byte[] iv,
+ int tagLen, byte[] aad);
+
+ /**
+ * calls ucrypto_encrypt_update(...) or ucrypto_decrypt_update(...)
+ * @returns the length of output or if negative, an error status code
+ */
+ private native static int nativeUpdate(long pContext, boolean encrypt,
+ byte[] in, int inOfs, int inLen,
+ byte[] out, int outOfs);
+
+ /**
+ * calls ucrypto_encrypt_final(...) or ucrypto_decrypt_final(...)
+ * @returns the length of output or if negative, an error status code
+ */
+ native static int nativeFinal(long pContext, boolean encrypt,
+ byte[] out, int outOfs);
+
+ protected void ensureInitialized() {
+ if (!initialized) {
+ init(encrypt, keyValue, iv);
+ if (!initialized) {
+ throw new UcryptoException("Cannot initialize Cipher");
+ }
+ }
+ }
+
+ protected int getOutputSizeByOperation(int inLen, boolean isDoFinal) {
+ if (inLen <= 0) {
+ inLen = 0;
+ }
+ if (!isDoFinal && (inLen == 0)) {
+ return 0;
+ }
+ return inLen + bytesBuffered;
+ }
+
+ // actual init() implementation - caller should clone key and iv if needed
+ protected void init(boolean encrypt, byte[] keyVal, byte[] ivVal) {
+ reset(true);
+ this.encrypt = encrypt;
+ this.keyValue = keyVal;
+ this.iv = ivVal;
+ long pCtxtVal = nativeInit(mech.value(), encrypt, keyValue, iv, 0, null);
+ initialized = (pCtxtVal != 0L);
+ if (initialized) {
+ pCtxt = new CipherContextRef(this, pCtxtVal, encrypt);
+ } else {
+ throw new UcryptoException("Cannot initialize Cipher");
+ }
+ }
+
+ // Caller MUST check and ensure output buffer has enough capacity
+ private int update(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) {
+ ensureInitialized();
+ if (inLen <= 0) { return 0; }
+
+ int k = nativeUpdate(pCtxt.id, encrypt, in, inOfs, inLen, out, outOfs);
+ if (k < 0) {
+ reset(false);
+ // cannot throw ShortBufferException here since it's too late
+ // native context is invalid upon any failure
+ throw new UcryptoException(-k);
+ }
+ bytesBuffered += (inLen - k);
+ return k;
+ }
+
+ // Caller MUST check and ensure output buffer has enough capacity
+ private int doFinal(byte[] out, int outOfs) throws IllegalBlockSizeException,
+ BadPaddingException {
+ try {
+ ensureInitialized();
+
+ int k = nativeFinal(pCtxt.id, encrypt, out, outOfs);
+ if (k < 0) {
+ String cause = UcryptoException.getErrorMessage(-k);
+ if (cause.endsWith("_LEN_RANGE")) {
+ throw new IllegalBlockSizeException(cause);
+ } else if (cause.endsWith("_DATA_INVALID")) {
+ throw new BadPaddingException(cause);
+ } else {
+ throw new UcryptoException(-k);
+ }
+ }
+ return k;
+ } finally {
+ reset(false);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.nio.ByteBuffer;
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.lang.ref.*;
+
+import java.security.AlgorithmParameters;
+import java.security.GeneralSecurityException;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Wrapper class which uses NativeCipher class and Java impls of padding scheme.
+ * This class currently supports
+ * - AES/ECB/PKCS5PADDING
+ * - AES/CBC/PKCS5PADDING
+ * - AES/CFB128/PKCS5PADDING
+ *
+ * @since 1.9
+ */
+public class NativeCipherWithJavaPadding extends CipherSpi {
+
+ private static interface Padding {
+ // ENC: generate and return the necessary padding bytes
+ int getPadLen(int dataLen);
+
+ // ENC: generate and return the necessary padding bytes
+ byte[] getPaddingBytes(int dataLen);
+
+ // DEC: process the decrypted data and buffer up the potential padding
+ // bytes
+ byte[] bufferBytes(byte[] intermediateData);
+
+ // DEC: return the length of internally buffered pad bytes
+ int getBufferedLength();
+
+ // DEC: unpad and place the output in 'out', starting from outOfs
+ // and return the number of bytes unpadded into 'out'.
+ int unpad(byte[] paddedData, byte[] out, int outOfs)
+ throws BadPaddingException, IllegalBlockSizeException,
+ ShortBufferException;
+
+ // DEC: Clears the padding object to the initial state
+ void clear();
+ }
+
+ private static class PKCS5Padding implements Padding {
+ private final int blockSize;
+ // buffer for storing the the potential padding bytes
+ private ByteBuffer trailingBytes = null;
+
+ PKCS5Padding(int blockSize)
+ throws NoSuchPaddingException {
+ if (blockSize == 0) {
+ throw new NoSuchPaddingException
+ ("PKCS#5 padding not supported with stream ciphers");
+ }
+ this.blockSize = blockSize;
+ }
+
+ public int getPadLen(int dataLen) {
+ return (blockSize - (dataLen & (blockSize - 1)));
+ }
+
+ public byte[] getPaddingBytes(int dataLen) {
+ byte padValue = (byte) getPadLen(dataLen);
+ byte[] paddingBytes = new byte[padValue];
+ Arrays.fill(paddingBytes, padValue);
+ return paddingBytes;
+ }
+
+ public byte[] bufferBytes(byte[] dataFromUpdate) {
+ if (dataFromUpdate == null || dataFromUpdate.length == 0) {
+ return null;
+ }
+ byte[] result = null;
+ if (trailingBytes == null) {
+ trailingBytes = ByteBuffer.wrap(new byte[blockSize]);
+ }
+ int tbSize = trailingBytes.position();
+ if (dataFromUpdate.length > trailingBytes.remaining()) {
+ int totalLen = dataFromUpdate.length + tbSize;
+ int newTBSize = totalLen % blockSize;
+ if (newTBSize == 0) {
+ newTBSize = blockSize;
+ }
+ if (tbSize == 0) {
+ result = Arrays.copyOf(dataFromUpdate, totalLen - newTBSize);
+ } else {
+ // combine 'trailingBytes' and 'dataFromUpdate'
+ result = Arrays.copyOf(trailingBytes.array(),
+ totalLen - newTBSize);
+ if (result.length != tbSize) {
+ System.arraycopy(dataFromUpdate, 0, result, tbSize,
+ result.length - tbSize);
+ }
+ }
+ // update 'trailingBytes' w/ remaining bytes in 'dataFromUpdate'
+ trailingBytes.clear();
+ trailingBytes.put(dataFromUpdate,
+ dataFromUpdate.length - newTBSize, newTBSize);
+ } else {
+ trailingBytes.put(dataFromUpdate);
+ }
+ return result;
+ }
+
+ public int getBufferedLength() {
+ if (trailingBytes != null) {
+ return trailingBytes.position();
+ }
+ return 0;
+ }
+
+ public int unpad(byte[] lastData, byte[] out, int outOfs)
+ throws BadPaddingException, IllegalBlockSizeException,
+ ShortBufferException {
+ int tbSize = (trailingBytes == null? 0:trailingBytes.position());
+ int dataLen = tbSize + lastData.length;
+ // check total length
+ if ((dataLen < 1) || (dataLen % blockSize != 0)) {
+ UcryptoProvider.debug("PKCS5Padding: unpad, buffered " + tbSize +
+ " bytes, last block " + lastData.length + " bytes");
+
+ throw new IllegalBlockSizeException
+ ("Input length must be multiples of " + blockSize);
+ }
+
+ // check padding bytes
+ if (lastData.length == 0) {
+ if (tbSize != 0) {
+ // work on 'trailingBytes' directly
+ lastData = Arrays.copyOf(trailingBytes.array(), tbSize);
+ trailingBytes.clear();
+ tbSize = 0;
+ } else {
+ throw new BadPaddingException("No pad bytes found!");
+ }
+ }
+ byte padValue = lastData[lastData.length - 1];
+ if (padValue < 1 || padValue > blockSize) {
+ UcryptoProvider.debug("PKCS5Padding: unpad, lastData: " + Arrays.toString(lastData));
+ UcryptoProvider.debug("PKCS5Padding: unpad, padValue=" + padValue);
+ throw new BadPaddingException("Invalid pad value!");
+ }
+
+ // sanity check padding bytes
+ int padStartIndex = lastData.length - padValue;
+ for (int i = padStartIndex; i < lastData.length; i++) {
+ if (lastData[i] != padValue) {
+ UcryptoProvider.debug("PKCS5Padding: unpad, lastData: " + Arrays.toString(lastData));
+ UcryptoProvider.debug("PKCS5Padding: unpad, padValue=" + padValue);
+ throw new BadPaddingException("Invalid padding bytes!");
+ }
+ }
+
+ int actualOutLen = dataLen - padValue;
+ // check output buffer capacity
+ if (out.length - outOfs < actualOutLen) {
+ throw new ShortBufferException("Output buffer too small, need " + actualOutLen +
+ ", got " + (out.length - outOfs));
+ }
+ try {
+ if (tbSize != 0) {
+ trailingBytes.rewind();
+ if (tbSize < actualOutLen) {
+ trailingBytes.get(out, outOfs, tbSize);
+ outOfs += tbSize;
+ } else {
+ // copy from trailingBytes and we are done
+ trailingBytes.get(out, outOfs, actualOutLen);
+ return actualOutLen;
+ }
+ }
+ if (lastData.length > padValue) {
+ System.arraycopy(lastData, 0, out, outOfs,
+ lastData.length - padValue);
+ }
+ return actualOutLen;
+ } finally {
+ clear();
+ }
+ }
+
+ public void clear() {
+ if (trailingBytes != null) trailingBytes.clear();
+ }
+ }
+
+ public static final class AesEcbPKCS5 extends NativeCipherWithJavaPadding {
+ public AesEcbPKCS5() throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super(new NativeCipher.AesEcbNoPadding(), "PKCS5Padding");
+ }
+ }
+
+ public static final class AesCbcPKCS5 extends NativeCipherWithJavaPadding {
+ public AesCbcPKCS5() throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super(new NativeCipher.AesCbcNoPadding(), "PKCS5Padding");
+ }
+ }
+
+ public static final class AesCfb128PKCS5 extends NativeCipherWithJavaPadding {
+ public AesCfb128PKCS5() throws NoSuchAlgorithmException, NoSuchPaddingException {
+ super(new NativeCipher.AesCfb128NoPadding(), "PKCS5Padding");
+ }
+ }
+
+ // fields (re)set in every init()
+ private final NativeCipher nc;
+ private final Padding padding;
+ private final int blockSize;
+ private int lastBlockLen = 0;
+
+ // Only ECB, CBC, CTR, and CFB128 modes w/ NOPADDING for now
+ NativeCipherWithJavaPadding(NativeCipher nc, String paddingScheme)
+ throws NoSuchAlgorithmException, NoSuchPaddingException {
+ this.nc = nc;
+ this.blockSize = nc.engineGetBlockSize();
+ if (paddingScheme.toUpperCase().equals("PKCS5PADDING")) {
+ padding = new PKCS5Padding(blockSize);
+ } else {
+ throw new NoSuchAlgorithmException("Unsupported padding scheme: " + paddingScheme);
+ }
+ }
+
+ void reset() {
+ padding.clear();
+ lastBlockLen = 0;
+ }
+
+ @Override
+ protected synchronized void engineSetMode(String mode) throws NoSuchAlgorithmException {
+ nc.engineSetMode(mode);
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineSetPadding(String padding)
+ throws NoSuchPaddingException {
+ // Disallow change of padding for now since currently it's explicitly
+ // defined in transformation strings
+ throw new NoSuchPaddingException("Unsupported padding " + padding);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineGetBlockSize() {
+ return blockSize;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineGetOutputSize(int inputLen) {
+ int result = nc.engineGetOutputSize(inputLen);
+ if (nc.encrypt) {
+ result += padding.getPadLen(result);
+ } else {
+ result += padding.getBufferedLength();
+ }
+ return result;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineGetIV() {
+ return nc.engineGetIV();
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized AlgorithmParameters engineGetParameters() {
+ return nc.engineGetParameters();
+ }
+
+ @Override
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ return nc.engineGetKeySize(key);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ reset();
+ nc.engineInit(opmode, key, random);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ reset();
+ nc.engineInit(opmode, key, params, random);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ reset();
+ nc.engineInit(opmode, key, params, random);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
+ if (nc.encrypt) {
+ lastBlockLen += inLen;
+ lastBlockLen &= (blockSize - 1);
+ return nc.engineUpdate(in, inOfs, inLen);
+ } else {
+ return padding.bufferBytes(nc.engineUpdate(in, inOfs, inLen));
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
+ int outOfs) throws ShortBufferException {
+ if (nc.encrypt) {
+ lastBlockLen += inLen;
+ lastBlockLen &= (blockSize - 1);
+ return nc.engineUpdate(in, inOfs, inLen, out, outOfs);
+ } else {
+ byte[] result = padding.bufferBytes(nc.engineUpdate(in, inOfs, inLen));
+ if (result != null) {
+ System.arraycopy(result, 0, out, outOfs, result.length);
+ return result.length;
+ } else return 0;
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ int estimatedOutLen = engineGetOutputSize(inLen);
+ byte[] out = new byte[estimatedOutLen];
+ try {
+ int actualOut = this.engineDoFinal(in, inOfs, inLen, out, 0);
+ // truncate off extra bytes
+ if (actualOut != out.length) {
+ out = Arrays.copyOf(out, actualOut);
+ }
+ } catch (ShortBufferException sbe) {
+ throw new UcryptoException("Internal Error");
+ } finally {
+ reset();
+ }
+ return out;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
+ int outOfs)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ int estimatedOutLen = engineGetOutputSize(inLen);
+
+ if (out.length - outOfs < estimatedOutLen) {
+ throw new ShortBufferException();
+ }
+ try {
+ if (nc.encrypt) {
+ int k = nc.engineUpdate(in, inOfs, inLen, out, outOfs);
+ lastBlockLen += inLen;
+ lastBlockLen &= (blockSize - 1);
+ byte[] padBytes = padding.getPaddingBytes(lastBlockLen);
+ k += nc.engineDoFinal(padBytes, 0, padBytes.length, out, (outOfs + k));
+ return k;
+ } else {
+ byte[] tempOut = nc.engineDoFinal(in, inOfs, inLen);
+ int len = padding.unpad(tempOut, out, outOfs);
+ return len;
+ }
+ } finally {
+ reset();
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineWrap(Key key) throws IllegalBlockSizeException,
+ InvalidKeyException {
+ byte[] result = null;
+ try {
+ byte[] encodedKey = key.getEncoded();
+ if ((encodedKey == null) || (encodedKey.length == 0)) {
+ throw new InvalidKeyException("Cannot get an encoding of " +
+ "the key to be wrapped");
+ }
+ result = engineDoFinal(encodedKey, 0, encodedKey.length);
+ } catch (BadPaddingException e) {
+ // Should never happen for key wrapping
+ throw new UcryptoException("Internal Error", e);
+ }
+ return result;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
+ int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ byte[] encodedKey;
+ try {
+ encodedKey = engineDoFinal(wrappedKey, 0,
+ wrappedKey.length);
+ } catch (Exception e) {
+ throw (InvalidKeyException)
+ (new InvalidKeyException()).initCause(e);
+ }
+
+ return NativeCipher.constructKey(wrappedKeyType, encodedKey,
+ wrappedKeyAlgorithm);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.lang.ref.*;
+
+import java.io.ByteArrayOutputStream;
+import java.util.*;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.security.*;
+
+/**
+ * MessageDigest implementation class. This class currently supports
+ * MD5, SHA1, SHA256, SHA384, and SHA512
+ *
+ * @since 1.9
+ */
+public abstract class NativeDigest extends MessageDigestSpi
+ implements Cloneable {
+
+ private static final int MECH_MD5 = 1;
+ private static final int MECH_SHA1 = 2;
+ private static final int MECH_SHA256 = 3;
+ private static final int MECH_SHA224 = 4;
+ private static final int MECH_SHA384 = 5;
+ private static final int MECH_SHA512 = 6;
+
+ private final int digestLen;
+ private final int mech;
+
+ // field for ensuring native memory is freed
+ private DigestContextRef pCtxt = null;
+
+ private static class DigestContextRef extends PhantomReference<NativeDigest>
+ implements Comparable<DigestContextRef> {
+
+ private static ReferenceQueue<NativeDigest> refQueue =
+ new ReferenceQueue<NativeDigest>();
+
+ // Needed to keep these references from being GC'ed until when their
+ // referents are GC'ed so we can do post-mortem processing
+ private static Set<DigestContextRef> refList =
+ new ConcurrentSkipListSet<DigestContextRef>();
+ // Collections.synchronizedSortedSet(new TreeSet<DigestContextRef>());
+
+ private final long id;
+ private final int mech;
+
+ private static void drainRefQueueBounded() {
+ while (true) {
+ DigestContextRef next = (DigestContextRef) refQueue.poll();
+ if (next == null) break;
+ next.dispose(true);
+ }
+ }
+
+ DigestContextRef(NativeDigest nc, long id, int mech) {
+ super(nc, refQueue);
+ this.id = id;
+ this.mech = mech;
+ refList.add(this);
+ UcryptoProvider.debug("Resource: track Digest Ctxt " + this.id);
+ drainRefQueueBounded();
+ }
+
+ public int compareTo(DigestContextRef other) {
+ if (this.id == other.id) {
+ return 0;
+ } else {
+ return (this.id < other.id) ? -1 : 1;
+ }
+ }
+
+ void dispose(boolean needFree) {
+ refList.remove(this);
+ try {
+ if (needFree) {
+ UcryptoProvider.debug("Resource: free Digest Ctxt " + this.id);
+ NativeDigest.nativeFree(mech, id);
+ } else UcryptoProvider.debug("Resource: stop tracking Digest Ctxt " + this.id);
+ } finally {
+ this.clear();
+ }
+ }
+ }
+
+ NativeDigest(int mech, int digestLen) {
+ this.digestLen = digestLen;
+ this.mech = mech;
+ }
+
+ // see JCA spec
+ protected int engineGetDigestLength() {
+ return digestLen;
+ }
+
+ // see JCA spec
+ protected synchronized void engineReset() {
+ if (pCtxt != null) {
+ pCtxt.dispose(true);
+ pCtxt = null;
+ }
+ }
+
+ // see JCA spec
+ protected synchronized byte[] engineDigest() {
+ byte[] digest = new byte[digestLen];
+ try {
+ int len = engineDigest(digest, 0, digestLen);
+ if (len != digestLen) {
+ throw new UcryptoException("Digest length mismatch");
+ }
+ return digest;
+ } catch (DigestException de) {
+ throw new UcryptoException("Internal error", de);
+ }
+ }
+
+ // see JCA spec
+ protected synchronized int engineDigest(byte[] out, int ofs, int len)
+ throws DigestException {
+ if (len < digestLen) {
+ throw new DigestException("Output buffer must be at least " +
+ digestLen + " bytes long");
+ }
+ if ((ofs < 0) || (len < 0) || (ofs > out.length - len)) {
+ throw new DigestException("Buffer too short to store digest");
+ }
+
+ if (pCtxt == null) {
+ pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+ }
+ try {
+ int status = nativeDigest(mech, pCtxt.id, out, ofs, digestLen);
+ if (status != 0) {
+ throw new DigestException("Internal error: " + status);
+ }
+ } finally {
+ pCtxt.dispose(false);
+ pCtxt = null;
+ }
+ return digestLen;
+ }
+
+ // see JCA spec
+ protected synchronized void engineUpdate(byte in) {
+ byte[] temp = { in };
+ engineUpdate(temp, 0, 1);
+ }
+
+ // see JCA spec
+ protected synchronized void engineUpdate(byte[] in, int ofs, int len) {
+ if (len == 0) {
+ return;
+ }
+ if ((ofs < 0) || (len < 0) || (ofs > in.length - len)) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (pCtxt == null) {
+ pCtxt = new DigestContextRef(this, nativeInit(mech), mech);
+ }
+ nativeUpdate(mech, pCtxt.id, in, ofs, len);
+ }
+
+ /**
+ * Clone this digest.
+ */
+ public synchronized Object clone() throws CloneNotSupportedException {
+ NativeDigest copy = (NativeDigest) super.clone();
+ // re-work the fields that cannot be copied over
+ if (pCtxt != null) {
+ copy.pCtxt = new DigestContextRef(this, nativeClone(mech, pCtxt.id), mech);
+ }
+ return copy;
+ }
+
+ // return pointer to the context
+ protected static native long nativeInit(int mech);
+ // return status code; always 0
+ protected static native int nativeUpdate(int mech, long pCtxt, byte[] in, int ofs, int inLen);
+ // return status code; always 0
+ protected static native int nativeDigest(int mech, long pCtxt, byte[] out, int ofs, int digestLen);
+ // return pointer to the duplicated context
+ protected static native long nativeClone(int mech, long pCtxt);
+ // free the specified context
+ private native static void nativeFree(int mech, long id);
+
+
+ public static final class MD5 extends NativeDigest {
+ public MD5() {
+ super(MECH_MD5, 16);
+ }
+ }
+
+ public static final class SHA1 extends NativeDigest {
+ public SHA1() {
+ super(MECH_SHA1, 20);
+ }
+ }
+
+ public static final class SHA256 extends NativeDigest {
+ public SHA256() {
+ super(MECH_SHA256, 32);
+ }
+ }
+
+
+ public static final class SHA384 extends NativeDigest {
+ public SHA384() {
+ super(MECH_SHA384, 48);
+ }
+ }
+
+
+ public static final class SHA512 extends NativeDigest {
+ public SHA512() {
+ super(MECH_SHA512, 64);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.io.ByteArrayOutputStream;
+import java.nio.ByteBuffer;
+
+import java.util.Set;
+import java.util.Arrays;
+import java.security.*;
+import java.security.spec.*;
+import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
+import javax.crypto.spec.GCMParameterSpec;
+
+/**
+ * Cipher wrapper class utilizing ucrypto APIs. This class currently supports
+ * - AES/GCM/NoPADDING
+ *
+ * @since 1.9
+ */
+class NativeGCMCipher extends NativeCipher {
+
+ public static final class AesGcmNoPadding extends NativeGCMCipher {
+ public AesGcmNoPadding() throws NoSuchAlgorithmException {
+ super(-1);
+ }
+ }
+ public static final class Aes128GcmNoPadding extends NativeGCMCipher {
+ public Aes128GcmNoPadding() throws NoSuchAlgorithmException {
+ super(16);
+ }
+ }
+ public static final class Aes192GcmNoPadding extends NativeGCMCipher {
+ public Aes192GcmNoPadding() throws NoSuchAlgorithmException {
+ super(24);
+ }
+ }
+ public static final class Aes256GcmNoPadding extends NativeGCMCipher {
+ public Aes256GcmNoPadding() throws NoSuchAlgorithmException {
+ super(32);
+ }
+ }
+
+ private static final int DEFAULT_TAG_LEN = 128; // same as SunJCE provider
+
+ // buffer for storing AAD data; if null, meaning buffer content has been
+ // supplied to native context
+ private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream();
+
+ // buffer for storing input in decryption, not used for encryption
+ private ByteArrayOutputStream ibuffer = null;
+
+ private int tagLen = DEFAULT_TAG_LEN;
+
+ /*
+ * variables used for performing the GCM (key+iv) uniqueness check.
+ * To use GCM mode safely, the cipher object must be re-initialized
+ * with a different combination of key + iv values for each
+ * ENCRYPTION operation. However, checking all past key + iv values
+ * isn't feasible. Thus, we only do a per-instance check of the
+ * key + iv values used in previous encryption.
+ * For decryption operations, no checking is necessary.
+ */
+ private boolean requireReinit = false;
+ private byte[] lastEncKey = null;
+ private byte[] lastEncIv = null;
+
+ NativeGCMCipher(int fixedKeySize) throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_AES_GCM, fixedKeySize);
+ }
+
+ @Override
+ protected void ensureInitialized() {
+ if (!initialized) {
+ if (aadBuffer != null && aadBuffer.size() > 0) {
+ init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
+ aadBuffer = null;
+ } else {
+ init(encrypt, keyValue, iv, tagLen, null);
+ }
+ if (!initialized) {
+ throw new UcryptoException("Cannot initialize Cipher");
+ }
+ }
+ }
+
+ @Override
+ protected int getOutputSizeByOperation(int inLen, boolean isDoFinal) {
+ if (inLen < 0) return 0;
+
+ if (!isDoFinal && (inLen == 0)) {
+ return 0;
+ }
+
+ int result = inLen + bytesBuffered;
+ if (encrypt) {
+ if (isDoFinal) {
+ result += tagLen/8;
+ }
+ } else {
+ if (ibuffer != null) {
+ result += ibuffer.size();
+ }
+ if (isDoFinal) {
+ result -= tagLen/8;
+ }
+ }
+ if (result < 0) {
+ result = 0;
+ }
+ return result;
+ }
+
+ @Override
+ protected void reset(boolean doCancel) {
+ super.reset(doCancel);
+ if (aadBuffer == null) {
+ aadBuffer = new ByteArrayOutputStream();
+ } else {
+ aadBuffer.reset();
+ }
+
+ if (ibuffer != null) {
+ ibuffer.reset();
+ }
+ if (!encrypt) requireReinit = false;
+ }
+
+ // actual init() implementation - caller should clone key and iv if needed
+ protected void init(boolean encrypt, byte[] keyVal, byte[] ivVal, int tLen, byte[] aad) {
+ reset(true);
+ this.encrypt = encrypt;
+ this.keyValue = keyVal;
+ this.iv = ivVal;
+ long pCtxtVal = NativeCipher.nativeInit(mech.value(), encrypt, keyValue, iv,
+ tLen, aad);
+ initialized = (pCtxtVal != 0L);
+ if (initialized) {
+ pCtxt = new CipherContextRef(this, pCtxtVal, encrypt);
+ } else {
+ throw new UcryptoException("Cannot initialize Cipher");
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized AlgorithmParameters engineGetParameters() {
+ AlgorithmParameters params = null;
+ try {
+ if (iv != null) {
+ GCMParameterSpec gcmSpec = new GCMParameterSpec(tagLen, iv.clone());
+ params = AlgorithmParameters.getInstance("GCM");
+ params.init(gcmSpec);
+ }
+ } catch (GeneralSecurityException e) {
+ // NoSuchAlgorithmException, NoSuchProviderException
+ // InvalidParameterSpecException
+ throw new UcryptoException("Could not encode parameters", e);
+ }
+ return params;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ checkKey(key);
+ if (opmode != Cipher.ENCRYPT_MODE &&
+ opmode != Cipher.DECRYPT_MODE &&
+ opmode != Cipher.WRAP_MODE &&
+ opmode != Cipher.UNWRAP_MODE) {
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported mode: " + opmode);
+ }
+ boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
+ byte[] keyBytes = key.getEncoded().clone();
+ byte[] ivBytes = null;
+ if (params != null) {
+ if (!(params instanceof GCMParameterSpec)) {
+ throw new InvalidAlgorithmParameterException("GCMParameterSpec required");
+ } else {
+ tagLen = ((GCMParameterSpec) params).getTLen();
+ ivBytes = ((GCMParameterSpec) params).getIV();
+ }
+ } else {
+ if (doEncrypt) {
+ tagLen = DEFAULT_TAG_LEN;
+
+ // generate IV if none supplied for encryption
+ ivBytes = new byte[blockSize];
+ new SecureRandom().nextBytes(ivBytes);
+ } else {
+ throw new InvalidAlgorithmParameterException("Parameters required for decryption");
+ }
+ }
+ if (doEncrypt) {
+ requireReinit = Arrays.equals(ivBytes, lastEncIv) &&
+ Arrays.equals(keyBytes, lastEncKey);
+ if (requireReinit) {
+ throw new InvalidAlgorithmParameterException
+ ("Cannot reuse iv for GCM encryption");
+ }
+ lastEncIv = ivBytes;
+ lastEncKey = keyBytes;
+ } else {
+ requireReinit = false;
+ ibuffer = new ByteArrayOutputStream();
+ }
+ init(doEncrypt, keyBytes, ivBytes, tagLen, null);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ AlgorithmParameterSpec spec = null;
+ if (params != null) {
+ try {
+ // mech must be UcryptoMech.CRYPTO_AES_GCM
+ spec = params.getParameterSpec(GCMParameterSpec.class);
+ } catch (InvalidParameterSpecException iaps) {
+ throw new InvalidAlgorithmParameterException(iaps);
+ }
+ }
+ engineInit(opmode, key, spec, random);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
+ if (aadBuffer != null && aadBuffer.size() > 0) {
+ // init again with AAD data
+ init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
+ aadBuffer = null;
+ }
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+ if (inLen > 0) {
+ if (!encrypt) {
+ ibuffer.write(in, inOfs, inLen);
+ return null;
+ }
+ return super.engineUpdate(in, inOfs, inLen);
+ } else return null;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
+ int outOfs) throws ShortBufferException {
+ int len = getOutputSizeByOperation(inLen, false);
+ if (out.length - outOfs < len) {
+ throw new ShortBufferException("Output buffer must be "
+ + "(at least) " + len
+ + " bytes long");
+ }
+ if (aadBuffer != null && aadBuffer.size() > 0) {
+ // init again with AAD data
+ init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
+ aadBuffer = null;
+ }
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+ if (inLen > 0) {
+ if (!encrypt) {
+ ibuffer.write(in, inOfs, inLen);
+ return 0;
+ } else {
+ return super.engineUpdate(in, inOfs, inLen, out, outOfs);
+ }
+ }
+ return 0;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineUpdateAAD(byte[] src, int srcOfs, int srcLen)
+ throws IllegalStateException {
+
+ if ((src == null) || (srcOfs < 0) || (srcOfs + srcLen > src.length)) {
+ throw new IllegalArgumentException("Invalid AAD");
+ }
+ if (keyValue == null) {
+ throw new IllegalStateException("Need to initialize Cipher first");
+ }
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+ if (aadBuffer != null) {
+ aadBuffer.write(src, srcOfs, srcLen);
+ } else {
+ // update has already been called
+ throw new IllegalStateException
+ ("Update has been called; no more AAD data");
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineUpdateAAD(ByteBuffer src)
+ throws IllegalStateException {
+ if (src == null) {
+ throw new IllegalArgumentException("Invalid AAD");
+ }
+ if (keyValue == null) {
+ throw new IllegalStateException("Need to initialize Cipher first");
+ }
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+ if (aadBuffer != null) {
+ if (src.hasRemaining()) {
+ byte[] srcBytes = new byte[src.remaining()];
+ src.get(srcBytes);
+ aadBuffer.write(srcBytes, 0, srcBytes.length);
+ }
+ } else {
+ // update has already been called
+ throw new IllegalStateException
+ ("Update has been called; no more AAD data");
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ byte[] out = new byte[getOutputSizeByOperation(inLen, true)];
+ try {
+ // delegate to the other engineDoFinal(...) method
+ int k = engineDoFinal(in, inOfs, inLen, out, 0);
+ if (out.length != k) {
+ out = Arrays.copyOf(out, k);
+ }
+ return out;
+ } catch (ShortBufferException e) {
+ throw new UcryptoException("Internal Error", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineDoFinal(byte[] in, int inOfs, int inLen,
+ byte[] out, int outOfs)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ int len = getOutputSizeByOperation(inLen, true);
+ if (out.length - outOfs < len) {
+ throw new ShortBufferException("Output buffer must be "
+ + "(at least) " + len
+ + " bytes long");
+ }
+ if (aadBuffer != null && aadBuffer.size() > 0) {
+ // init again with AAD data
+ init(encrypt, keyValue, iv, tagLen, aadBuffer.toByteArray());
+ aadBuffer = null;
+ }
+ if (requireReinit) {
+ throw new IllegalStateException
+ ("Must use either different key or iv for GCM encryption");
+ }
+ if (!encrypt) {
+ if (inLen > 0) {
+ ibuffer.write(in, inOfs, inLen);
+ }
+ inLen = ibuffer.size();
+ if (inLen < tagLen/8) {
+ // Otherwise, Solaris lib will error out w/ CRYPTO_BUFFER_TOO_SMALL
+ // when ucrypto_decrypt_final() is called
+ throw new AEADBadTagException("Input too short - need tag");
+ }
+ // refresh 'in' to all buffered-up bytes
+ in = ibuffer.toByteArray();
+ inOfs = 0;
+ ibuffer.reset();
+ }
+ try {
+ return super.engineDoFinal(in, inOfs, inLen, out, outOfs);
+ } catch (UcryptoException ue) {
+ if (ue.getMessage().equals("CRYPTO_INVALID_MAC")) {
+ throw new AEADBadTagException("Tag does not match");
+ } else {
+ // pass it up
+ throw ue;
+ }
+ } finally {
+ requireReinit = encrypt;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeKey.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.lang.ref.*;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.PrivateKey;
+import java.security.KeyFactorySpi;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPublicKey;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+/**
+ * Wrapper class for native keys needed for using ucrypto APIs.
+ * This class currently supports native RSA private/public keys.
+ *
+ * @since 1.9
+ */
+abstract class NativeKey implements Key {
+
+ private static final long serialVersionUID = 6812507588904302830L;
+
+ private final int numComponents;
+
+ NativeKey(int numComponents) {
+ this.numComponents = numComponents;
+ }
+
+ abstract long value();
+
+ int length() {
+ return numComponents;
+ }
+
+ public String getAlgorithm() { return "RSA"; }
+ public String getFormat() { return "RAW"; }
+ public byte[] getEncoded() {
+ // not used; so not generated
+ return null;
+ }
+
+ private native static void nativeFree(long id, int numComponents);
+
+ static byte[] getMagnitude(BigInteger bi) {
+ byte[] b = bi.toByteArray();
+ if ((b.length > 1) && (b[0] == 0)) {
+ int n = b.length - 1;
+ byte[] newarray = new byte[n];
+ System.arraycopy(b, 1, newarray, 0, n);
+ b = newarray;
+ }
+ return b;
+ }
+
+ static final class RSAPrivateCrt extends NativeKey implements RSAPrivateCrtKey {
+
+ private static final long serialVersionUID = 6812507588904302831L;
+
+ private final RSAPrivateCrtKeySpec keySpec;
+ private final long keyId;
+
+ RSAPrivateCrt(KeySpec keySpec) throws InvalidKeySpecException {
+ super(8);
+ long pKey = 0L;
+ if (keySpec instanceof RSAPrivateCrtKeySpec) {
+ RSAPrivateCrtKeySpec ks = (RSAPrivateCrtKeySpec) keySpec;
+ BigInteger mod = ks.getModulus();
+ BigInteger publicExp = ks.getPublicExponent();
+ BigInteger privateExp = ks.getPrivateExponent();
+ BigInteger primeP = ks.getPrimeP();
+ BigInteger primeQ = ks.getPrimeQ();
+ BigInteger primeExpP = ks.getPrimeExponentP();
+ BigInteger primeExpQ = ks.getPrimeExponentQ();
+ BigInteger crtCoeff = ks.getCrtCoefficient();
+ pKey = nativeInit(NativeKey.getMagnitude(mod),
+ NativeKey.getMagnitude(publicExp),
+ NativeKey.getMagnitude(privateExp),
+ NativeKey.getMagnitude(primeP),
+ NativeKey.getMagnitude(primeQ),
+ NativeKey.getMagnitude(primeExpP),
+ NativeKey.getMagnitude(primeExpQ),
+ NativeKey.getMagnitude(crtCoeff));
+ } else {
+ throw new InvalidKeySpecException("Only supports RSAPrivateCrtKeySpec");
+ }
+ if (pKey == 0L) {
+ throw new UcryptoException("Error constructing RSA PrivateKey");
+ }
+ // track native resource clean up
+ new KeyRef(this, pKey);
+ this.keySpec = (RSAPrivateCrtKeySpec) keySpec;
+ this.keyId = pKey;
+ }
+
+ long value() { return keyId; }
+ public BigInteger getModulus() { return keySpec.getModulus(); };
+ public BigInteger getPublicExponent() { return keySpec.getPublicExponent(); };
+ public BigInteger getPrivateExponent() { return keySpec.getPrivateExponent(); };
+ public BigInteger getPrimeP() { return keySpec.getPrimeP(); };
+ public BigInteger getPrimeQ() { return keySpec.getPrimeQ(); };
+ public BigInteger getPrimeExponentP() { return keySpec.getPrimeExponentP(); };
+ public BigInteger getPrimeExponentQ() { return keySpec.getPrimeExponentQ(); };
+ public BigInteger getCrtCoefficient() { return keySpec.getCrtCoefficient(); };
+
+ private native static long nativeInit(byte[] mod, byte[] pubExp, byte[] privExp,
+ byte[] p, byte[] q,
+ byte[] expP, byte[] expQ, byte[] crtCoeff);
+ }
+
+ static final class RSAPublic extends NativeKey implements RSAPublicKey {
+
+ private static final long serialVersionUID = 6812507588904302832L;
+
+ private final RSAPublicKeySpec keySpec;
+ private final long keyId;
+
+ RSAPublic(KeySpec keySpec) throws InvalidKeySpecException {
+ super(2);
+ long pKey = 0L;
+ if (keySpec instanceof RSAPublicKeySpec) {
+ RSAPublicKeySpec ks = (RSAPublicKeySpec) keySpec;
+ BigInteger mod = ks.getModulus();
+ BigInteger publicExp = ks.getPublicExponent();
+ pKey = nativeInit(NativeKey.getMagnitude(mod),
+ NativeKey.getMagnitude(publicExp));
+ } else {
+ throw new InvalidKeySpecException("Only supports RSAPublicKeySpec");
+ }
+ if (pKey == 0L) {
+ throw new UcryptoException("Error constructing RSA PublicKey");
+ }
+ // track native resource clean up
+ new KeyRef(this, pKey);
+ this.keySpec = (RSAPublicKeySpec) keySpec;
+ this.keyId = pKey;
+ }
+
+ long value() { return keyId; }
+ public BigInteger getModulus() { return keySpec.getModulus(); };
+ public BigInteger getPublicExponent() { return keySpec.getPublicExponent(); };
+
+ private native static long nativeInit(byte[] mod, byte[] pubExp);
+ }
+
+ // internal class for native resource cleanup
+ private static class KeyRef extends PhantomReference<NativeKey>
+ implements Comparable<KeyRef> {
+
+ private static ReferenceQueue<NativeKey> refQueue =
+ new ReferenceQueue<NativeKey>();
+
+ // Needed to keep these references from being GC'ed until when their
+ // referents are GC'ed so we can do post-mortem processing
+ private static Set<KeyRef> refList =
+ new ConcurrentSkipListSet<KeyRef>();
+
+ private final long id;
+ private final int length;
+
+ private static void drainRefQueueBounded() {
+ while (true) {
+ KeyRef next = (KeyRef) refQueue.poll();
+ if (next == null) break;
+ next.dispose();
+ }
+ }
+
+ KeyRef(NativeKey nk, long id) {
+ super(nk, refQueue);
+ this.id = id;
+ this.length = nk.length();
+ refList.add(this);
+ UcryptoProvider.debug("Resource: track NativeKey " + this.id);
+ drainRefQueueBounded();
+ }
+
+ public int compareTo(KeyRef other) {
+ if (this.id == other.id) {
+ return 0;
+ } else {
+ return (this.id < other.id) ? -1 : 1;
+ }
+ }
+
+ void dispose() {
+ refList.remove(this);
+ UcryptoProvider.debug("Resource: free NativeKey " + this.id);
+ try {
+ NativeKey.nativeFree(id, length);
+ } finally {
+ this.clear();
+ }
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.util.Arrays;
+import java.util.WeakHashMap;
+import java.util.Collections;
+import java.util.Map;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.PrivateKey;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.security.interfaces.RSAKey;
+import java.security.interfaces.RSAPrivateCrtKey;
+import java.security.interfaces.RSAPublicKey;
+
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.CipherSpi;
+import javax.crypto.SecretKey;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.ShortBufferException;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import sun.security.internal.spec.TlsRsaPremasterSecretParameterSpec;
+import sun.security.util.KeyUtil;
+
+/**
+ * Asymmetric Cipher wrapper class utilizing ucrypto APIs. This class
+ * currently supports
+ * - RSA/ECB/NOPADDING
+ * - RSA/ECB/PKCS1PADDING
+ *
+ * @since 1.9
+ */
+public class NativeRSACipher extends CipherSpi {
+ // fields set in constructor
+ private final UcryptoMech mech;
+ private final int padLen;
+ private final NativeRSAKeyFactory keyFactory;
+ private AlgorithmParameterSpec spec;
+ private SecureRandom random;
+
+ // Keep a cache of RSA keys and their RSA NativeKey for reuse.
+ // When the RSA key is gc'ed, we let NativeKey phatom references cleanup
+ // the native allocation
+ private static final Map<Key, NativeKey> keyList =
+ Collections.synchronizedMap(new WeakHashMap<Key, NativeKey>());
+
+ //
+ // fields (re)set in every init()
+ //
+ private NativeKey key = null;
+ private int outputSize = 0; // e.g. modulus size in bytes
+ private boolean encrypt = true;
+ private byte[] buffer;
+ private int bufOfs = 0;
+
+ // public implementation classes
+ public static final class NoPadding extends NativeRSACipher {
+ public NoPadding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_RSA_X_509, 0);
+ }
+ }
+
+ public static final class PKCS1Padding extends NativeRSACipher {
+ public PKCS1Padding() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_RSA_PKCS, 11);
+ }
+ }
+
+ NativeRSACipher(UcryptoMech mech, int padLen)
+ throws NoSuchAlgorithmException {
+ this.mech = mech;
+ this.padLen = padLen;
+ this.keyFactory = new NativeRSAKeyFactory();
+ }
+
+ @Override
+ protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
+ // Disallow change of mode for now since currently it's explicitly
+ // defined in transformation strings
+ throw new NoSuchAlgorithmException("Unsupported mode " + mode);
+ }
+
+ // see JCE spec
+ @Override
+ protected void engineSetPadding(String padding)
+ throws NoSuchPaddingException {
+ // Disallow change of padding for now since currently it's explicitly
+ // defined in transformation strings
+ throw new NoSuchPaddingException("Unsupported padding " + padding);
+ }
+
+ // see JCE spec
+ @Override
+ protected int engineGetBlockSize() {
+ return 0;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineGetOutputSize(int inputLen) {
+ return outputSize;
+ }
+
+ // see JCE spec
+ @Override
+ protected byte[] engineGetIV() {
+ return null;
+ }
+
+ // see JCE spec
+ @Override
+ protected AlgorithmParameters engineGetParameters() {
+ return null;
+ }
+
+ @Override
+ protected int engineGetKeySize(Key key) throws InvalidKeyException {
+ if (!(key instanceof RSAKey)) {
+ throw new InvalidKeyException("RSAKey required");
+ }
+ int n = ((RSAKey)key).getModulus().bitLength();
+ // strip off the leading extra 0x00 byte prefix
+ int realByteSize = (n + 7) >> 3;
+ return realByteSize * 8;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key, SecureRandom random)
+ throws InvalidKeyException {
+ try {
+ engineInit(opmode, key, (AlgorithmParameterSpec)null, random);
+ } catch (InvalidAlgorithmParameterException e) {
+ throw new InvalidKeyException("init() failed", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key newKey,
+ AlgorithmParameterSpec params, SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (newKey == null) {
+ throw new InvalidKeyException("Key cannot be null");
+ }
+ if (opmode != Cipher.ENCRYPT_MODE &&
+ opmode != Cipher.DECRYPT_MODE &&
+ opmode != Cipher.WRAP_MODE &&
+ opmode != Cipher.UNWRAP_MODE) {
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported mode: " + opmode);
+ }
+ if (params != null) {
+ if (!(params instanceof TlsRsaPremasterSecretParameterSpec)) {
+ throw new InvalidAlgorithmParameterException(
+ "No Parameters can be specified");
+ }
+ spec = params;
+ this.random = random; // for TLS RSA premaster secret
+ }
+ boolean doEncrypt = (opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.WRAP_MODE);
+
+ // Make sure the proper opmode uses the proper key
+ if (doEncrypt && (!(newKey instanceof RSAPublicKey))) {
+ throw new InvalidKeyException("RSAPublicKey required for encryption");
+ } else if (!doEncrypt && (!(newKey instanceof RSAPrivateCrtKey))) {
+ throw new InvalidKeyException("RSAPrivateCrtKey required for decryption");
+ }
+
+ NativeKey nativeKey = null;
+ // Check keyList cache for a nativeKey
+ nativeKey = keyList.get(newKey);
+ if (nativeKey == null) {
+ // With no existing nativeKey for this newKey, create one
+ if (doEncrypt) {
+ RSAPublicKey publicKey = (RSAPublicKey) newKey;
+ try {
+ nativeKey = (NativeKey) keyFactory.engineGeneratePublic
+ (new RSAPublicKeySpec(publicKey.getModulus(), publicKey.getPublicExponent()));
+ } catch (InvalidKeySpecException ikse) {
+ throw new InvalidKeyException(ikse);
+ }
+ } else {
+ RSAPrivateCrtKey privateKey = (RSAPrivateCrtKey) newKey;
+ try {
+ nativeKey = (NativeKey) keyFactory.engineGeneratePrivate
+ (new RSAPrivateCrtKeySpec(privateKey.getModulus(),
+ privateKey.getPublicExponent(),
+ privateKey.getPrivateExponent(),
+ privateKey.getPrimeP(),
+ privateKey.getPrimeQ(),
+ privateKey.getPrimeExponentP(),
+ privateKey.getPrimeExponentQ(),
+ privateKey.getCrtCoefficient()));
+ } catch (InvalidKeySpecException ikse) {
+ throw new InvalidKeyException(ikse);
+ }
+ }
+
+ // Add nativeKey to keyList cache and associate it with newKey
+ keyList.put(newKey, nativeKey);
+ }
+
+ init(doEncrypt, nativeKey);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized void engineInit(int opmode, Key key, AlgorithmParameters params,
+ SecureRandom random)
+ throws InvalidKeyException, InvalidAlgorithmParameterException {
+ if (params != null) {
+ throw new InvalidAlgorithmParameterException("No Parameters can be specified");
+ }
+ engineInit(opmode, key, (AlgorithmParameterSpec) null, random);
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineUpdate(byte[] in, int inOfs, int inLen) {
+ if (inLen > 0) {
+ update(in, inOfs, inLen);
+ }
+ return null;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineUpdate(byte[] in, int inOfs, int inLen, byte[] out,
+ int outOfs) throws ShortBufferException {
+ if (out.length - outOfs < outputSize) {
+ throw new ShortBufferException("Output buffer too small");
+ }
+ if (inLen > 0) {
+ update(in, inOfs, inLen);
+ }
+ return 0;
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineDoFinal(byte[] in, int inOfs, int inLen)
+ throws IllegalBlockSizeException, BadPaddingException {
+ byte[] out = new byte[outputSize];
+ try {
+ // delegate to the other engineDoFinal(...) method
+ int actualLen = engineDoFinal(in, inOfs, inLen, out, 0);
+ if (actualLen != outputSize) {
+ return Arrays.copyOf(out, actualLen);
+ } else {
+ return out;
+ }
+ } catch (ShortBufferException e) {
+ throw new UcryptoException("Internal Error", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
+ int outOfs)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ if (inLen != 0) {
+ update(in, inOfs, inLen);
+ }
+ return doFinal(out, outOfs, out.length - outOfs);
+ }
+
+
+ // see JCE spec
+ @Override
+ protected synchronized byte[] engineWrap(Key key) throws IllegalBlockSizeException,
+ InvalidKeyException {
+ try {
+ byte[] encodedKey = key.getEncoded();
+ if ((encodedKey == null) || (encodedKey.length == 0)) {
+ throw new InvalidKeyException("Cannot get an encoding of " +
+ "the key to be wrapped");
+ }
+ if (encodedKey.length > buffer.length) {
+ throw new InvalidKeyException("Key is too long for wrapping");
+ }
+ return engineDoFinal(encodedKey, 0, encodedKey.length);
+ } catch (BadPaddingException e) {
+ // Should never happen for key wrapping
+ throw new UcryptoException("Internal Error", e);
+ }
+ }
+
+ // see JCE spec
+ @Override
+ protected synchronized Key engineUnwrap(byte[] wrappedKey,
+ String wrappedKeyAlgorithm, int wrappedKeyType)
+ throws InvalidKeyException, NoSuchAlgorithmException {
+
+ if (wrappedKey.length > buffer.length) {
+ throw new InvalidKeyException("Key is too long for unwrapping");
+ }
+
+ boolean isTlsRsaPremasterSecret =
+ wrappedKeyAlgorithm.equals("TlsRsaPremasterSecret");
+ Exception failover = null;
+
+ byte[] encodedKey = null;
+ try {
+ encodedKey = engineDoFinal(wrappedKey, 0, wrappedKey.length);
+ } catch (BadPaddingException bpe) {
+ if (isTlsRsaPremasterSecret) {
+ failover = bpe;
+ } else {
+ throw new InvalidKeyException("Unwrapping failed", bpe);
+ }
+ } catch (Exception e) {
+ throw new InvalidKeyException("Unwrapping failed", e);
+ }
+
+ if (isTlsRsaPremasterSecret) {
+ if (!(spec instanceof TlsRsaPremasterSecretParameterSpec)) {
+ throw new IllegalStateException(
+ "No TlsRsaPremasterSecretParameterSpec specified");
+ }
+
+ // polish the TLS premaster secret
+ encodedKey = KeyUtil.checkTlsPreMasterSecretKey(
+ ((TlsRsaPremasterSecretParameterSpec)spec).getClientVersion(),
+ ((TlsRsaPremasterSecretParameterSpec)spec).getServerVersion(),
+ random, encodedKey, (failover != null));
+ }
+
+ return NativeCipher.constructKey(wrappedKeyType,
+ encodedKey, wrappedKeyAlgorithm);
+ }
+
+ /**
+ * calls ucrypto_encrypt(...) or ucrypto_decrypt(...)
+ * @returns the length of output or an negative error status code
+ */
+ private native static int nativeAtomic(int mech, boolean encrypt,
+ long keyValue, int keyLength,
+ byte[] in, int inLen,
+ byte[] out, int ouOfs, int outLen);
+
+ // do actual initialization
+ private void init(boolean encrypt, NativeKey key) {
+ this.encrypt = encrypt;
+ this.key = key;
+ try {
+ this.outputSize = engineGetKeySize(key)/8;
+ } catch (InvalidKeyException ike) {
+ throw new UcryptoException("Internal Error", ike);
+ }
+ this.buffer = new byte[outputSize];
+ this.bufOfs = 0;
+ }
+
+ // store the specified input into the internal buffer
+ private void update(byte[] in, int inOfs, int inLen) {
+ if ((inLen <= 0) || (in == null)) {
+ return;
+ }
+ // buffer bytes internally until doFinal is called
+ if ((bufOfs + inLen + (encrypt? padLen:0)) > buffer.length) {
+ // lead to IllegalBlockSizeException when doFinal() is called
+ bufOfs = buffer.length + 1;
+ return;
+ }
+ System.arraycopy(in, inOfs, buffer, bufOfs, inLen);
+ bufOfs += inLen;
+ }
+
+ // return the actual non-negative output length
+ private int doFinal(byte[] out, int outOfs, int outLen)
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ if (bufOfs > buffer.length) {
+ throw new IllegalBlockSizeException(
+ "Data must not be longer than " +
+ (buffer.length - (encrypt ? padLen : 0)) + " bytes");
+ }
+ if (outLen < outputSize) {
+ throw new ShortBufferException();
+ }
+ try {
+ long keyValue = key.value();
+ int k = nativeAtomic(mech.value(), encrypt, keyValue,
+ key.length(), buffer, bufOfs,
+ out, outOfs, outLen);
+ if (k < 0) {
+ if ( k == -16 || k == -64) {
+ // -16: CRYPTO_ENCRYPTED_DATA_INVALID
+ // -64: CKR_ENCRYPTED_DATA_INVALID, see bug 17459266
+ UcryptoException ue = new UcryptoException(16);
+ BadPaddingException bpe =
+ new BadPaddingException("Invalid encryption data");
+ bpe.initCause(ue);
+ throw bpe;
+ }
+ throw new UcryptoException(-k);
+ }
+
+ return k;
+ } finally {
+ bufOfs = 0;
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSAKeyFactory.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.lang.ref.*;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.PrivateKey;
+import java.security.KeyFactorySpi;
+
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+/**
+ * Ucrypto-private KeyFactory class for generating native keys
+ * needed for using ucrypto APIs. Given that it's not used
+ * externally, it only needs to support RSAPrivateCrtKeySpec
+ * and RSAPublicKeySpec objects.
+ *
+ * @since 1.9
+ */
+public final class NativeRSAKeyFactory extends KeyFactorySpi {
+
+ @Override
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ return new NativeKey.RSAPrivateCrt(keySpec);
+ }
+
+ @Override
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException {
+ return new NativeKey.RSAPublic(keySpec);
+ }
+
+ @Override
+ protected <T extends KeySpec> T
+ engineGetKeySpec(Key key, Class<T> keySpec)
+ throws InvalidKeySpecException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected Key engineTranslateKey(Key key) throws InvalidKeyException {
+ // no need to support this
+ throw new UnsupportedOperationException();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.util.Set;
+import java.util.Arrays;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.lang.ref.*;
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+import java.security.SignatureSpi;
+import java.security.NoSuchAlgorithmException;
+import java.security.InvalidParameterException;
+import java.security.InvalidKeyException;
+import java.security.SignatureException;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import java.security.*;
+import java.security.interfaces.*;
+import java.security.spec.RSAPrivateCrtKeySpec;
+import java.security.spec.RSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import sun.nio.ch.DirectBuffer;
+import java.nio.ByteBuffer;
+import sun.security.rsa.RSAPadding;
+
+/**
+ * Signature implementation class. This class currently supports the
+ * following algorithms:
+ *
+ * . RSA:
+ * . MD5withRSA
+ * . SHA1withRSA
+ * . SHA256withRSA
+ * . SHA384withRSA
+ * . SHA512withRSA
+ *
+ * @since 1.9
+ */
+class NativeRSASignature extends SignatureSpi {
+
+ private static final int PKCS1PADDING_LEN = 11;
+
+ // fields set in constructor
+ private final UcryptoMech mech;
+ private final int encodedLen;
+
+ // field for ensuring native memory is freed
+ private SignatureContextRef pCtxt = null;
+
+ //
+ // fields (re)set in every init()
+ //
+ private boolean initialized = false;
+ private boolean sign = true;
+ private int sigLength;
+ private NativeKey key;
+ private NativeRSAKeyFactory keyFactory; // may need a more generic type later
+
+ // public implementation classes
+ public static final class MD5 extends NativeRSASignature {
+ public MD5() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_MD5_RSA_PKCS, 34);
+ }
+ }
+
+ public static final class SHA1 extends NativeRSASignature {
+ public SHA1() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_SHA1_RSA_PKCS, 35);
+ }
+ }
+
+ public static final class SHA256 extends NativeRSASignature {
+ public SHA256() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_SHA256_RSA_PKCS, 51);
+ }
+ }
+
+ public static final class SHA384 extends NativeRSASignature {
+ public SHA384() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_SHA384_RSA_PKCS, 67);
+ }
+ }
+
+ public static final class SHA512 extends NativeRSASignature {
+ public SHA512() throws NoSuchAlgorithmException {
+ super(UcryptoMech.CRYPTO_SHA512_RSA_PKCS, 83);
+ }
+ }
+
+ // internal class for native resource cleanup
+ private static class SignatureContextRef extends PhantomReference<NativeRSASignature>
+ implements Comparable<SignatureContextRef> {
+
+ private static ReferenceQueue<NativeRSASignature> refQueue =
+ new ReferenceQueue<NativeRSASignature>();
+
+ // Needed to keep these references from being GC'ed until when their
+ // referents are GC'ed so we can do post-mortem processing
+ private static Set<SignatureContextRef> refList =
+ new ConcurrentSkipListSet<SignatureContextRef>();
+ // Collections.synchronizedSortedSet(new TreeSet<SignatureContextRef>());
+
+ private final long id;
+ private final boolean sign;
+
+ private static void drainRefQueueBounded() {
+ while (true) {
+ SignatureContextRef next = (SignatureContextRef) refQueue.poll();
+ if (next == null) break;
+ next.dispose(true);
+ }
+ }
+
+ SignatureContextRef(NativeRSASignature ns, long id, boolean sign) {
+ super(ns, refQueue);
+ this.id = id;
+ this.sign = sign;
+ refList.add(this);
+ UcryptoProvider.debug("Resource: track Signature Ctxt " + this.id);
+ drainRefQueueBounded();
+ }
+
+ public int compareTo(SignatureContextRef other) {
+ if (this.id == other.id) {
+ return 0;
+ } else {
+ return (this.id < other.id) ? -1 : 1;
+ }
+ }
+
+ void dispose(boolean doCancel) {
+ refList.remove(this);
+ try {
+ if (doCancel) {
+ UcryptoProvider.debug("Resource: free Signature Ctxt " + this.id);
+ NativeRSASignature.nativeFinal(id, sign, null, 0, 0);
+ } else {
+ UcryptoProvider.debug("Resource: stop tracking Signature Ctxt " + this.id);
+ }
+ } finally {
+ this.clear();
+ }
+ }
+ }
+
+ NativeRSASignature(UcryptoMech mech, int encodedLen)
+ throws NoSuchAlgorithmException {
+ this.mech = mech;
+ this.encodedLen = encodedLen;
+ this.keyFactory = new NativeRSAKeyFactory();
+ }
+
+ // deprecated but abstract
+ @SuppressWarnings("deprecation")
+ protected Object engineGetParameter(String param) throws InvalidParameterException {
+ throw new UnsupportedOperationException("getParameter() not supported");
+ }
+
+ @Override
+ protected synchronized void engineInitSign(PrivateKey privateKey)
+ throws InvalidKeyException {
+ if (privateKey == null) {
+ throw new InvalidKeyException("Key must not be null");
+ }
+ NativeKey newKey = key;
+ int newSigLength = sigLength;
+ // Need to check RSA key length whenever a new private key is set
+ if (privateKey != key) {
+ if (privateKey instanceof RSAPrivateCrtKey) {
+ RSAPrivateCrtKey rsaPrivKey = (RSAPrivateCrtKey) privateKey;
+ BigInteger mod = rsaPrivKey.getModulus();
+ newSigLength = checkRSAKeyLength(mod);
+ try {
+ newKey = (NativeKey) keyFactory.engineGeneratePrivate
+ (new RSAPrivateCrtKeySpec(mod,
+ rsaPrivKey.getPublicExponent(),
+ rsaPrivKey.getPrivateExponent(),
+ rsaPrivKey.getPrimeP(),
+ rsaPrivKey.getPrimeQ(),
+ rsaPrivKey.getPrimeExponentP(),
+ rsaPrivKey.getPrimeExponentQ(),
+ rsaPrivKey.getCrtCoefficient()));
+ } catch (InvalidKeySpecException ikse) {
+ throw new InvalidKeyException(ikse);
+ }
+ } else {
+ throw new InvalidKeyException("RSAPrivateCrtKey required");
+ }
+ }
+ init(true, newKey, newSigLength);
+ }
+
+
+ @Override
+ protected synchronized void engineInitVerify(PublicKey publicKey)
+ throws InvalidKeyException {
+ if (publicKey == null) {
+ throw new InvalidKeyException("Key must not be null");
+ }
+ NativeKey newKey = key;
+ int newSigLength = sigLength;
+ // Need to check RSA key length whenever a new public key is set
+ if (publicKey != key) {
+ if (publicKey instanceof RSAPublicKey) {
+ BigInteger mod = ((RSAPublicKey) publicKey).getModulus();
+ newSigLength = checkRSAKeyLength(mod);
+ try {
+ newKey = (NativeKey) keyFactory.engineGeneratePublic
+ (new RSAPublicKeySpec(mod, ((RSAPublicKey) publicKey).getPublicExponent()));
+ } catch (InvalidKeySpecException ikse) {
+ throw new InvalidKeyException(ikse);
+ }
+ } else {
+ throw new InvalidKeyException("RSAPublicKey required");
+ }
+ }
+ init(false, newKey, newSigLength);
+ }
+
+ // deprecated but abstract
+ @SuppressWarnings("deprecation")
+ protected void engineSetParameter(String param, Object value) throws InvalidParameterException {
+ throw new UnsupportedOperationException("setParameter() not supported");
+ }
+
+ @Override
+ protected synchronized byte[] engineSign() throws SignatureException {
+ byte[] sig = new byte[sigLength];
+ int rv = doFinal(sig, 0, sigLength);
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ return sig;
+ }
+
+ @Override
+ protected synchronized int engineSign(byte[] outbuf, int offset, int len)
+ throws SignatureException {
+ if (outbuf == null || (offset < 0) || (outbuf.length < (offset + sigLength))
+ || (len < sigLength)) {
+ throw new SignatureException("Invalid output buffer");
+ }
+ int rv = doFinal(outbuf, offset, sigLength);
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ return sigLength;
+ }
+
+ @Override
+ protected synchronized void engineUpdate(byte b) throws SignatureException {
+ byte[] in = { b };
+ int rv = update(in, 0, 1);
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ }
+
+ @Override
+ protected synchronized void engineUpdate(byte[] in, int inOfs, int inLen)
+ throws SignatureException {
+ if (in == null || inOfs < 0 || inLen == 0) return;
+
+ int rv = update(in, inOfs, inLen);
+ if (rv < 0) {
+ throw new SignatureException(new UcryptoException(-rv));
+ }
+ }
+
+ @Override
+ protected synchronized void engineUpdate(ByteBuffer in) {
+ if (in == null || in.remaining() == 0) return;
+
+ if (in instanceof DirectBuffer == false) {
+ // cannot do better than default impl
+ super.engineUpdate(in);
+ return;
+ }
+ long inAddr = ((DirectBuffer)in).address();
+ int inOfs = in.position();
+ int inLen = in.remaining();
+
+ int rv = update((inAddr + inOfs), inLen);
+ if (rv < 0) {
+ throw new UcryptoException(-rv);
+ }
+ in.position(inOfs + inLen);
+ }
+
+ @Override
+ protected synchronized boolean engineVerify(byte[] sigBytes) throws SignatureException {
+ return engineVerify(sigBytes, 0, sigBytes.length);
+ }
+
+ @Override
+ protected synchronized boolean engineVerify(byte[] sigBytes, int sigOfs, int sigLen)
+ throws SignatureException {
+ if (sigBytes == null || (sigOfs < 0) || (sigBytes.length < (sigOfs + this.sigLength))
+ || (sigLen < this.sigLength)) {
+ throw new SignatureException("Invalid signature buffer");
+ }
+
+ int rv = doFinal(sigBytes, sigOfs, sigLen);
+ if (rv == 0) {
+ return true;
+ } else {
+ UcryptoProvider.debug("Signature: " + mech + " verification error " +
+ new UcryptoException(-rv).getMessage());
+ return false;
+ }
+ }
+
+ void reset(boolean doCancel) {
+ initialized = false;
+ if (pCtxt != null) {
+ pCtxt.dispose(doCancel);
+ pCtxt = null;
+ }
+ }
+
+ /**
+ * calls ucrypto_sign_init(...) or ucrypto_verify_init(...)
+ * @return pointer to the context
+ */
+ private native static long nativeInit(int mech, boolean sign,
+ long keyValue, int keyLength);
+
+ /**
+ * calls ucrypto_sign_update(...) or ucrypto_verify_update(...)
+ * @returns an error status code (0 means SUCCESS)
+ */
+ private native static int nativeUpdate(long pContext, boolean sign,
+ byte[] in, int inOfs, int inLen);
+ /**
+ * calls ucrypto_sign_update(...) or ucrypto_verify_update(...)
+ * @returns an error status code (0 means SUCCESS)
+ */
+ private native static int nativeUpdate(long pContext, boolean sign,
+ long pIn, int inLen);
+
+ /**
+ * calls ucrypto_sign_final(...) or ucrypto_verify_final(...)
+ * @returns the length of signature bytes or verification status.
+ * If negative, it indicates an error status code
+ */
+ private native static int nativeFinal(long pContext, boolean sign,
+ byte[] sig, int sigOfs, int sigLen);
+
+ // actual init() implementation - caller should clone key if needed
+ private void init(boolean sign, NativeKey key, int sigLength) {
+ reset(true);
+ this.sign = sign;
+ this.sigLength = sigLength;
+ this.key = key;
+ long pCtxtVal = nativeInit(mech.value(), sign, key.value(),
+ key.length());
+ initialized = (pCtxtVal != 0L);
+ if (initialized) {
+ pCtxt = new SignatureContextRef(this, pCtxtVal, sign);
+ } else {
+ throw new UcryptoException("Cannot initialize Signature");
+ }
+ }
+
+ private void ensureInitialized() {
+ if (!initialized) {
+ init(sign, key, sigLength);
+ if (!initialized) {
+ throw new UcryptoException("Cannot initialize Signature");
+ }
+ }
+ }
+
+ // returns 0 (success) or negative (ucrypto error occurred)
+ private int update(byte[] in, int inOfs, int inLen) {
+ if (inOfs < 0 || inOfs + inLen > in.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ ensureInitialized();
+ int k = nativeUpdate(pCtxt.id, sign, in, inOfs, inLen);
+ if (k < 0) {
+ reset(false);
+ }
+ return k;
+ }
+
+ // returns 0 (success) or negative (ucrypto error occurred)
+ private int update(long pIn, int inLen) {
+ ensureInitialized();
+ int k = nativeUpdate(pCtxt.id, sign, pIn, inLen);
+ if (k < 0) {
+ reset(false);
+ }
+ return k;
+ }
+
+ // returns 0 (success) or negative (ucrypto error occurred)
+ private int doFinal(byte[] sigBytes, int sigOfs, int sigLen) {
+ try {
+ ensureInitialized();
+ int k = nativeFinal(pCtxt.id, sign, sigBytes, sigOfs, sigLen);
+ return k;
+ } finally {
+ reset(false);
+ }
+ }
+
+ // check and return RSA key size in number of bytes
+ private int checkRSAKeyLength(BigInteger mod) throws InvalidKeyException {
+ int keySize = (mod.bitLength() + 7) >> 3;
+ int maxDataSize = keySize - PKCS1PADDING_LEN;
+ if (maxDataSize < encodedLen) {
+ throw new InvalidKeyException
+ ("Key is too short for this signature algorithm");
+ }
+ return keySize;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.util.*;
+import java.security.ProviderException;
+
+/**
+ * The exception class used by SunUcrypto provider. An exception
+ * object of this class indicates that a function call to the underlying
+ * native calls returned a value not equal to CRYPTO_SUCCESS.
+ *
+ * @since 1.9
+ */
+public final class UcryptoException extends ProviderException {
+
+ private static final long serialVersionUID = -933864511110035746L;
+
+ // NOTE: check /usr/include/sys/crypto/common.h for updates
+ private static final String ERROR_MSG[] = {
+ "CRYPTO_SUCCESS",
+ "CRYPTO_CANCEL",
+ "CRYPTO_HOST_MEMORY",
+ "CRYPTO_GENERAL_ERROR",
+ "CRYPTO_FAILED",
+ "CRYPTO_ARGUMENTS_BAD",
+ "CRYPTO_ATTRIBUTE_READ_ONLY",
+ "CRYPTO_ATTRIBUTE_SENSITIVE",
+ "CRYPTO_ATTRIBUTE_TYPE_INVALID",
+ "CRYPTO_ATTRIBUTE_VALUE_INVALID",
+ "CRYPTO_CANCELED",
+ "CRYPTO_DATA_INVALID",
+ "CRYPTO_DATA_LEN_RANGE",
+ "CRYPTO_DEVICE_ERROR",
+ "CRYPTO_DEVICE_MEMORY",
+ "CRYPTO_DEVICE_REMOVED",
+ "CRYPTO_ENCRYPTED_DATA_INVALID",
+ "CRYPTO_ENCRYPTED_DATA_LEN_RANGE",
+ "CRYPTO_KEY_HANDLE_INVALID",
+ "CRYPTO_KEY_SIZE_RANGE",
+ "CRYPTO_KEY_TYPE_INCONSISTENT",
+ "CRYPTO_KEY_NOT_NEEDED",
+ "CRYPTO_KEY_CHANGED",
+ "CRYPTO_KEY_NEEDED",
+ "CRYPTO_KEY_INDIGESTIBLE",
+ "CRYPTO_KEY_FUNCTION_NOT_PERMITTED",
+ "CRYPTO_KEY_NOT_WRAPPABLE",
+ "CRYPTO_KEY_UNEXTRACTABLE",
+ "CRYPTO_MECHANISM_INVALID",
+ "CRYPTO_MECHANISM_PARAM_INVALID",
+ "CRYPTO_OBJECT_HANDLE_INVALID",
+ "CRYPTO_OPERATION_IS_ACTIVE",
+ "CRYPTO_OPERATION_NOT_INITIALIZED",
+ "CRYPTO_PIN_INCORRECT",
+ "CRYPTO_PIN_INVALID",
+ "CRYPTO_PIN_LEN_RANGE",
+ "CRYPTO_PIN_EXPIRED",
+ "CRYPTO_PIN_LOCKED",
+ "CRYPTO_SESSION_CLOSED",
+ "CRYPTO_SESSION_COUNT",
+ "CRYPTO_SESSION_HANDLE_INVALID",
+ "CRYPTO_SESSION_READ_ONLY",
+ "CRYPTO_SESSION_EXISTS",
+ "CRYPTO_SESSION_READ_ONLY_EXISTS",
+ "CRYPTO_SESSION_READ_WRITE_SO_EXISTS",
+ "CRYPTO_SIGNATURE_INVALID",
+ "CRYPTO_SIGNATURE_LEN_RANGE",
+ "CRYPTO_TEMPLATE_INCOMPLETE",
+ "CRYPTO_TEMPLATE_INCONSISTENT",
+ "CRYPTO_UNWRAPPING_KEY_HANDLE_INVALID",
+ "CRYPTO_UNWRAPPING_KEY_SIZE_RANGE",
+ "CRYPTO_UNWRAPPING_KEY_TYPE_INCONSISTENT",
+ "CRYPTO_USER_ALREADY_LOGGED_IN",
+ "CRYPTO_USER_NOT_LOGGED_IN",
+ "CRYPTO_USER_PIN_NOT_INITIALIZED",
+ "CRYPTO_USER_TYPE_INVALID",
+ "CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN",
+ "CRYPTO_USER_TOO_MANY_TYPES",
+ "CRYPTO_WRAPPED_KEY_INVALID",
+ "CRYPTO_WRAPPED_KEY_LEN_RANGE",
+ "CRYPTO_WRAPPING_KEY_HANDLE_INVALID",
+ "CRYPTO_WRAPPING_KEY_SIZE_RANGE",
+ "CRYPTO_WRAPPING_KEY_TYPE_INCONSISTENT",
+ "CRYPTO_RANDOM_SEED_NOT_SUPPORTED",
+ "CRYPTO_RANDOM_NO_RNG",
+ "CRYPTO_DOMAIN_PARAMS_INVALID",
+ "CRYPTO_BUFFER_TOO_SMALL",
+ "CRYPTO_INFORMATION_SENSITIVE",
+ "CRYPTO_NOT_SUPPORTED",
+ "CRYPTO_QUEUED",
+ "CRYPTO_BUFFER_TOO_BIG",
+ "CRYPTO_INVALID_CONTEXT",
+ "CRYPTO_INVALID_MAC",
+ "CRYPTO_MECH_NOT_SUPPORTED",
+ "CRYPTO_INCONSISTENT_ATTRIBUTE",
+ "CRYPTO_NO_PERMISSION",
+ "CRYPTO_INVALID_PROVIDER_ID",
+ "CRYPTO_VERSION_MISMATCH",
+ "CRYPTO_BUSY",
+ "CRYPTO_UNKNOWN_PROVIDER",
+ "CRYPTO_MODVERIFICATION_FAILED",
+ "CRYPTO_OLD_CTX_TEMPLATE",
+ "CRYPTO_WEAK_KEY",
+ "CRYPTO_FIPS140_ERROR"
+ };
+
+ /**
+ * The error code if this exception is triggered by a Ucrypto error.
+ */
+ private final int errorCode;
+
+ /**
+ * This method gets the corresponding text error message from a
+ * predefined mapping. If mapping is not found, then it returns the error
+ * code as a hex-string.
+ *
+ * @return The message or the error code; e.g. "CRYPTO_DATA_INVALID" or
+ * "0x88".
+ */
+ static String getErrorMessage(int errorCode) {
+ String message;
+ if (errorCode < ERROR_MSG.length) {
+ message = ERROR_MSG[errorCode];
+ } else {
+ message = "0x" + Integer.toHexString(errorCode);
+ }
+ return message;
+ }
+
+ /**
+ * Constructor taking the error code as defined for the CRYPTO_* constants
+ */
+ public UcryptoException(int rv) {
+ super(getErrorMessage(rv));
+ this.errorCode = rv;
+ }
+
+ public UcryptoException(String message) {
+ super(message);
+ errorCode = -1;
+ }
+
+ public UcryptoException(String message, Throwable cause) {
+ super(message, cause);
+ errorCode = -1;
+ }
+
+ /**
+ * Returns the Ucrypto error code.
+ *
+ * @return The error code.
+ */
+ public int getErrorCode() {
+ return errorCode;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.util.HashMap;
+
+/**
+ * Enum for representing the ucrypto mechanisms.
+ *
+ * @since 1.9
+ */
+// Check /usr/include/libsoftcrypto.h for updates
+public enum UcryptoMech {
+ CRYPTO_AES_ECB(1, new String[]
+ { "Cipher.AES/ECB/NoPadding;com.oracle.security.ucrypto.NativeCipher$AesEcbNoPadding",
+ "Cipher.AES/ECB/PKCS5Padding;com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesEcbPKCS5",
+ "Cipher.AES_128/ECB/NoPadding;com.oracle.security.ucrypto.NativeCipher$Aes128EcbNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.1;AES_128/ECB/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.1;AES_128/ECB/NoPadding",
+ "Cipher.AES_192/ECB/NoPadding;com.oracle.security.ucrypto.NativeCipher$Aes192EcbNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.21;AES_192/ECB/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.21;AES_192/ECB/NoPadding",
+ "Cipher.AES_256/ECB/NoPadding;com.oracle.security.ucrypto.NativeCipher$Aes256EcbNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.41;AES_256/ECB/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.41;AES_256/ECB/NoPadding"
+ }),
+ CRYPTO_AES_CBC(2, new String[]
+ { "Cipher.AES/CBC/NoPadding;com.oracle.security.ucrypto.NativeCipher$AesCbcNoPadding",
+ "Cipher.AES/CBC/PKCS5Padding;com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCbcPKCS5",
+ "Cipher.AES_128/CBC/NoPadding;com.oracle.security.ucrypto.NativeCipher$Aes128CbcNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.2;AES_128/CBC/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.2;AES_128/CBC/NoPadding",
+ "Cipher.AES_192/CBC/NoPadding;com.oracle.security.ucrypto.NativeCipher$Aes192CbcNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.22;AES_192/CBC/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.22;AES_192/CBC/NoPadding",
+ "Cipher.AES_256/CBC/NoPadding;com.oracle.security.ucrypto.NativeCipher$Aes256CbcNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.42;AES_256/CBC/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.42;AES_256/CBC/NoPadding"
+ }),
+ CRYPTO_AES_CBC_PAD(3, null), // No support from Solaris yet
+ CRYPTO_AES_CTR(4, new String[]
+ { "Cipher.AES/CTR/NoPadding;com.oracle.security.ucrypto.NativeCipher$AesCtrNoPadding" }),
+ CRYPTO_AES_CCM(5, null), // Cannot support due to lack of Java API which corresponds to CK_AES_CCM_PARAMS
+ CRYPTO_AES_GCM(6, new String[]
+ { "Cipher.AES/GCM/NoPadding;com.oracle.security.ucrypto.NativeGCMCipher$AesGcmNoPadding",
+ "Cipher.AES_128/GCM/NoPadding;com.oracle.security.ucrypto.NativeGCMCipher$Aes128GcmNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.6;AES_128/GCM/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.6;AES_128/GCM/NoPadding",
+ "Cipher.AES_192/GCM/NoPadding;com.oracle.security.ucrypto.NativeGCMCipher$Aes192GcmNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.26;AES_192/GCM/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.26;AES_192/GCM/NoPadding",
+ "Cipher.AES_256/GCM/NoPadding;com.oracle.security.ucrypto.NativeGCMCipher$Aes256GcmNoPadding",
+ "Alg.Alias.Cipher.2.16.840.1.101.3.4.1.46;AES_256/GCM/NoPadding",
+ "Alg.Alias.Cipher.OID.2.16.840.1.101.3.4.1.46;AES_256/GCM/NoPadding",
+ }),
+ CRYPTO_AES_GMAC(7, null), // No support from Solaris yet
+ CRYPTO_AES_CFB128(8, new String[]
+ { "Cipher.AES/CFB128/NoPadding;com.oracle.security.ucrypto.NativeCipher$AesCfb128NoPadding",
+ "Cipher.AES/CFB128/PKCS5Padding;com.oracle.security.ucrypto.NativeCipherWithJavaPadding$AesCfb128PKCS5" }),
+ CRYPTO_RSA_PKCS(31, new String[]
+ { "Cipher.RSA/ECB/PKCS1Padding;com.oracle.security.ucrypto.NativeRSACipher$PKCS1Padding" }),
+ CRYPTO_RSA_X_509(32, new String[]
+ { "Cipher.RSA/ECB/NoPadding;com.oracle.security.ucrypto.NativeRSACipher$NoPadding" }),
+ CRYPTO_MD5_RSA_PKCS(33, new String[]
+ { "Signature.MD5withRSA;com.oracle.security.ucrypto.NativeRSASignature$MD5",
+ "Alg.Alias.Signature.1.2.840.113549.1.1.4;MD5withRSA",
+ "Alg.Alias.Signature.OID.1.2.840.113549.1.1.4;MD5withRSA" }),
+ CRYPTO_SHA1_RSA_PKCS(34, new String[]
+ { "Signature.SHA1withRSA;com.oracle.security.ucrypto.NativeRSASignature$SHA1",
+ "Alg.Alias.Signature.1.2.840.113549.1.1.5;SHA1withRSA",
+ "Alg.Alias.Signature.OID.1.2.840.113549.1.1.5;SHA1withRSA",
+ "Alg.Alias.Signature.1.3.14.3.2.29;SHA1withRSA" }),
+ CRYPTO_SHA256_RSA_PKCS(35, new String[]
+ { "Signature.SHA256withRSA;com.oracle.security.ucrypto.NativeRSASignature$SHA256",
+ "Alg.Alias.Signature.1.2.840.113549.1.1.11;SHA256withRSA",
+ "Alg.Alias.Signature.OID.1.2.840.113549.1.1.11;SHA256withRSA" }),
+ CRYPTO_SHA384_RSA_PKCS(36, new String[]
+ { "Signature.SHA384withRSA;com.oracle.security.ucrypto.NativeRSASignature$SHA384",
+ "Alg.Alias.Signature.1.2.840.113549.1.1.12;SHA384withRSA",
+ "Alg.Alias.Signature.OID.1.2.840.113549.1.1.12;SHA384withRSA" }),
+ CRYPTO_SHA512_RSA_PKCS(37, new String[]
+ { "Signature.SHA512withRSA;com.oracle.security.ucrypto.NativeRSASignature$SHA512",
+ "Alg.Alias.Signature.1.2.840.113549.1.1.13;SHA512withRSA",
+ "Alg.Alias.Signature.OID.1.2.840.113549.1.1.13;SHA512withRSA" });
+
+ private int mech;
+ private String[] jceProps;
+
+ UcryptoMech(int mech, String[] jceProps) {
+ this.mech = mech;
+ this.jceProps = jceProps;
+ }
+
+ public int value() { return mech; }
+ public String[] jceProperties() { return jceProps; }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.oracle.security.ucrypto;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+import java.security.*;
+import sun.security.action.PutAllAction;
+import sun.security.action.GetPropertyAction;
+
+/**
+ * OracleUcrypto provider main class.
+ *
+ * @since 1.9
+ */
+public final class UcryptoProvider extends Provider {
+
+ private static final long serialVersionUID = 351251234302833L;
+
+ private static boolean DEBUG;
+ private static HashMap<String, String> provProp;
+
+ static {
+ try {
+ DEBUG = Boolean.parseBoolean(AccessController.doPrivileged
+ (new GetPropertyAction("com.oracle.security.ucrypto.debug")));
+
+ // cannot use LoadLibraryAction because that would make the native
+ // library available to the bootclassloader, but we run in the
+ // extension classloader.
+ provProp = AccessController.doPrivileged
+ (new PrivilegedAction<HashMap<String, String>>() {
+ public HashMap<String, String> run() {
+ try {
+ System.loadLibrary("j2ucrypto");
+ String osname = System.getProperty("os.name");
+ if (osname.startsWith("SunOS")) {
+ return new HashMap<String, String>();
+ } else return null;
+ } catch (Error err) {
+ return null;
+ } catch (SecurityException se) {
+ return null;
+ }
+ }
+ });
+ if (provProp != null) {
+ boolean[] result = loadLibraries();
+ if (result.length == 2) {
+ if (result[0]) { // successfully loaded libmd
+ provProp.put("MessageDigest.MD5",
+ "com.oracle.security.ucrypto.NativeDigest$MD5");
+ provProp.put("MessageDigest.SHA",
+ "com.oracle.security.ucrypto.NativeDigest$SHA1");
+ provProp.put("Alg.Alias.MessageDigest.SHA-1", "SHA");
+ provProp.put("Alg.Alias.MessageDigest.SHA1", "SHA");
+ provProp.put("MessageDigest.SHA-256",
+ "com.oracle.security.ucrypto.NativeDigest$SHA256");
+ provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.1", "SHA-256");
+ provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.1", "SHA-256");
+
+ provProp.put("MessageDigest.SHA-384",
+ "com.oracle.security.ucrypto.NativeDigest$SHA384");
+ provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.2", "SHA-384");
+ provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.2", "SHA-384");
+
+ provProp.put("MessageDigest.SHA-512",
+ "com.oracle.security.ucrypto.NativeDigest$SHA512");
+ provProp.put("Alg.Alias.MessageDigest.2.16.840.1.101.3.4.2.3", "SHA-512");
+ provProp.put("Alg.Alias.MessageDigest.OID.2.16.840.1.101.3.4.2.3", "SHA-512");
+
+ }
+ if (result[1]) { // successfully loaded libsoftcrypto
+ String supportedMechs = getMechList();
+ debug("Prov: supported mechs = " + supportedMechs);
+ for (UcryptoMech m : UcryptoMech.values()) {
+ if (supportedMechs.indexOf(m.name() + ",") != -1) {
+ String[] jceProps = m.jceProperties();
+ // skip unsupported UcryptoMech
+ if (jceProps == null) continue;
+ for (int p = 0; p < jceProps.length; p++) {
+ StringTokenizer st =
+ new StringTokenizer(jceProps[p], ";");
+ if (st.countTokens() != 2) {
+ throw new RuntimeException("Wrong format: " + jceProps[p]);
+ }
+ provProp.put(st.nextToken(), st.nextToken());
+ }
+ }
+ }
+ // NOTE: GCM support is only available since jdk 7
+ provProp.put("AlgorithmParameters.GCM",
+ "com.oracle.security.ucrypto.GCMParameters");
+ }
+ } else {
+ debug("Prov: unexpected ucrypto library loading error, got " + result.length);
+ }
+ }
+ } catch (AccessControlException ace) {
+ // disable Ucrypto provider
+ DEBUG = false;
+ provProp = null;
+ }
+ }
+
+ static Provider provider = null;
+ private static native boolean[] loadLibraries();
+ private static native String getMechList();
+
+ static void debug(String msg) {
+ if (DEBUG) {
+ System.out.println("UCrypto/" + msg);
+ }
+ }
+
+ public UcryptoProvider() {
+ super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
+ if (provProp != null) {
+ AccessController.doPrivileged(new PutAllAction(this, provProp));
+ }
+ if (provider == null) provider = this;
+ }
+
+ public UcryptoProvider(String configName) {
+ super("OracleUcrypto", 1.9d, "Provider using Oracle Ucrypto API");
+ try {
+ if (provProp != null) {
+ HashMap<String, String> customProvProp =
+ new HashMap<String, String>(provProp);
+ Config c = new Config(configName);
+ String[] disabledServices = c.getDisabledServices();
+ for (int i = 0; i < disabledServices.length; i++) {
+ if (customProvProp.remove(disabledServices[i]) != null) {
+ debug("Prov: remove config-disabled service " + disabledServices[i]);
+ } else {
+ debug("Prov: ignore unsupported config-disabled service " +
+ disabledServices[i]);
+ }
+ }
+ AccessController.doPrivileged(new PutAllAction(this, customProvProp));
+ }
+ } catch (IOException ioe) { // thrown by Config
+ throw new UcryptoException("Error parsing Config", ioe);
+ }
+ if (provider == null) provider = this;
+ }
+
+ public boolean equals(Object obj) {
+ return this == obj;
+ }
+
+ public int hashCode() {
+ return System.identityHashCode(this);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/conf/security/ucrypto-solaris.cfg Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,9 @@
+#
+# Configuration file for the OracleUcrypto provider
+#
+disabledServices = {
+ # disabled due to Solaris bug 7121679
+ Cipher.AES/CFB128/PKCS5Padding
+ Cipher.AES/CFB128/NoPadding
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.c Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,1250 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <jni.h>
+#include <libsoftcrypto.h>
+#include "nativeCrypto.h"
+#include "nativeFunc.h"
+
+/*
+ * Dumps out byte array in hex with and name and length info
+ */
+void printBytes(char* header, unsigned char* bytes, int len) {
+ int i;
+
+ printf("%s", header);
+ printf("len=%d {", len);
+ for (i = 0; i < len; i++) {
+ if (i > 0) printf(":");
+ printf("%02X", bytes[i]);
+ }
+ printf("}\n");
+}
+
+/*
+ * Throws java.lang.OutOfMemoryError
+ */
+void throwOutOfMemoryError(JNIEnv *env, const char *msg)
+{
+ jclass jExClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
+ if (jExClass != 0) /* Otherwise an exception has already been thrown */ {
+ (*env)->ThrowNew(env, jExClass, msg);
+ }
+ /* free the local ref */
+ (*env)->DeleteLocalRef(env, jExClass);
+}
+
+JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
+ return JNI_VERSION_1_4;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_UcryptoProvider
+ * Method: loadLibraries
+ * Signature: ()[Z
+ */
+JNIEXPORT jbooleanArray JNICALL Java_com_oracle_security_ucrypto_UcryptoProvider_loadLibraries
+(JNIEnv *env, jclass jcls) {
+ jbooleanArray jResult;
+ jboolean *result;
+ jResult = (*env)->NewBooleanArray(env, 2);
+
+ if (jResult != NULL) {
+ result = loadNative();
+ (*env)->SetBooleanArrayRegion(env, jResult, 0, 2, result);
+ free(result);
+ }
+ return jResult;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_UcryptoProvider
+ * Method: getMechList
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_oracle_security_ucrypto_UcryptoProvider_getMechList
+(JNIEnv *env, jclass jcls) {
+ jstring jResult;
+ char* result;
+ int length;
+
+ jResult = NULL;
+ if (ftab->ucryptoVersion != NULL && ftab->ucryptoGetMechList != NULL) {
+ length = (*ftab->ucryptoGetMechList)(NULL);
+ if (DEBUG) printf("mech list length: %d\n", length);
+ result = malloc(length);
+ if (result == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return NULL;
+ }
+ length = (*ftab->ucryptoGetMechList)(result);
+ if (DEBUG) printf("mech list: %s\n", result);
+ jResult = (*env)->NewStringUTF(env, result);
+ free(result);
+ } else {
+ // version 0 on Solaris 10
+ result = "CRYPTO_AES_ECB,CRYPTO_AES_CBC,CRYPTO_AES_CFB128,";
+ jResult = (*env)->NewStringUTF(env, result);
+ }
+ return jResult;
+}
+
+/*
+ * Utility function for throwing a UcryptoException when rv is not CRYPTO_OK(0)
+ */
+void throwUCExceptionUsingRV(JNIEnv *env, int rv) {
+ jclass jExClass;
+ jmethodID jConstructor;
+ jthrowable jException;
+
+ if ((*env)->ExceptionCheck(env)) return;
+
+ jExClass = (*env)->FindClass(env, "com/oracle/security/ucrypto/UcryptoException");
+ /* if jExClass is NULL, an exception has already been thrown */
+ if (jExClass != NULL) {
+ jConstructor = (*env)->GetMethodID(env, jExClass, "<init>", "(I)V");
+ if (jConstructor != NULL) {
+ jException = (jthrowable) (*env)->NewObject(env, jExClass, jConstructor, rv);
+ if (jException != NULL) {
+ (*env)->Throw(env, jException);
+ }
+ }
+ }
+ /* free the local ref */
+ (*env)->DeleteLocalRef(env, jExClass);
+}
+
+/*
+ * Utility function for duplicating a byte array from jbyteArray
+ * If anything went wrong, no memory will be allocated.
+ * NOTE: caller is responsible for freeing the allocated memory
+ * once this method returned successfully.
+ */
+jbyte* getBytes(JNIEnv *env, jbyteArray bytes, int offset, int len) {
+ jbyte* result = NULL;
+
+ if (!(*env)->ExceptionCheck(env)) {
+ result = (jbyte*) calloc(len, sizeof(char));
+ if (result == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return NULL;
+ }
+ (*env)->GetByteArrayRegion(env, bytes, offset, len, result);
+ if ((*env)->ExceptionCheck(env)) {
+ // free allocated memory if error occurred
+ free(result);
+ return NULL;
+ }
+ }
+ return result;
+}
+
+
+int
+CipherInit(crypto_ctx_t *context, int encrypt, ucrypto_mech_t mech,
+ unsigned char *jKey, int jKeyLen, unsigned char *jIv, int jIvLen,
+ int tagLen, unsigned char *jAad, int jAadLen)
+
+{
+ int rv = 0;
+ void *iv;
+ size_t ivLen;
+
+ if (DEBUG) printf("CipherInit: mech %i, key %i(%i), iv %i(%i) tagLen %i, aad %i(%i)\n",
+ mech, jKey, jKeyLen, jIv, jIvLen, tagLen, jAad, jAadLen);
+ if (mech == CRYPTO_AES_CTR) {
+ ivLen = sizeof(CK_AES_CTR_PARAMS);
+ iv = (CK_AES_CTR_PARAMS*) malloc(ivLen);
+ if (iv == NULL) return -1;
+
+ ((CK_AES_CTR_PARAMS*)iv)->ulCounterBits = 32;
+ memcpy(((CK_AES_CTR_PARAMS*)iv)->cb, jIv, 16);
+ } else if (mech == CRYPTO_AES_GCM) {
+ ivLen = sizeof(CK_AES_GCM_PARAMS);
+ iv = (CK_AES_GCM_PARAMS*) malloc(ivLen);
+ if (iv == NULL) return -1;
+
+ ((CK_AES_GCM_PARAMS*)iv)->pIv = (uchar_t *)jIv;
+ ((CK_AES_GCM_PARAMS*)iv)->ulIvLen = (ulong_t)jIvLen;
+ ((CK_AES_GCM_PARAMS*)iv)->ulIvBits = 96;
+ ((CK_AES_GCM_PARAMS*)iv)->pAAD = (uchar_t *)jAad;
+ ((CK_AES_GCM_PARAMS*)iv)->ulAADLen = (ulong_t)jAadLen;
+ ((CK_AES_GCM_PARAMS*)iv)->ulTagBits = (ulong_t)tagLen;
+ } else {
+ // normal bytes
+ iv = jIv;
+ ivLen = jIvLen;
+ }
+ if (encrypt) {
+ rv = (*ftab->ucryptoEncryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
+ if (rv != 0 && DEBUG) printf("ucryptoEncryptInit: ret = 0x%x\n", rv);
+ } else {
+ rv =(*ftab->ucryptoDecryptInit)(context, mech, jKey, (size_t)jKeyLen, iv, ivLen);
+ if (rv != 0 && DEBUG) printf("ucryptoDecryptInit: ret = 0x%x\n", rv);
+ }
+
+ if (iv != jIv) {
+ if (mech == CRYPTO_AES_CTR) {
+ free((CK_AES_CTR_PARAMS*)iv);
+ } else {
+ free((CK_AES_GCM_PARAMS*)iv);
+ }
+ }
+
+ return rv;
+}
+
+int
+CipherUpdate(crypto_ctx_t *context, int encrypt, unsigned char *bufIn, int inOfs,
+ int inLen, unsigned char *bufOut, int outOfs, int *outLen)
+{
+ int rv = 0;
+ size_t outLength;
+
+ outLength = (size_t) *outLen;
+ if (DEBUG) {
+ printf("CipherUpdate: Inofs %i, InLen %i, OutOfs %i, OutLen %i\n", inOfs, inLen, outOfs, *outLen);
+ printBytes("BufIn=", (unsigned char*)(bufIn+inOfs), inLen);
+ }
+ if (encrypt) {
+ rv = (*ftab->ucryptoEncryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
+ if (rv != 0) {
+ if (DEBUG) printf("ucryptoEncryptUpdate: ret = 0x%x\n", rv);
+ } else {
+ *outLen = (int)outLength;
+ }
+ } else {
+ rv = (*ftab->ucryptoDecryptUpdate)(context, (unsigned char*)(bufIn+inOfs), (size_t)inLen, (unsigned char*)(bufOut+outOfs), &outLength);
+ if (rv != 0) {
+ if (DEBUG) printf("ucryptoDecryptUpdate: ret = 0x%x\n", rv);
+ } else {
+ if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
+ *outLen = (int)outLength;
+ }
+ }
+
+ return rv;
+}
+
+int
+CipherFinal(crypto_ctx_t *context, int encrypt, unsigned char *bufOut, int outOfs, int *outLen)
+{
+ int rv = 0;
+ size_t outLength;
+
+ outLength = (size_t)*outLen;
+
+ if (DEBUG) printf("CipherFinal: OutOfs %i, outLen %i\n", outOfs, *outLen);
+ if (encrypt) {
+ rv = (*ftab->ucryptoEncryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
+ if (rv != 0) {
+ if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+ } else {
+ if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
+ *outLen = (int)outLength;
+ }
+ } else {
+ rv = (*ftab->ucryptoDecryptFinal)(context, (unsigned char*)(bufOut+outOfs), &outLength);
+ if (rv != 0) {
+ if (DEBUG) printf("ucryptoDecryptFinal: ret = 0x%x\n", rv);
+ } else {
+ if (DEBUG) printBytes("BufOut=", (unsigned char*)(bufOut+outOfs), outLength);
+ *outLen = (int)outLength;
+ }
+ }
+ return rv;
+}
+
+////////////////////////////////////////////////////////
+// SPECIAL ENTRIES FOR JVM JNI-BYPASSING OPTIMIZATION
+////////////////////////////////////////////////////////
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(jint mech) {
+ void *pContext = NULL;
+
+ switch (mech) {
+ case com_oracle_security_ucrypto_NativeDigest_MECH_SHA1:
+ pContext = (SHA1_CTX *) malloc(sizeof(SHA1_CTX));
+ if (pContext != NULL) {
+ (*ftab->sha1Init)((SHA1_CTX *)pContext);
+ }
+ break;
+ case com_oracle_security_ucrypto_NativeDigest_MECH_MD5:
+ pContext = (MD5_CTX *) malloc(sizeof(MD5_CTX));
+ if (pContext != NULL) {
+ (*ftab->md5Init)((MD5_CTX *)pContext);
+ }
+ break;
+ case com_oracle_security_ucrypto_NativeDigest_MECH_SHA256:
+ pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
+ if (pContext != NULL) {
+ (*ftab->sha2Init)(SHA256, (SHA2_CTX *)pContext);
+ }
+ break;
+ case com_oracle_security_ucrypto_NativeDigest_MECH_SHA384:
+ pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
+ if (pContext != NULL) {
+ (*ftab->sha2Init)(SHA384, (SHA2_CTX *)pContext);
+ }
+ break;
+ case com_oracle_security_ucrypto_NativeDigest_MECH_SHA512:
+ pContext = (SHA2_CTX *) malloc(sizeof(SHA2_CTX));
+ if (pContext != NULL) {
+ (*ftab->sha2Init)(SHA512, (SHA2_CTX *)pContext);
+ }
+ break;
+ default:
+ if (DEBUG) printf("ERROR: Unsupported mech %i\n", mech);
+ }
+ return (jlong) pContext;
+}
+
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
+ (jint mech, jlong pContext, int notUsed, unsigned char* in, jint ofs, jint len) {
+ if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
+ (*ftab->sha1Update)((SHA1_CTX*)pContext, (unsigned char*)(in+ofs), len);
+ } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
+ (*ftab->md5Update)((MD5_CTX*)pContext, (unsigned char*)(in+ofs), len);
+ } else { // SHA-2 family
+ (*ftab->sha2Update)((SHA2_CTX*)pContext, (unsigned char*)(in+ofs), len);
+ }
+ return 0;
+}
+
+// Do digest and free the context immediately
+jint JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest
+ (jint mech, jlong pContext, int notUsed, unsigned char* out, jint ofs, jint digestLen) {
+
+ if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
+ (*ftab->sha1Final)((unsigned char*)(out + ofs), (SHA1_CTX *)pContext);
+ free((SHA1_CTX *)pContext);
+ } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
+ (*ftab->md5Final)((unsigned char*)(out + ofs), (MD5_CTX *)pContext);
+ free((MD5_CTX *)pContext);
+ } else { // SHA-2 family
+ (*ftab->sha2Final)((unsigned char*)(out + ofs), (SHA2_CTX *)pContext);
+ free((SHA2_CTX *)pContext);
+ }
+ return 0;
+}
+
+jlong JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone
+ (jint mech, jlong pContext) {
+ void *copy = NULL;
+ size_t len = 0;
+
+ if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
+ len = sizeof(SHA1_CTX);
+ } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
+ len = sizeof(MD5_CTX);
+ } else { // SHA-2 family
+ len = sizeof(SHA2_CTX);
+ }
+ copy = (void*) malloc(len);
+ if (copy != NULL) {
+ bcopy((void *)pContext, copy, len);
+ }
+ return (jlong) copy;
+}
+
+void JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree
+ (jint mech, jlong pContext) {
+ if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_SHA1) {
+ free((SHA1_CTX*) pContext);
+ } else if (mech == com_oracle_security_ucrypto_NativeDigest_MECH_MD5) {
+ free((MD5_CTX*) pContext);
+ } else { // SHA-2 family
+ free((SHA2_CTX*) pContext);
+ }
+}
+
+// AES
+jlong JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeInit
+ (jint mech, jboolean encrypt, int keyLen, unsigned char* bufKey,
+ int ivLen, unsigned char* bufIv, jint tagLen, int aadLen, unsigned char* bufAad) {
+ crypto_ctx_t *context = NULL;
+ int rv;
+
+ context = malloc(sizeof(crypto_ctx_t));
+ if (context != NULL) {
+ rv = CipherInit(context, encrypt, (ucrypto_mech_t) mech, bufKey, keyLen,
+ bufIv, ivLen, tagLen, bufAad, aadLen);
+ if (rv) {
+ free(context);
+ return 0L;
+ }
+ }
+ return (jlong)context;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeCipher
+ * Method: nativeUpdate
+ * Signature: (JZ[BII[BI)I
+ */
+jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeUpdate
+ (jlong pContext, jboolean encrypt, int notUsed, jbyte* bufIn, jint inOfs, jint inLen,
+ int outCapacity, jbyte* bufOut, jint outOfs) {
+ crypto_ctx_t *context;
+ int rv = 0;
+ int outLen = outCapacity - outOfs; // recalculate the real out length
+
+ context = (crypto_ctx_t *) pContext;
+ rv = CipherUpdate(context, encrypt, (unsigned char*)bufIn, inOfs, inLen, (unsigned char*)bufOut, outOfs, &outLen);
+ if (rv) {
+ free(context);
+ context = 0;
+ return -rv; // use negative value to indicate error!
+ }
+
+ return outLen;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeCipher
+ * Method: nativeFinal
+ * Signature: (JZ[BI)I
+ */
+jint JavaCritical_com_oracle_security_ucrypto_NativeCipher_nativeFinal
+ (jlong pContext, jboolean encrypt, int outLen, jbyte* bufOut, jint outOfs) {
+ crypto_ctx_t *context;
+ int rv = 0;
+
+ context = (crypto_ctx_t *) pContext;
+ rv = CipherFinal(context, encrypt, (unsigned char*)bufOut, outOfs, &outLen);
+ free(context);
+ if (rv) {
+ return -rv; // use negative value to indicate error!
+ }
+
+ return outLen;
+}
+
+
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeDigest
+ * Method: nativeInit
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeInit
+ (JNIEnv *env, jclass jcls, jint mech) {
+ jlong result = JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeInit(mech);
+ if (result == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ }
+ return result;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeDigest
+ * Method: nativeUpdate
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeUpdate
+ (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jIn, jint jOfs, jint jLen) {
+ unsigned char *bufIn;
+
+ bufIn = (unsigned char *) getBytes(env, jIn, jOfs, jLen);
+ if (!(*env)->ExceptionCheck(env)) {
+ JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeUpdate(mech, pContext, jLen, bufIn, 0, jLen);
+ free(bufIn);
+ }
+ return 0;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeDigest
+ * Method: nativeDigest
+ * Signature: (IJ[BII)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeDigest
+ (JNIEnv *env, jclass jcls, jint mech, jlong pContext, jbyteArray jOut, jint jOutOfs, jint digestLen) {
+ unsigned char *bufOut;
+
+ bufOut = (unsigned char *) malloc(digestLen);
+ if (bufOut == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return 0;
+ }
+
+ JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeDigest(mech, pContext, digestLen, bufOut, 0, digestLen);
+
+ (*env)->SetByteArrayRegion(env, jOut, jOutOfs, digestLen, (jbyte *) bufOut);
+ free(bufOut);
+ return 0;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeDigest
+ * Method: nativeClone
+ * Signature: (IJ)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeClone
+ (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+ return JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeClone(mech, pContext);
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeDigest
+ * Method: nativeFree
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeDigest_nativeFree
+ (JNIEnv *env, jclass jcls, jint mech, jlong pContext) {
+ JavaCritical_com_oracle_security_ucrypto_NativeDigest_nativeFree(mech, pContext);
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeCipher
+ * Method: nativeInit
+ * Signature: (IZ[B[BI[B)J
+ */
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeInit
+(JNIEnv *env, jclass jcls, jint mech, jboolean encrypt, jbyteArray jKey,
+ jbyteArray jIv, jint tagLen, jbyteArray jAad) {
+
+ crypto_ctx_t *context;
+ unsigned char *bufKey;
+ unsigned char *bufIv;
+ unsigned char *bufAad;
+ int keyLen, ivLen, aadLen, rv = 0;
+ jlong result = 0L;
+
+ bufKey = bufIv = bufAad = NULL;
+ keyLen = ivLen = aadLen = 0;
+ context = malloc(sizeof(crypto_ctx_t));
+ if (context == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return 0L;
+ }
+
+ // jKey MUST NOT BE NULL;
+ keyLen = (*env)->GetArrayLength(env, jKey);
+ bufKey = (unsigned char *) (*env)->GetByteArrayElements(env, jKey, NULL);
+ if (bufKey == NULL) {
+ goto cleanup;
+ }
+
+ if (jIv != NULL) {
+ ivLen = (*env)->GetArrayLength(env, jIv);
+ bufIv = (unsigned char *) (*env)->GetByteArrayElements(env, jIv, NULL);
+ if (bufIv == NULL) {
+ goto cleanup;
+ }
+ }
+
+ if (jAad != NULL) {
+ aadLen = (*env)->GetArrayLength(env, jAad);
+ bufAad = (unsigned char *) (*env)->GetByteArrayElements(env, jAad, NULL);
+ if (bufAad == NULL) {
+ goto cleanup;
+ }
+ }
+
+ rv = CipherInit(context, encrypt, mech, bufKey, keyLen, bufIv, ivLen, tagLen, bufAad, aadLen);
+ if (rv != 0) {
+ throwUCExceptionUsingRV(env, rv);
+ } else {
+ result = (jlong) context;
+ }
+
+cleanup:
+ if ((result == 0L) && (context != NULL)) {
+ free(context);
+ }
+ if (bufKey != NULL) {
+ (*env)->ReleaseByteArrayElements(env, jKey, (jbyte *)bufKey, 0);
+ }
+ if (bufIv != NULL) {
+ (*env)->ReleaseByteArrayElements(env, jIv, (jbyte *)bufIv, 0);
+ }
+ if (bufAad != NULL) {
+ (*env)->ReleaseByteArrayElements(env, jAad, (jbyte *)bufAad, 0);
+ }
+
+ return result;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeCipher
+ * Method: nativeUpdate
+ * Signature: (JZ[BII[BI)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeUpdate
+ (JNIEnv *env, jclass jcls, jlong contextID, jboolean encrypt,
+ jbyteArray jIn, jint inOfs, jint inLen, jbyteArray jOut, jint outOfs) {
+ crypto_ctx_t *context;
+ unsigned char *bufIn;
+ unsigned char *bufOut;
+ int outLen, rv = 0;
+
+ context = (crypto_ctx_t *) contextID;
+ bufIn = (unsigned char *) getBytes(env, jIn, inOfs, inLen);
+ if ((*env)->ExceptionCheck(env)) {
+ return 0;
+ }
+
+ outLen = (*env)->GetArrayLength(env, jOut) - outOfs;
+ bufOut = calloc(outLen, sizeof(char));
+ if (bufOut == NULL) {
+ free(bufIn);
+ throwOutOfMemoryError(env, NULL);
+ return 0;
+ }
+
+ rv = CipherUpdate(context, encrypt, bufIn, 0, inLen, bufOut, 0, &outLen);
+ if (rv) {
+ free(context);
+ free(bufIn);
+ free(bufOut);
+ return -rv;
+ } else {
+ (*env)->SetByteArrayRegion(env, jOut, outOfs, outLen, (jbyte *)bufOut);
+ free(bufIn);
+ free(bufOut);
+ return outLen;
+ }
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeCipher
+ * Method: nativeFinal
+ * Signature: (JZ[BI)I
+ */
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeCipher_nativeFinal
+ (JNIEnv *env, jclass jCls, jlong contextID, jboolean encrypt,
+ jbyteArray out, jint outOfs) {
+ crypto_ctx_t *context;
+ unsigned char *bufIn;
+ unsigned char *bufOut;
+ int outLen, rv = 0;
+
+ context = (crypto_ctx_t *) contextID;
+
+ // out is null when nativeFinal() is called solely for resource clean up
+ if (out == NULL) {
+ bufOut = NULL;
+ outLen = 0;
+ } else {
+ outLen = (*env)->GetArrayLength(env, out) - outOfs;
+ bufOut = calloc(outLen, sizeof(char));
+ if (bufOut == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return 0;
+ }
+ }
+ rv = CipherFinal(context, encrypt, bufOut, 0, &outLen);
+ if (rv) {
+ free(context);
+ free(bufOut);
+ return -rv;
+ } else {
+ if (bufOut != NULL) {
+ (*env)->SetByteArrayRegion(env, out, outOfs, outLen, (jbyte *)bufOut);
+ free(bufOut);
+ }
+ free(context);
+ return outLen;
+ }
+}
+
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeKey
+ * Method: nativeFree
+ * Signature: (JI)V
+ */
+void JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree
+ (jlong id, jint numOfComponents) {
+ crypto_object_attribute_t* pKey;
+ int i;
+
+ pKey = (crypto_object_attribute_t*) id;
+ for (i = 0; i < numOfComponents; i++) {
+ free(pKey[i].oa_value);
+ }
+ free(pKey);
+}
+
+JNIEXPORT void JNICALL Java_com_oracle_security_ucrypto_NativeKey_nativeFree
+ (JNIEnv *env, jclass jCls, jlong id, jint numOfComponents) {
+ JavaCritical_com_oracle_security_ucrypto_NativeKey_nativeFree(id, numOfComponents);
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeKey_RSAPrivateCrt
+ * Method: nativeInit
+ * Signature: ([B[B[B[B[B[B[B[B)J
+ */
+jlong JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit
+(int modLen, jbyte* jMod, int pubLen, jbyte* jPub, int privLen, jbyte* jPriv,
+ int pLen, jbyte* jP, int qLen, jbyte* jQ, int expPLen, jbyte* jExpP,
+ int expQLen, jbyte* jExpQ, int crtCoeffLen, jbyte* jCrtCoeff) {
+
+ unsigned char *mod, *pub, *priv, *p, *q, *expP, *expQ, *crtCoeff;
+ crypto_object_attribute_t* pKey = NULL;
+
+ pKey = calloc(8, sizeof(crypto_object_attribute_t));
+ if (pKey == NULL) {
+ return 0L;
+ }
+ mod = pub = priv = p = q = expP = expQ = crtCoeff = NULL;
+ mod = malloc(modLen);
+ pub = malloc(pubLen);
+ priv = malloc(privLen);
+ p = malloc(pLen);
+ q = malloc(qLen);
+ expP = malloc(expPLen);
+ expQ = malloc(expQLen);
+ crtCoeff = malloc(crtCoeffLen);
+ if (mod == NULL || pub == NULL || priv == NULL || p == NULL ||
+ q == NULL || expP == NULL || expQ == NULL || crtCoeff == NULL) {
+ free(pKey);
+ free(mod);
+ free(pub);
+ free(priv);
+ free(p);
+ free(q);
+ free(expP);
+ free(expQ);
+ free(crtCoeff);
+ return 0L;
+ } else {
+ memcpy(mod, jMod, modLen);
+ memcpy(pub, jPub, pubLen);
+ memcpy(priv, jPriv, privLen);
+ memcpy(p, jP, pLen);
+ memcpy(q, jQ, qLen);
+ memcpy(expP, jExpP, expPLen);
+ memcpy(expQ, jExpQ, expQLen);
+ memcpy(crtCoeff, jCrtCoeff, crtCoeffLen);
+ }
+
+ // NOTE: numOfComponents should be 8
+ pKey[0].oa_type = SUN_CKA_MODULUS;
+ pKey[0].oa_value = (char*) mod;
+ pKey[0].oa_value_len = (size_t) modLen;
+ pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
+ pKey[1].oa_value = (char*) pub;
+ pKey[1].oa_value_len = (size_t) pubLen;
+ pKey[2].oa_type = SUN_CKA_PRIVATE_EXPONENT;
+ pKey[2].oa_value = (char*) priv;
+ pKey[2].oa_value_len = (size_t) privLen;
+ pKey[3].oa_type = SUN_CKA_PRIME_1;
+ pKey[3].oa_value = (char*) p;
+ pKey[3].oa_value_len = (size_t) pLen;
+ pKey[4].oa_type = SUN_CKA_PRIME_2;
+ pKey[4].oa_value = (char*) q;
+ pKey[4].oa_value_len = (size_t) qLen;
+ pKey[5].oa_type = SUN_CKA_EXPONENT_1;
+ pKey[5].oa_value = (char*) expP;
+ pKey[5].oa_value_len = (size_t) expPLen;
+ pKey[6].oa_type = SUN_CKA_EXPONENT_2;
+ pKey[6].oa_value = (char*) expQ;
+ pKey[6].oa_value_len = (size_t) expQLen;
+ pKey[7].oa_type = SUN_CKA_COEFFICIENT;
+ pKey[7].oa_value = (char*) crtCoeff;
+ pKey[7].oa_value_len = (size_t) crtCoeffLen;
+
+ return (jlong) pKey;
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_com_oracle_security_ucrypto_NativeKey_00024RSAPrivateCrt_nativeInit
+ (JNIEnv *env, jclass jCls, jbyteArray jMod, jbyteArray jPub, jbyteArray jPriv,
+ jbyteArray jP, jbyteArray jQ, jbyteArray jExpP, jbyteArray jExpQ,
+ jbyteArray jCrtCoeff) {
+
+ int modLen, pubLen, privLen, pLen, qLen, expPLen, expQLen, crtCoeffLen;
+ jbyte *bufMod, *bufPub, *bufPriv, *bufP, *bufQ, *bufExpP, *bufExpQ, *bufCrtCoeff;
+ crypto_object_attribute_t* pKey = NULL;
+
+ bufMod = bufPub = bufPriv = bufP = bufQ = bufExpP = bufExpQ = bufCrtCoeff = NULL;
+
+ modLen = (*env)->GetArrayLength(env, jMod);
+ bufMod = getBytes(env, jMod, 0, modLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ pubLen = (*env)->GetArrayLength(env, jPub);
+ bufPub = getBytes(env, jPub, 0, pubLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ privLen = (*env)->GetArrayLength(env, jPriv);
+ bufPriv = getBytes(env, jPriv, 0, privLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ pLen = (*env)->GetArrayLength(env, jP);
+ bufP = getBytes(env, jP, 0, pLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ qLen = (*env)->GetArrayLength(env, jQ);
+ bufQ = getBytes(env, jQ, 0, qLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ expPLen = (*env)->GetArrayLength(env, jExpP);
+ bufExpP = getBytes(env, jExpP, 0, expPLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ expQLen = (*env)->GetArrayLength(env, jExpQ);
+ bufExpQ = getBytes(env, jExpQ, 0, expQLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ crtCoeffLen = (*env)->GetArrayLength(env, jCrtCoeff);
+ bufCrtCoeff = getBytes(env, jCrtCoeff, 0, crtCoeffLen);
+ if ((*env)->ExceptionCheck(env)) goto cleanup;
+
+ // proceed if no error; otherwise free allocated memory
+ pKey = calloc(8, sizeof(crypto_object_attribute_t));
+ if (pKey == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ goto cleanup;
+ }
+
+ // NOTE: numOfComponents should be 8
+ pKey[0].oa_type = SUN_CKA_MODULUS;
+ pKey[0].oa_value = (char*) bufMod;
+ pKey[0].oa_value_len = (size_t) modLen;
+ pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
+ pKey[1].oa_value = (char*) bufPub;
+ pKey[1].oa_value_len = (size_t) pubLen;
+ pKey[2].oa_type = SUN_CKA_PRIVATE_EXPONENT;
+ pKey[2].oa_value = (char*) bufPriv;
+ pKey[2].oa_value_len = (size_t) privLen;
+ pKey[3].oa_type = SUN_CKA_PRIME_1;
+ pKey[3].oa_value = (char*) bufP;
+ pKey[3].oa_value_len = (size_t) pLen;
+ pKey[4].oa_type = SUN_CKA_PRIME_2;
+ pKey[4].oa_value = (char*) bufQ;
+ pKey[4].oa_value_len = (size_t) qLen;
+ pKey[5].oa_type = SUN_CKA_EXPONENT_1;
+ pKey[5].oa_value = (char*) bufExpP;
+ pKey[5].oa_value_len = (size_t) expPLen;
+ pKey[6].oa_type = SUN_CKA_EXPONENT_2;
+ pKey[6].oa_value = (char*) bufExpQ;
+ pKey[6].oa_value_len = (size_t) expQLen;
+ pKey[7].oa_type = SUN_CKA_COEFFICIENT;
+ pKey[7].oa_value = (char*) bufCrtCoeff;
+ pKey[7].oa_value_len = (size_t) crtCoeffLen;
+ return (jlong) pKey;
+
+cleanup:
+ free(bufMod);
+ free(bufPub);
+ free(bufPriv);
+ free(bufP);
+ free(bufQ);
+ free(bufExpP);
+ free(bufExpQ);
+ free(bufCrtCoeff);
+
+ return 0L;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeKey_RSAPublic
+ * Method: nativeInit
+ * Signature: ([B[B)J
+ */
+
+jlong JavaCritical_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit
+(int modLen, jbyte* jMod, int pubLen, jbyte* jPub) {
+ unsigned char *mod, *pub;
+ crypto_object_attribute_t* pKey = NULL;
+
+ pKey = calloc(2, sizeof(crypto_object_attribute_t));
+ if (pKey == NULL) {
+ return 0L;
+ }
+ mod = pub = NULL;
+ mod = malloc(modLen);
+ pub = malloc(pubLen);
+ if (mod == NULL || pub == NULL) {
+ free(pKey);
+ free(mod);
+ free(pub);
+ return 0L;
+ } else {
+ memcpy(mod, jMod, modLen);
+ memcpy(pub, jPub, pubLen);
+ }
+
+ if (DEBUG) {
+ printf("RSAPublicKey Init: keyValue=%ld, keyLen=2\n", pKey);
+ printBytes("RSA PublicKey mod: ", (unsigned char*) mod, modLen);
+ printBytes("RSA PublicKey pubExp: ", (unsigned char*) pub, pubLen);
+ }
+
+ pKey[0].oa_type = SUN_CKA_MODULUS;
+ pKey[0].oa_value = (char*) mod;
+ pKey[0].oa_value_len = (size_t) modLen;
+ pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
+ pKey[1].oa_value = (char*) pub;
+ pKey[1].oa_value_len = (size_t) pubLen;
+
+ return (jlong) pKey;
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_oracle_security_ucrypto_NativeKey_00024RSAPublic_nativeInit
+(JNIEnv *env, jclass jCls, jbyteArray jMod, jbyteArray jPub) {
+ int modLen, pubLen;
+ jbyte *bufMod, *bufPub;
+ crypto_object_attribute_t* pKey = NULL;
+
+ bufMod = bufPub = NULL;
+
+ modLen = (*env)->GetArrayLength(env, jMod);
+ bufMod = getBytes(env, jMod, 0, modLen);
+ if ((*env)->ExceptionCheck(env)) {
+ return 0L;
+ }
+
+ pubLen = (*env)->GetArrayLength(env, jPub);
+ bufPub = getBytes(env, jPub, 0, pubLen);
+ if ((*env)->ExceptionCheck(env)) {
+ free(bufMod);
+ return 0L;
+ }
+
+ // proceed if no error; otherwise free allocated memory
+ pKey = calloc(2, sizeof(crypto_object_attribute_t));
+ if (pKey != NULL) {
+ // NOTE: numOfComponents should be 2
+ pKey[0].oa_type = SUN_CKA_MODULUS;
+ pKey[0].oa_value = (char*) bufMod;
+ pKey[0].oa_value_len = (size_t) modLen;
+ pKey[1].oa_type = SUN_CKA_PUBLIC_EXPONENT;
+ pKey[1].oa_value = (char*) bufPub;
+ pKey[1].oa_value_len = (size_t) pubLen;
+ return (jlong) pKey;
+ } else {
+ free(bufMod);
+ free(bufPub);
+ throwOutOfMemoryError(env, NULL);
+ return 0L;
+ }
+}
+
+////////////////////////
+// NativeRSASignature
+////////////////////////
+
+int
+SignatureInit(crypto_ctx_t *context, jint mechVal, jboolean sign,
+ uchar_t *pKey, size_t keyLength) {
+ ucrypto_mech_t mech;
+ int rv = 0;
+
+ mech = (ucrypto_mech_t) mechVal;
+
+ if (sign) {
+ rv = (*ftab->ucryptoSignInit)(context, mech, pKey, keyLength,
+ NULL, 0);
+ } else {
+ rv = (*ftab->ucryptoVerifyInit)(context, mech, pKey, keyLength,
+ NULL, 0);
+ }
+ if (DEBUG) {
+ printf("SignatureInit: context=%ld, mech=%d, sign=%d, keyValue=%ld, keyLength=%d\n",
+ context, mech, sign, pKey, keyLength);
+ printf("SignatureInit, ret => 0x%x\n", rv);
+ }
+ return rv;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeRSASignature
+ * Method: nativeInit
+ * Signature: (IZJI[B)J
+ */
+jlong JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeInit
+(jint mech, jboolean sign, jlong jKey, jint keyLength) {
+ crypto_ctx_t *context;
+ int rv;
+ uchar_t *pKey;
+
+ context = malloc(sizeof(crypto_ctx_t));
+ if (context != NULL) {
+ pKey = (uchar_t *) jKey;
+ rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
+ if (rv) {
+ free(context);
+ return 0L;
+ }
+ }
+ return (jlong)context;
+}
+
+JNIEXPORT jlong JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeInit
+(JNIEnv *env, jclass jCls, jint mech, jboolean sign, jlong jKey, jint keyLength) {
+ crypto_ctx_t *context;
+ int rv = 0;
+ uchar_t *pKey;
+
+ context = malloc(sizeof(crypto_ctx_t));
+ if (context == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return 0L;
+ }
+
+ pKey = (uchar_t *) jKey;
+ rv = SignatureInit(context, mech, sign, pKey, (size_t)keyLength);
+ if (rv) {
+ free(context);
+ throwUCExceptionUsingRV(env, rv);
+ return 0L;
+ }
+
+ return (jlong)context;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeRSASignature
+ * Method: nativeUpdate
+ * Signature: (JZ[BII)I
+ */
+jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
+(jlong pCtxt, jboolean sign, int notUsed, jbyte* jIn, jint jInOfs, jint jInLen) {
+ crypto_ctx_t *context;
+ int rv = 0;
+
+ context = (crypto_ctx_t *) pCtxt;
+ if (DEBUG) {
+ printf("Signature update: context=%ld, sign=%d, jIn=%ld, jInOfs=%d, jInLen=%d\n",
+ context, sign, jIn, jInOfs, jInLen);
+ }
+ if (sign) {
+ rv = (*ftab->ucryptoSignUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
+ } else {
+ rv = (*ftab->ucryptoVerifyUpdate)(context, (uchar_t *) (jIn + jInOfs), (size_t) jInLen);
+ }
+ if (DEBUG) printf("Signature update, ret => 0x%x\n", rv);
+ if (rv) {
+ free(context);
+ return -rv; // use negative value to indicate error!
+ }
+
+ return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
+(JNIEnv *env, jclass jCls, jlong pCtxt, jboolean sign, jbyteArray jIn, jint inOfs, jint inLen) {
+ int rv = 0;
+ jbyte* bufIn;
+
+ bufIn = getBytes(env, jIn, inOfs, inLen);
+ if ((*env)->ExceptionCheck(env)) {
+ return -1; // use negative value to indicate error!
+ }
+
+ if (DEBUG) printBytes("Update w/ data: ", (unsigned char*)bufIn, (size_t) inLen);
+
+ rv = JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
+ (pCtxt, sign, inLen, bufIn, 0, inLen);
+
+ free(bufIn);
+ return rv;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeRSASignature
+ * Method: nativeUpdate
+ * Signature: (JZJI)I
+ */
+jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI
+(jlong pCtxt, jboolean sign, jlong inAddr, jint inLen) {
+
+ return JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
+ (pCtxt, sign, inLen, (jbyte*)inAddr, 0, inLen);
+}
+
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZJI
+(JNIEnv *env, jclass jCls, jlong pCtxt, jboolean sign, jlong inAddr, jint inLen) {
+
+ return JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeUpdate__JZ_3BII
+ (pCtxt, sign, inLen, (jbyte*)inAddr, 0, inLen);
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeRSASignature
+ * Method: nativeFinal
+ * Signature: (JZ[BII)I
+ */
+jint JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
+(jlong pCtxt, jboolean sign, int notUsed, jbyte* bufSig, jint sigOfs, jint jSigLen) {
+
+ crypto_ctx_t *context;
+ int rv = 0;
+ size_t sigLength = (size_t) jSigLen;
+
+ context = (crypto_ctx_t *) pCtxt;
+ if (DEBUG) {
+ printf("Signature final: context=%ld, sign=%d, bufSig=%ld, sigOfs=%d, sigLen=%d\n",
+ context, sign, bufSig, sigOfs, jSigLen);
+ printBytes("Before Final: SigBytes ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+ }
+ if (sign) {
+ rv = (*ftab->ucryptoSignFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
+ } else {
+ rv = (*ftab->ucryptoVerifyFinal)(context, (uchar_t *) (bufSig + sigOfs), &sigLength);
+ }
+
+ if (DEBUG) {
+ printf("Signature nativeFinal, ret => 0x%x\n", rv);
+ if (sigLength != jSigLen) {
+ printf("SIG actual output len=%d\n", sigLength);
+ }
+ if (sign) {
+ printBytes("After nativeFinal: ", (unsigned char*) (bufSig + sigOfs), jSigLen);
+ }
+ }
+
+ free(context);
+ if (rv) {
+ return -rv;
+ } else return 0;
+}
+
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
+(JNIEnv *env, jclass jCls, jlong pCtxt, jboolean sign, jbyteArray jSig, jint jSigOfs, jint jSigLen) {
+ int rv = 0;
+ jbyte* bufSig = NULL;
+
+ if (jSigLen != 0) {
+ bufSig = calloc(jSigLen, sizeof(char));
+ if (bufSig == NULL) {
+ throwOutOfMemoryError(env, NULL);
+ return 0;
+ }
+ if (!sign) {
+ // need to copy over the to-be-verified signature bytes
+ (*env)->GetByteArrayRegion(env, jSig, jSigOfs, jSigLen, (jbyte *)bufSig);
+ }
+ }
+
+ if (!(*env)->ExceptionCheck(env)) {
+ // Frees context + converts rv to negative if error occurred
+ rv = JavaCritical_com_oracle_security_ucrypto_NativeRSASignature_nativeFinal
+ (pCtxt, sign, jSigLen, bufSig, 0, jSigLen);
+
+ if (rv == 0 && sign) {
+ // need to copy the generated signature bytes to the java bytearray
+ (*env)->SetByteArrayRegion(env, jSig, jSigOfs, jSigLen, (jbyte *)bufSig);
+ }
+ } else {
+ // set rv to negative to indicate error
+ rv = -1;
+ }
+
+ free(bufSig);
+
+ return rv;
+}
+
+/*
+ * Class: com_oracle_security_ucrypto_NativeRSACipher
+ * Method: nativeAtomic
+ * Signature: (IZJI[BI[BII)I
+ */
+jint JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
+ (jint mech, jboolean encrypt, jlong keyValue, jint keyLength,
+ int notUsed1, jbyte* bufIn, jint jInLen,
+ int notUsed2, jbyte* bufOut, jint jOutOfs, jint jOutLen) {
+
+ uchar_t *pKey;
+ crypto_object_attribute_t* pKey2;
+ int rv = 0;
+ size_t outLength = (size_t) jOutLen;
+
+ pKey = (uchar_t *) keyValue;
+ if (DEBUG) {
+ printf("Cipher nativeAtomic: mech=%d, encrypt=%d, pKey=%ld, keyLength=%d\n",
+ mech, encrypt, pKey, keyLength);
+ printBytes("Before nativeAtomic: in: ", (unsigned char*) bufIn, jInLen);
+ printBytes("Before nativeAtomic: out: ", (unsigned char*) (bufOut + jOutOfs), jOutLen);
+ }
+
+ if (encrypt) {
+ rv = (*ftab->ucryptoEncrypt)((ucrypto_mech_t)mech, pKey, (size_t)keyLength,
+ NULL, 0, (uchar_t *)bufIn, (size_t)jInLen,
+ (uchar_t *)(bufOut + jOutOfs), &outLength);
+ } else {
+ rv = (*ftab->ucryptoDecrypt)((ucrypto_mech_t)mech, pKey, (size_t)keyLength,
+ NULL, 0, (uchar_t *)bufIn, (size_t)jInLen,
+ (uchar_t *)(bufOut + jOutOfs), &outLength);
+ }
+ if (DEBUG) {
+ printf("Cipher nativeAtomic, ret => 0x%x\n", rv);
+ if (outLength != jOutLen) {
+ printf("CIP actual output len=%d\n", outLength);
+ }
+ printBytes("After nativeAtomic: ", (unsigned char*) (bufOut + jOutOfs), outLength);
+ }
+
+ if (rv) {
+ return -rv;
+ } else return outLength;
+}
+
+JNIEXPORT jint JNICALL Java_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
+ (JNIEnv *env, jclass jCls, jint mech, jboolean encrypt,
+ jlong keyValue, jint keyLength, jbyteArray jIn, jint jInLen,
+ jbyteArray jOut, jint jOutOfs, jint jOutLen) {
+ int rv = 0;
+ jbyte *bufIn = NULL;
+ jbyte *bufOut = NULL;
+
+ if (jInLen != 0) {
+ bufIn = (*env)->GetByteArrayElements(env, jIn, NULL);
+ if (bufIn == NULL) {
+ return 0;
+ }
+ }
+ bufOut = calloc(jOutLen, sizeof(jbyte));
+ if (bufOut == NULL) {
+ (*env)->ReleaseByteArrayElements(env, jIn, bufIn, 0);
+ throwOutOfMemoryError(env, NULL);
+ return 0;
+ }
+
+ // rv: output length or error code (if negative)
+ rv = JavaCritical_com_oracle_security_ucrypto_NativeRSACipher_nativeAtomic
+ (mech, encrypt, keyValue, keyLength, jInLen, bufIn, jInLen,
+ jOutLen, bufOut, 0, jOutLen);
+
+ if (rv > 0) {
+ (*env)->SetByteArrayRegion(env, jOut, jOutOfs, rv, (jbyte *)bufOut);
+ }
+
+ if (bufIn != NULL) {
+ (*env)->ReleaseByteArrayElements(env, jIn, bufIn, 0);
+ }
+ free(bufOut);
+ return rv;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeCrypto.h Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _Included_com_oracle_security_ucrypto_NativeCrypto
+#define _Included_com_oracle_security_ucrypto_NativeCrypto
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef com_oracle_security_ucrypto_NativeDigest_MECH_MD5
+#define com_oracle_security_ucrypto_NativeDigest_MECH_MD5 1L
+#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA1
+#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA1 2L
+#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA256
+#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA256 3L
+#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA224
+#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA224 4L
+#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA384
+#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA384 5L
+#undef com_oracle_security_ucrypto_NativeDigest_MECH_SHA512
+#define com_oracle_security_ucrypto_NativeDigest_MECH_SHA512 6L
+
+#define DEBUG 0
+
+#ifdef __cplusplus
+}
+#endif
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.c Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <jni.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <link.h>
+#include "nativeFunc.h"
+
+/* standard md5/md/softcrypto method names (ordering is from mapfile) */
+static const char MD5_INIT[] = "MD5Init";
+static const char MD5_UPDATE[] = "MD5Update";
+static const char MD5_FINAL[] = "MD5Final";
+static const char SHA1_INIT[] = "SHA1Init";
+static const char SHA1_UPDATE[] = "SHA1Update";
+static const char SHA1_FINAL[] = "SHA1Final";
+static const char SHA2_INIT[] = "SHA2Init";
+static const char SHA2_UPDATE[] = "SHA2Update";
+static const char SHA2_FINAL[] = "SHA2Final";
+static const char UCRYPTO_VERSION[] = "ucrypto_version";
+static const char UCRYPTO_GET_MECHLIST[] = "ucrypto_get_mechlist";
+static const char UCRYPTO_ENCRYPT_INIT[] = "ucrypto_encrypt_init";
+static const char UCRYPTO_ENCRYPT_UPDATE[] = "ucrypto_encrypt_update";
+static const char UCRYPTO_ENCRYPT_FINAL[] = "ucrypto_encrypt_final";
+static const char UCRYPTO_ENCRYPT[] = "ucrypto_encrypt";
+static const char UCRYPTO_DECRYPT_INIT[] = "ucrypto_decrypt_init";
+static const char UCRYPTO_DECRYPT_UPDATE[] = "ucrypto_decrypt_update";
+static const char UCRYPTO_DECRYPT_FINAL[] = "ucrypto_decrypt_final";
+static const char UCRYPTO_DECRYPT[] = "ucrypto_decrypt";
+static const char UCRYPTO_SIGN_INIT[] = "ucrypto_sign_init";
+static const char UCRYPTO_SIGN_UPDATE[] = "ucrypto_sign_update";
+static const char UCRYPTO_SIGN_FINAL[] = "ucrypto_sign_final";
+static const char UCRYPTO_VERIFY_INIT[] = "ucrypto_verify_init";
+static const char UCRYPTO_VERIFY_UPDATE[] = "ucrypto_verify_update";
+static const char UCRYPTO_VERIFY_FINAL[] = "ucrypto_verify_final";
+
+/**
+ * Initialize native T4 crypto function pointers
+ */
+jboolean* loadNative() {
+
+ jboolean* buf;
+ void *lib;
+
+ buf = malloc(2 * sizeof(jboolean));
+ buf[0] = buf[1] = JNI_FALSE;
+ ftab = (T4CRYPTO_FUNCTION_TABLE_PTR) calloc(1, sizeof(T4CRYPTO_FUNCTION_TABLE));
+ if (ftab == NULL) {
+ free(buf);
+ return NULL;
+ }
+
+ lib = dlopen("libmd.so", RTLD_NOW);
+ if (lib != NULL) {
+ ftab->md5Init = (MD5INIT_FN_PTR) dlsym(lib, MD5_INIT);
+ ftab->md5Update = (MD5UPDATE_FN_PTR) dlsym(lib, MD5_UPDATE);
+ ftab->md5Final = (MD5FINAL_FN_PTR) dlsym(lib, MD5_FINAL);
+ ftab->sha1Init = (SHA1INIT_FN_PTR) dlsym(lib, SHA1_INIT);
+ ftab->sha1Update = (SHA1UPDATE_FN_PTR) dlsym(lib, SHA1_UPDATE);
+ ftab->sha1Final = (SHA1FINAL_FN_PTR) dlsym(lib, SHA1_FINAL);
+ ftab->sha2Init = (SHA2INIT_FN_PTR) dlsym(lib, SHA2_INIT);
+ ftab->sha2Update = (SHA2UPDATE_FN_PTR) dlsym(lib, SHA2_UPDATE);
+ ftab->sha2Final = (SHA2FINAL_FN_PTR) dlsym(lib, SHA2_FINAL);
+ if (ftab->md5Init != NULL && ftab->md5Update != NULL &&
+ ftab->md5Final != NULL && ftab->sha1Init != NULL &&
+ ftab->sha1Update != NULL && ftab->sha1Final != NULL &&
+ ftab->sha2Init != NULL && ftab->sha2Update != NULL &&
+ ftab->sha2Final != NULL) {
+ buf[0] = JNI_TRUE;
+ } else {
+ dlclose(lib);
+ }
+ }
+
+ lib = dlopen("libsoftcrypto.so", RTLD_NOW);
+ if (lib != NULL) {
+ // These APIs aren't available for v0 lib on Solaris 10
+ ftab->ucryptoVersion = (UCRYPTO_VERSION_FN_PTR)
+ dlsym(lib, UCRYPTO_VERSION);
+ ftab->ucryptoGetMechList = (UCRYPTO_GET_MECHLIST_FN_PTR)
+ dlsym(lib, UCRYPTO_GET_MECHLIST);
+ //??
+ ftab->ucryptoSignInit = (UCRYPTO_SIGN_INIT_FN_PTR)
+ dlsym(lib, UCRYPTO_SIGN_INIT);
+ ftab->ucryptoSignUpdate = (UCRYPTO_SIGN_UPDATE_FN_PTR)
+ dlsym(lib, UCRYPTO_SIGN_UPDATE);
+ ftab->ucryptoSignFinal = (UCRYPTO_SIGN_FINAL_FN_PTR)
+ dlsym(lib, UCRYPTO_SIGN_FINAL);
+ ftab->ucryptoVerifyInit = (UCRYPTO_VERIFY_INIT_FN_PTR)
+ dlsym(lib, UCRYPTO_VERIFY_INIT);
+ ftab->ucryptoVerifyUpdate = (UCRYPTO_VERIFY_UPDATE_FN_PTR)
+ dlsym(lib, UCRYPTO_VERIFY_UPDATE);
+ ftab->ucryptoVerifyFinal = (UCRYPTO_VERIFY_FINAL_FN_PTR)
+ dlsym(lib, UCRYPTO_VERIFY_FINAL);
+
+ // These should be avilable for all libsoftcrypto libs
+ ftab->ucryptoEncryptInit = (UCRYPTO_ENCRYPT_INIT_FN_PTR)
+ dlsym(lib, UCRYPTO_ENCRYPT_INIT);
+ ftab->ucryptoEncryptUpdate = (UCRYPTO_ENCRYPT_UPDATE_FN_PTR)
+ dlsym(lib, UCRYPTO_ENCRYPT_UPDATE);
+ ftab->ucryptoEncryptFinal = (UCRYPTO_ENCRYPT_FINAL_FN_PTR)
+ dlsym(lib, UCRYPTO_ENCRYPT_FINAL);
+ ftab->ucryptoEncrypt = (UCRYPTO_ENCRYPT_FN_PTR)
+ dlsym(lib, UCRYPTO_ENCRYPT);
+
+ ftab->ucryptoDecryptInit = (UCRYPTO_DECRYPT_INIT_FN_PTR)
+ dlsym(lib, UCRYPTO_DECRYPT_INIT);
+ ftab->ucryptoDecryptUpdate = (UCRYPTO_DECRYPT_UPDATE_FN_PTR)
+ dlsym(lib, UCRYPTO_DECRYPT_UPDATE);
+ ftab->ucryptoDecryptFinal = (UCRYPTO_DECRYPT_FINAL_FN_PTR)
+ dlsym(lib, UCRYPTO_DECRYPT_FINAL);
+ ftab->ucryptoDecrypt = (UCRYPTO_DECRYPT_FN_PTR)
+ dlsym(lib, UCRYPTO_DECRYPT);
+
+ if (ftab->ucryptoEncryptInit != NULL &&
+ ftab->ucryptoEncryptUpdate != NULL &&
+ ftab->ucryptoEncryptFinal != NULL &&
+ ftab->ucryptoEncrypt != NULL &&
+ ftab->ucryptoDecryptInit != NULL &&
+ ftab->ucryptoDecryptUpdate != NULL &&
+ ftab->ucryptoDecryptFinal != NULL &&
+ ftab->ucryptoDecrypt != NULL) {
+ buf[1] = JNI_TRUE;
+ } else {
+ dlclose(lib);
+ }
+ }
+
+ return buf;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/nativeFunc.h Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SPARCT4_NATIVE_FUNC_H
+#define SPARCT4_NATIVE_FUNC_H
+#include <md5.h>
+#include <sha1.h>
+#include <sha2.h>
+#include <libsoftcrypto.h>
+
+jboolean* loadNative();
+
+/* function pointer definitions */
+
+typedef void (*MD5INIT_FN_PTR)(MD5_CTX *context);
+
+typedef void (*MD5UPDATE_FN_PTR)
+ (MD5_CTX *context, unsigned char *input,
+ unsigned int inlen);
+
+typedef void (*MD5FINAL_FN_PTR)
+ (unsigned char *output, MD5_CTX *context);
+
+typedef void (*SHA1INIT_FN_PTR)(SHA1_CTX *context);
+
+typedef void (*SHA1UPDATE_FN_PTR)
+ (SHA1_CTX *context, unsigned char *input,
+ unsigned int inlen);
+
+typedef void (*SHA1FINAL_FN_PTR)
+ (unsigned char *output, SHA1_CTX *context);
+
+typedef void (*SHA2INIT_FN_PTR)(uint64_t mech, SHA2_CTX *context);
+
+typedef void (*SHA2UPDATE_FN_PTR)
+ (SHA2_CTX *context, unsigned char *input,
+ unsigned int inlen);
+
+typedef void (*SHA2FINAL_FN_PTR)
+ (unsigned char *output, SHA2_CTX *context);
+
+typedef int (*UCRYPTO_VERSION_FN_PTR)();
+
+typedef int (*UCRYPTO_GET_MECHLIST_FN_PTR)(char *str);
+
+typedef int (*UCRYPTO_ENCRYPT_INIT_FN_PTR)
+ (crypto_ctx_t *context, ucrypto_mech_t mech_type,
+ uchar_t *key_str, size_t key_len,
+ void *iv, size_t iv_len);
+
+typedef int (*UCRYPTO_ENCRYPT_UPDATE_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *in,
+ size_t in_len, uchar_t *out, size_t *out_len);
+
+typedef int (*UCRYPTO_ENCRYPT_FINAL_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *out,
+ size_t *out_len);
+
+typedef int (*UCRYPTO_ENCRYPT_FN_PTR)
+ (ucrypto_mech_t mech_type, uchar_t *key_str,
+ size_t key_len, void *iv, size_t iv_len, uchar_t *in,
+ size_t in_len, uchar_t *out, size_t *out_len);
+
+typedef int (*UCRYPTO_DECRYPT_INIT_FN_PTR)
+ (crypto_ctx_t *context,
+ ucrypto_mech_t mech_type, uchar_t *key_str, size_t key_len,
+ void *iv, size_t iv_len);
+
+typedef int (*UCRYPTO_DECRYPT_UPDATE_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *in,
+ size_t in_len, uchar_t *out, size_t *out_len);
+
+typedef int (*UCRYPTO_DECRYPT_FINAL_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *out,
+ size_t *out_len);
+
+typedef int (*UCRYPTO_DECRYPT_FN_PTR)
+ (ucrypto_mech_t mech_type, uchar_t *key_str,
+ size_t key_len, void *iv, size_t iv_len, uchar_t *in,
+ size_t in_len, uchar_t *out, size_t *out_len);
+
+typedef int (*UCRYPTO_SIGN_INIT_FN_PTR)
+ (crypto_ctx_t *context, ucrypto_mech_t mech_type,
+ uchar_t *key_str, size_t key_len,
+ void *iv, size_t iv_len);
+
+typedef int (*UCRYPTO_SIGN_UPDATE_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
+
+typedef int (*UCRYPTO_SIGN_FINAL_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
+
+typedef int (*UCRYPTO_VERIFY_INIT_FN_PTR)
+ (crypto_ctx_t *context, ucrypto_mech_t mech_type,
+ uchar_t *key_str, size_t key_len,
+ void *iv, size_t iv_len);
+
+typedef int (*UCRYPTO_VERIFY_UPDATE_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *data_str, size_t data_len);
+
+typedef int (*UCRYPTO_VERIFY_FINAL_FN_PTR)
+ (crypto_ctx_t *context, uchar_t *sig_str, size_t *sig_len);
+
+
+
+/* dynamically resolved functions from libmd, and libsoftcrypto
+ libraries */
+typedef struct T4CRYPTO_FUNCTION_TABLE {
+ MD5INIT_FN_PTR md5Init;
+ MD5UPDATE_FN_PTR md5Update;
+ MD5FINAL_FN_PTR md5Final;
+ SHA1INIT_FN_PTR sha1Init;
+ SHA1UPDATE_FN_PTR sha1Update;
+ SHA1FINAL_FN_PTR sha1Final;
+ SHA2INIT_FN_PTR sha2Init;
+ SHA2UPDATE_FN_PTR sha2Update;
+ SHA2FINAL_FN_PTR sha2Final;
+ UCRYPTO_VERSION_FN_PTR ucryptoVersion;
+ UCRYPTO_GET_MECHLIST_FN_PTR ucryptoGetMechList;
+ UCRYPTO_ENCRYPT_INIT_FN_PTR ucryptoEncryptInit;
+ UCRYPTO_ENCRYPT_UPDATE_FN_PTR ucryptoEncryptUpdate;
+ UCRYPTO_ENCRYPT_FINAL_FN_PTR ucryptoEncryptFinal;
+ UCRYPTO_ENCRYPT_FN_PTR ucryptoEncrypt;
+ UCRYPTO_DECRYPT_INIT_FN_PTR ucryptoDecryptInit;
+ UCRYPTO_DECRYPT_UPDATE_FN_PTR ucryptoDecryptUpdate;
+ UCRYPTO_DECRYPT_FINAL_FN_PTR ucryptoDecryptFinal;
+ UCRYPTO_DECRYPT_FN_PTR ucryptoDecrypt;
+ UCRYPTO_SIGN_INIT_FN_PTR ucryptoSignInit;
+ UCRYPTO_SIGN_UPDATE_FN_PTR ucryptoSignUpdate;
+ UCRYPTO_SIGN_FINAL_FN_PTR ucryptoSignFinal;
+ UCRYPTO_VERIFY_INIT_FN_PTR ucryptoVerifyInit;
+ UCRYPTO_VERIFY_UPDATE_FN_PTR ucryptoVerifyUpdate;
+ UCRYPTO_VERIFY_FINAL_FN_PTR ucryptoVerifyFinal;
+} T4CRYPTO_FUNCTION_TABLE;
+
+typedef T4CRYPTO_FUNCTION_TABLE *T4CRYPTO_FUNCTION_TABLE_PTR;
+
+/* global function table */
+T4CRYPTO_FUNCTION_TABLE_PTR ftab;
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/sys_old/crypto/common.h Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _SYS_CRYPTO_COMMON_H
+#define _SYS_CRYPTO_COMMON_H
+
+/*
+ * Header file for the common data structures of the cryptographic framework
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/stream.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+
+/* Convenience defines/macros */
+
+#define CRYPTO_ARG_INPLACE(input, output) \
+ if ((output) == NULL) \
+ (output) = (input);
+
+#ifdef _KERNEL
+
+#include <sys/kmem.h>
+#define CRYPTO_KMFLAG(x) crypto_kmflag((x))
+#define CRYPTO_ALLOC(sz, kmflag) kmem_alloc((sz), (kmflag))
+#define CRYPTO_ZALLOC(sz, kmflag) kmem_zalloc((sz), (kmflag))
+#define CRYPTO_FREE(ptr, sz) kmem_free((ptr), (sz))
+#define CRYPTO_ZFREE(ptr, sz) if (ptr != NULL) { \
+ bzero((ptr), (sz)), \
+ kmem_free((ptr), (sz)); \
+ }
+
+#else /* _KERNEL */
+
+#include <malloc.h>
+#define CRYPTO_KMFLAG(x) (0)
+#define CRYPTO_ALLOC(sz, kmflag) malloc((sz))
+#define CRYPTO_ZALLOC(sz, kmflag) calloc(1, (sz))
+#define CRYPTO_FREE(ptr, sz) free((ptr))
+#define CRYPTO_ZFREE(ptr, sz) if (ptr != NULL) { \
+ bzero((ptr), (sz)), \
+ free((ptr)); \
+ }
+
+#endif /* _KERNEL */
+
+/* Cryptographic Mechanisms */
+
+#define CRYPTO_MAX_MECH_NAME 32
+typedef char crypto_mech_name_t[CRYPTO_MAX_MECH_NAME];
+
+typedef uint64_t crypto_mech_type_t;
+
+typedef struct crypto_mechanism {
+ crypto_mech_type_t cm_type; /* mechanism type */
+ caddr_t cm_param; /* mech. parameter */
+ size_t cm_param_len; /* mech. parameter len */
+} crypto_mechanism_t;
+
+#ifdef _SYSCALL32
+
+typedef struct crypto_mechanism32 {
+ crypto_mech_type_t cm_type; /* mechanism type */
+ caddr32_t cm_param; /* mech. parameter */
+ size32_t cm_param_len; /* mech. parameter len */
+} crypto_mechanism32_t;
+
+#endif /* _SYSCALL32 */
+
+#ifdef _KERNEL
+/* CK_AES_CTR_PARAMS provides parameters to the CKM_AES_CTR mechanism */
+typedef struct CK_AES_CTR_PARAMS {
+ ulong_t ulCounterBits;
+ uint8_t cb[16];
+} CK_AES_CTR_PARAMS;
+#endif
+
+/* CK_AES_CCM_PARAMS provides parameters to the CKM_AES_CCM mechanism */
+typedef struct CK_AES_CCM_PARAMS {
+ ulong_t ulMACSize;
+ ulong_t ulNonceSize;
+ ulong_t ulAuthDataSize;
+ ulong_t ulDataSize; /* used for plaintext or ciphertext */
+ uchar_t *nonce;
+ uchar_t *authData;
+} CK_AES_CCM_PARAMS;
+
+/* CK_AES_GCM_PARAMS provides parameters to the CKM_AES_GCM mechanism */
+typedef struct CK_AES_GCM_PARAMS {
+ uchar_t *pIv;
+ ulong_t ulIvLen;
+ ulong_t ulIvBits;
+ uchar_t *pAAD;
+ ulong_t ulAADLen;
+ ulong_t ulTagBits;
+} CK_AES_GCM_PARAMS;
+
+/* CK_AES_GMAC_PARAMS provides parameters to the CKM_AES_GMAC mechanism */
+typedef struct CK_AES_GMAC_PARAMS {
+ uchar_t *pIv;
+ uchar_t *pAAD;
+ ulong_t ulAADLen;
+} CK_AES_GMAC_PARAMS;
+
+#ifdef _KERNEL
+/*
+ * CK_ECDH1_DERIVE_PARAMS provides the parameters to the
+ * CKM_ECDH1_KEY_DERIVE mechanism
+ */
+typedef struct CK_ECDH1_DERIVE_PARAMS {
+ ulong_t kdf;
+ ulong_t ulSharedDataLen;
+ uchar_t *pSharedData;
+ ulong_t ulPublicDataLen;
+ uchar_t *pPublicData;
+} CK_ECDH1_DERIVE_PARAMS;
+#endif
+
+#ifdef _KERNEL
+#ifdef _SYSCALL32
+
+/* needed for 32-bit applications running on 64-bit kernels */
+typedef struct CK_AES_CTR_PARAMS32 {
+ uint32_t ulCounterBits;
+ uint8_t cb[16];
+} CK_AES_CTR_PARAMS32;
+
+/* needed for 32-bit applications running on 64-bit kernels */
+typedef struct CK_AES_CCM_PARAMS32 {
+ uint32_t ulMACSize;
+ uint32_t ulNonceSize;
+ uint32_t ulAuthDataSize;
+ uint32_t ulDataSize;
+ caddr32_t nonce;
+ caddr32_t authData;
+} CK_AES_CCM_PARAMS32;
+
+/* needed for 32-bit applications running on 64-bit kernels */
+typedef struct CK_AES_GCM_PARAMS32 {
+ caddr32_t pIv;
+ uint32_t ulIvLen;
+ uint32_t ulIvBits;
+ caddr32_t pAAD;
+ uint32_t ulAADLen;
+ uint32_t ulTagBits;
+} CK_AES_GCM_PARAMS32;
+
+/* needed for 32-bit applications running on 64-bit kernels */
+typedef struct CK_AES_GMAC_PARAMS32 {
+ caddr32_t pIv;
+ caddr32_t pAAD;
+ uint32_t ulAADLen;
+} CK_AES_GMAC_PARAMS32;
+
+typedef struct CK_ECDH1_DERIVE_PARAMS32 {
+ uint32_t kdf;
+ uint32_t ulSharedDataLen;
+ caddr32_t pSharedData;
+ uint32_t ulPublicDataLen;
+ caddr32_t pPublicData;
+} CK_ECDH1_DERIVE_PARAMS32;
+
+#endif /* _SYSCALL32 */
+#endif /* _KERNEL */
+
+/*
+ * The measurement unit bit flag for a mechanism's minimum or maximum key size.
+ * The unit are mechanism dependent. It can be in bits or in bytes.
+ */
+typedef uint32_t crypto_keysize_unit_t;
+
+/*
+ * The following bit flags are valid in cm_mech_flags field in
+ * the crypto_mech_info_t structure of the SPI.
+ *
+ * Only the first two bit flags are valid in mi_keysize_unit
+ * field in the crypto_mechanism_info_t structure of the API.
+ */
+#define CRYPTO_KEYSIZE_UNIT_IN_BITS 0x00000001
+#define CRYPTO_KEYSIZE_UNIT_IN_BYTES 0x00000002
+#define CRYPTO_CAN_SHARE_OPSTATE 0x00000004 /* supports sharing */
+
+
+/* Mechanisms supported out-of-the-box */
+#define SUN_CKM_MD4 "CKM_MD4"
+#define SUN_CKM_MD5 "CKM_MD5"
+#define SUN_CKM_MD5_HMAC "CKM_MD5_HMAC"
+#define SUN_CKM_MD5_HMAC_GENERAL "CKM_MD5_HMAC_GENERAL"
+#define SUN_CKM_SHA1 "CKM_SHA_1"
+#define SUN_CKM_SHA1_HMAC "CKM_SHA_1_HMAC"
+#define SUN_CKM_SHA1_HMAC_GENERAL "CKM_SHA_1_HMAC_GENERAL"
+#define SUN_CKM_SHA256 "CKM_SHA256"
+#define SUN_CKM_SHA256_HMAC "CKM_SHA256_HMAC"
+#define SUN_CKM_SHA256_HMAC_GENERAL "CKM_SHA256_HMAC_GENERAL"
+#define SUN_CKM_SHA384 "CKM_SHA384"
+#define SUN_CKM_SHA384_HMAC "CKM_SHA384_HMAC"
+#define SUN_CKM_SHA384_HMAC_GENERAL "CKM_SHA384_HMAC_GENERAL"
+#define SUN_CKM_SHA512 "CKM_SHA512"
+#define SUN_CKM_SHA512_HMAC "CKM_SHA512_HMAC"
+#define SUN_CKM_SHA512_HMAC_GENERAL "CKM_SHA512_HMAC_GENERAL"
+#define SUN_CKM_DES_CBC "CKM_DES_CBC"
+#define SUN_CKM_DES3_CBC "CKM_DES3_CBC"
+#define SUN_CKM_DES_ECB "CKM_DES_ECB"
+#define SUN_CKM_DES3_ECB "CKM_DES3_ECB"
+#define SUN_CKM_BLOWFISH_CBC "CKM_BLOWFISH_CBC"
+#define SUN_CKM_BLOWFISH_ECB "CKM_BLOWFISH_ECB"
+#define SUN_CKM_AES_CBC "CKM_AES_CBC"
+#define SUN_CKM_AES_ECB "CKM_AES_ECB"
+#define SUN_CKM_AES_CTR "CKM_AES_CTR"
+#define SUN_CKM_AES_CCM "CKM_AES_CCM"
+#define SUN_CKM_AES_GCM "CKM_AES_GCM"
+#define SUN_CKM_AES_GMAC "CKM_AES_GMAC"
+#define SUN_CKM_AES_CFB128 "CKM_AES_CFB128"
+#define SUN_CKM_RC4 "CKM_RC4"
+#define SUN_CKM_RSA_PKCS "CKM_RSA_PKCS"
+#define SUN_CKM_RSA_X_509 "CKM_RSA_X_509"
+#define SUN_CKM_MD5_RSA_PKCS "CKM_MD5_RSA_PKCS"
+#define SUN_CKM_SHA1_RSA_PKCS "CKM_SHA1_RSA_PKCS"
+#define SUN_CKM_SHA256_RSA_PKCS "CKM_SHA256_RSA_PKCS"
+#define SUN_CKM_SHA384_RSA_PKCS "CKM_SHA384_RSA_PKCS"
+#define SUN_CKM_SHA512_RSA_PKCS "CKM_SHA512_RSA_PKCS"
+#define SUN_CKM_EC_KEY_PAIR_GEN "CKM_EC_KEY_PAIR_GEN"
+#define SUN_CKM_ECDH1_DERIVE "CKM_ECDH1_DERIVE"
+#define SUN_CKM_ECDSA_SHA1 "CKM_ECDSA_SHA1"
+#define SUN_CKM_ECDSA "CKM_ECDSA"
+
+/* Shared operation context format for CKM_RC4 */
+typedef struct {
+#if defined(__amd64)
+ uint32_t i, j;
+ uint32_t arr[256];
+ uint32_t flag;
+#else
+ uchar_t arr[256];
+ uchar_t i, j;
+#endif /* __amd64 */
+ uint64_t pad; /* For 64-bit alignment */
+} arcfour_state_t;
+
+/* Data arguments of cryptographic operations */
+
+typedef enum crypto_data_format {
+ CRYPTO_DATA_RAW = 1,
+ CRYPTO_DATA_UIO,
+ CRYPTO_DATA_MBLK
+} crypto_data_format_t;
+
+typedef struct crypto_data {
+ crypto_data_format_t cd_format; /* Format identifier */
+ off_t cd_offset; /* Offset from the beginning */
+ size_t cd_length; /* # of bytes in use */
+ caddr_t cd_miscdata; /* ancillary data */
+ union {
+ /* Raw format */
+ iovec_t cdu_raw; /* Pointer and length */
+
+ /* uio scatter-gather format */
+ uio_t *cdu_uio;
+
+ /* mblk scatter-gather format */
+ mblk_t *cdu_mp; /* The mblk chain */
+
+ } cdu; /* Crypto Data Union */
+} crypto_data_t;
+
+#define cd_raw cdu.cdu_raw
+#define cd_uio cdu.cdu_uio
+#define cd_mp cdu.cdu_mp
+
+#define CRYPTO_SET_RAW_DATA(var, str, len) \
+ (var).cd_format = CRYPTO_DATA_RAW; \
+ (var).cd_offset = 0; \
+ (var).cd_length = (len); \
+ (var).cd_miscdata = NULL; \
+ (var).cd_raw.iov_base = (caddr_t)(str); \
+ (var).cd_raw.iov_len = (len);
+
+#define CRYPTO_DATA_IS_USERSPACE(buf) \
+ ((buf->cd_format == CRYPTO_DATA_UIO && \
+ buf->cd_uio->uio_segflg == UIO_USERSPACE))
+
+typedef struct crypto_dual_data {
+ crypto_data_t dd_data; /* The data */
+ off_t dd_offset2; /* Used by dual operation */
+ size_t dd_len2; /* # of bytes to take */
+} crypto_dual_data_t;
+
+#define dd_format dd_data.cd_format
+#define dd_offset1 dd_data.cd_offset
+#define dd_len1 dd_data.cd_length
+#define dd_miscdata dd_data.cd_miscdata
+#define dd_raw dd_data.cd_raw
+#define dd_uio dd_data.cd_uio
+#define dd_mp dd_data.cd_mp
+
+/* The keys, and their contents */
+
+typedef enum {
+ CRYPTO_KEY_RAW = 1, /* ck_data is a cleartext key */
+ CRYPTO_KEY_REFERENCE, /* ck_obj_id is an opaque reference */
+ CRYPTO_KEY_ATTR_LIST /* ck_attrs is a list of object attributes */
+} crypto_key_format_t;
+
+typedef uint64_t crypto_attr_type_t;
+
+/* Attribute types to use for passing a RSA public key or a private key. */
+#define SUN_CKA_MODULUS 0x00000120
+#define SUN_CKA_MODULUS_BITS 0x00000121
+#define SUN_CKA_PUBLIC_EXPONENT 0x00000122
+#define SUN_CKA_PRIVATE_EXPONENT 0x00000123
+#define SUN_CKA_PRIME_1 0x00000124
+#define SUN_CKA_PRIME_2 0x00000125
+#define SUN_CKA_EXPONENT_1 0x00000126
+#define SUN_CKA_EXPONENT_2 0x00000127
+#define SUN_CKA_COEFFICIENT 0x00000128
+#define SUN_CKA_PRIME 0x00000130
+#define SUN_CKA_SUBPRIME 0x00000131
+#define SUN_CKA_BASE 0x00000132
+
+#define CKK_EC 0x00000003
+#define CKK_GENERIC_SECRET 0x00000010
+#define CKK_RC4 0x00000012
+#define CKK_AES 0x0000001F
+#define CKK_DES 0x00000013
+#define CKK_DES2 0x00000014
+#define CKK_DES3 0x00000015
+
+#define CKO_PUBLIC_KEY 0x00000002
+#define CKO_PRIVATE_KEY 0x00000003
+#define CKA_CLASS 0x00000000
+#define CKA_VALUE 0x00000011
+#define CKA_KEY_TYPE 0x00000100
+#define CKA_VALUE_LEN 0x00000161
+#define CKA_EC_PARAMS 0x00000180
+#define CKA_EC_POINT 0x00000181
+
+typedef uint32_t crypto_object_id_t;
+
+typedef struct crypto_object_attribute {
+ crypto_attr_type_t oa_type; /* attribute type */
+ caddr_t oa_value; /* attribute value */
+ ssize_t oa_value_len; /* length of attribute value */
+} crypto_object_attribute_t;
+
+typedef struct crypto_key {
+ crypto_key_format_t ck_format; /* format identifier */
+ union {
+ /* for CRYPTO_KEY_RAW ck_format */
+ struct {
+ uint_t cku_v_length; /* # of bits in ck_data */
+ void *cku_v_data; /* ptr to key value */
+ } cku_key_value;
+
+ /* for CRYPTO_KEY_REFERENCE ck_format */
+ crypto_object_id_t cku_key_id; /* reference to object key */
+
+ /* for CRYPTO_KEY_ATTR_LIST ck_format */
+ struct {
+ uint_t cku_a_count; /* number of attributes */
+ crypto_object_attribute_t *cku_a_oattr;
+ } cku_key_attrs;
+ } cku_data; /* Crypto Key union */
+} crypto_key_t;
+
+#ifdef _SYSCALL32
+
+typedef struct crypto_object_attribute32 {
+ uint64_t oa_type; /* attribute type */
+ caddr32_t oa_value; /* attribute value */
+ ssize32_t oa_value_len; /* length of attribute value */
+} crypto_object_attribute32_t;
+
+typedef struct crypto_key32 {
+ crypto_key_format_t ck_format; /* format identifier */
+ union {
+ /* for CRYPTO_KEY_RAW ck_format */
+ struct {
+ uint32_t cku_v_length; /* # of bytes in ck_data */
+ caddr32_t cku_v_data; /* ptr to key value */
+ } cku_key_value;
+
+ /* for CRYPTO_KEY_REFERENCE ck_format */
+ crypto_object_id_t cku_key_id; /* reference to object key */
+
+ /* for CRYPTO_KEY_ATTR_LIST ck_format */
+ struct {
+ uint32_t cku_a_count; /* number of attributes */
+ caddr32_t cku_a_oattr;
+ } cku_key_attrs;
+ } cku_data; /* Crypto Key union */
+} crypto_key32_t;
+
+#endif /* _SYSCALL32 */
+
+#define ck_data cku_data.cku_key_value.cku_v_data
+#define ck_length cku_data.cku_key_value.cku_v_length
+#define ck_obj_id cku_data.cku_key_id
+#define ck_count cku_data.cku_key_attrs.cku_a_count
+#define ck_attrs cku_data.cku_key_attrs.cku_a_oattr
+
+/*
+ * Raw key lengths are expressed in number of bits.
+ * The following macro returns the minimum number of
+ * bytes that can contain the specified number of bits.
+ * Round up without overflowing the integer type.
+ */
+#define CRYPTO_BITS2BYTES(n) ((n) == 0 ? 0 : (((n) - 1) >> 3) + 1)
+#define CRYPTO_BYTES2BITS(n) ((n) << 3)
+
+/* Providers */
+
+typedef enum {
+ CRYPTO_HW_PROVIDER = 0,
+ CRYPTO_SW_PROVIDER,
+ CRYPTO_LOGICAL_PROVIDER
+} crypto_provider_type_t;
+
+typedef uint32_t crypto_provider_id_t;
+#define KCF_PROVID_INVALID ((uint32_t)-1)
+
+typedef struct crypto_provider_entry {
+ crypto_provider_id_t pe_provider_id;
+ uint_t pe_mechanism_count;
+} crypto_provider_entry_t;
+
+typedef struct crypto_dev_list_entry {
+ char le_dev_name[MAXNAMELEN];
+ uint_t le_dev_instance;
+ uint_t le_mechanism_count;
+} crypto_dev_list_entry_t;
+
+/* User type for authentication ioctls and SPI entry points */
+
+typedef enum crypto_user_type {
+ CRYPTO_SO = 0,
+ CRYPTO_USER
+} crypto_user_type_t;
+
+/* Version for provider management ioctls and SPI entry points */
+
+typedef struct crypto_version {
+ uchar_t cv_major;
+ uchar_t cv_minor;
+} crypto_version_t;
+
+/* session data structure opaque to the consumer */
+typedef void *crypto_session_t;
+
+/* provider data structure opaque to the consumer */
+typedef void *crypto_provider_t;
+
+/* Limits used by both consumers and providers */
+#define CRYPTO_EXT_SIZE_LABEL 32
+#define CRYPTO_EXT_SIZE_MANUF 32
+#define CRYPTO_EXT_SIZE_MODEL 16
+#define CRYPTO_EXT_SIZE_SERIAL 16
+#define CRYPTO_EXT_SIZE_TIME 16
+
+typedef struct crypto_provider_ext_info {
+ uchar_t ei_label[CRYPTO_EXT_SIZE_LABEL];
+ uchar_t ei_manufacturerID[CRYPTO_EXT_SIZE_MANUF];
+ uchar_t ei_model[CRYPTO_EXT_SIZE_MODEL];
+ uchar_t ei_serial_number[CRYPTO_EXT_SIZE_SERIAL];
+ ulong_t ei_flags;
+ ulong_t ei_max_session_count;
+ ulong_t ei_max_pin_len;
+ ulong_t ei_min_pin_len;
+ ulong_t ei_total_public_memory;
+ ulong_t ei_free_public_memory;
+ ulong_t ei_total_private_memory;
+ ulong_t ei_free_private_memory;
+ crypto_version_t ei_hardware_version;
+ crypto_version_t ei_firmware_version;
+ uchar_t ei_time[CRYPTO_EXT_SIZE_TIME];
+ int ei_hash_max_input_len;
+ int ei_hmac_max_input_len;
+} crypto_provider_ext_info_t;
+
+typedef uint_t crypto_session_id_t;
+
+typedef enum cmd_type {
+ COPY_FROM_DATA,
+ COPY_TO_DATA,
+ COMPARE_TO_DATA,
+ MD5_DIGEST_DATA,
+ SHA1_DIGEST_DATA,
+ SHA2_DIGEST_DATA,
+ GHASH_DATA
+} cmd_type_t;
+
+#define CRYPTO_DO_UPDATE 0x01
+#define CRYPTO_DO_FINAL 0x02
+#define CRYPTO_DO_MD5 0x04
+#define CRYPTO_DO_SHA1 0x08
+#define CRYPTO_DO_SIGN 0x10
+#define CRYPTO_DO_VERIFY 0x20
+#define CRYPTO_DO_SHA2 0x40
+
+#define PROVIDER_OWNS_KEY_SCHEDULE 0x00000001
+
+/*
+ * Common cryptographic status and error codes.
+ */
+#define CRYPTO_SUCCESS 0x00000000
+#define CRYPTO_CANCEL 0x00000001
+#define CRYPTO_HOST_MEMORY 0x00000002
+#define CRYPTO_GENERAL_ERROR 0x00000003
+#define CRYPTO_FAILED 0x00000004
+#define CRYPTO_ARGUMENTS_BAD 0x00000005
+#define CRYPTO_ATTRIBUTE_READ_ONLY 0x00000006
+#define CRYPTO_ATTRIBUTE_SENSITIVE 0x00000007
+#define CRYPTO_ATTRIBUTE_TYPE_INVALID 0x00000008
+#define CRYPTO_ATTRIBUTE_VALUE_INVALID 0x00000009
+#define CRYPTO_CANCELED 0x0000000A
+#define CRYPTO_DATA_INVALID 0x0000000B
+#define CRYPTO_DATA_LEN_RANGE 0x0000000C
+#define CRYPTO_DEVICE_ERROR 0x0000000D
+#define CRYPTO_DEVICE_MEMORY 0x0000000E
+#define CRYPTO_DEVICE_REMOVED 0x0000000F
+#define CRYPTO_ENCRYPTED_DATA_INVALID 0x00000010
+#define CRYPTO_ENCRYPTED_DATA_LEN_RANGE 0x00000011
+#define CRYPTO_KEY_HANDLE_INVALID 0x00000012
+#define CRYPTO_KEY_SIZE_RANGE 0x00000013
+#define CRYPTO_KEY_TYPE_INCONSISTENT 0x00000014
+#define CRYPTO_KEY_NOT_NEEDED 0x00000015
+#define CRYPTO_KEY_CHANGED 0x00000016
+#define CRYPTO_KEY_NEEDED 0x00000017
+#define CRYPTO_KEY_INDIGESTIBLE 0x00000018
+#define CRYPTO_KEY_FUNCTION_NOT_PERMITTED 0x00000019
+#define CRYPTO_KEY_NOT_WRAPPABLE 0x0000001A
+#define CRYPTO_KEY_UNEXTRACTABLE 0x0000001B
+#define CRYPTO_MECHANISM_INVALID 0x0000001C
+#define CRYPTO_MECHANISM_PARAM_INVALID 0x0000001D
+#define CRYPTO_OBJECT_HANDLE_INVALID 0x0000001E
+#define CRYPTO_OPERATION_IS_ACTIVE 0x0000001F
+#define CRYPTO_OPERATION_NOT_INITIALIZED 0x00000020
+#define CRYPTO_PIN_INCORRECT 0x00000021
+#define CRYPTO_PIN_INVALID 0x00000022
+#define CRYPTO_PIN_LEN_RANGE 0x00000023
+#define CRYPTO_PIN_EXPIRED 0x00000024
+#define CRYPTO_PIN_LOCKED 0x00000025
+#define CRYPTO_SESSION_CLOSED 0x00000026
+#define CRYPTO_SESSION_COUNT 0x00000027
+#define CRYPTO_SESSION_HANDLE_INVALID 0x00000028
+#define CRYPTO_SESSION_READ_ONLY 0x00000029
+#define CRYPTO_SESSION_EXISTS 0x0000002A
+#define CRYPTO_SESSION_READ_ONLY_EXISTS 0x0000002B
+#define CRYPTO_SESSION_READ_WRITE_SO_EXISTS 0x0000002C
+#define CRYPTO_SIGNATURE_INVALID 0x0000002D
+#define CRYPTO_SIGNATURE_LEN_RANGE 0x0000002E
+#define CRYPTO_TEMPLATE_INCOMPLETE 0x0000002F
+#define CRYPTO_TEMPLATE_INCONSISTENT 0x00000030
+#define CRYPTO_UNWRAPPING_KEY_HANDLE_INVALID 0x00000031
+#define CRYPTO_UNWRAPPING_KEY_SIZE_RANGE 0x00000032
+#define CRYPTO_UNWRAPPING_KEY_TYPE_INCONSISTENT 0x00000033
+#define CRYPTO_USER_ALREADY_LOGGED_IN 0x00000034
+#define CRYPTO_USER_NOT_LOGGED_IN 0x00000035
+#define CRYPTO_USER_PIN_NOT_INITIALIZED 0x00000036
+#define CRYPTO_USER_TYPE_INVALID 0x00000037
+#define CRYPTO_USER_ANOTHER_ALREADY_LOGGED_IN 0x00000038
+#define CRYPTO_USER_TOO_MANY_TYPES 0x00000039
+#define CRYPTO_WRAPPED_KEY_INVALID 0x0000003A
+#define CRYPTO_WRAPPED_KEY_LEN_RANGE 0x0000003B
+#define CRYPTO_WRAPPING_KEY_HANDLE_INVALID 0x0000003C
+#define CRYPTO_WRAPPING_KEY_SIZE_RANGE 0x0000003D
+#define CRYPTO_WRAPPING_KEY_TYPE_INCONSISTENT 0x0000003E
+#define CRYPTO_RANDOM_SEED_NOT_SUPPORTED 0x0000003F
+#define CRYPTO_RANDOM_NO_RNG 0x00000040
+#define CRYPTO_DOMAIN_PARAMS_INVALID 0x00000041
+#define CRYPTO_BUFFER_TOO_SMALL 0x00000042
+#define CRYPTO_INFORMATION_SENSITIVE 0x00000043
+#define CRYPTO_NOT_SUPPORTED 0x00000044
+
+#define CRYPTO_QUEUED 0x00000045
+#define CRYPTO_BUFFER_TOO_BIG 0x00000046
+#define CRYPTO_INVALID_CONTEXT 0x00000047
+#define CRYPTO_INVALID_MAC 0x00000048
+#define CRYPTO_MECH_NOT_SUPPORTED 0x00000049
+#define CRYPTO_INCONSISTENT_ATTRIBUTE 0x0000004A
+#define CRYPTO_NO_PERMISSION 0x0000004B
+#define CRYPTO_INVALID_PROVIDER_ID 0x0000004C
+#define CRYPTO_VERSION_MISMATCH 0x0000004D
+#define CRYPTO_BUSY 0x0000004E
+#define CRYPTO_UNKNOWN_PROVIDER 0x0000004F
+#define CRYPTO_MODVERIFICATION_FAILED 0x00000050
+#define CRYPTO_OLD_CTX_TEMPLATE 0x00000051
+#define CRYPTO_WEAK_KEY 0x00000052
+#define CRYPTO_FIPS140_ERROR 0x00000053
+/*
+ * Don't forget to update CRYPTO_LAST_ERROR and the error_number_table[]
+ * in kernelUtil.c when new error code is added.
+ */
+#define CRYPTO_LAST_ERROR 0x00000053
+
+/*
+ * Special values that can be used to indicate that information is unavailable
+ * or that there is not practical limit. These values can be used
+ * by fields of the SPI crypto_provider_ext_info(9S) structure.
+ * The value of CRYPTO_UNAVAILABLE_INFO should be the same as
+ * CK_UNAVAILABLE_INFO in the PKCS#11 spec.
+ */
+#define CRYPTO_UNAVAILABLE_INFO ((ulong_t)(-1))
+#define CRYPTO_EFFECTIVELY_INFINITE 0x0
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_CRYPTO_COMMON_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.crypto.ucrypto/solaris/native/libj2ucrypto/sys_old/crypto/spi.h Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,791 @@
+/*
+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef _SYS_CRYPTO_SPI_H
+#define _SYS_CRYPTO_SPI_H
+
+/*
+ * CSPI: Cryptographic Service Provider Interface.
+ */
+
+#include <sys/types.h>
+#include <sys/crypto/common.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _KERNEL
+#include <sys/dditypes.h>
+#include <sys/ddi.h>
+#include <sys/kmem.h>
+
+#define CRYPTO_SPI_VERSION_1 1
+#define CRYPTO_SPI_VERSION_2 2
+#define CRYPTO_SPI_VERSION_3 3
+#define CRYPTO_SPI_VERSION_4 4
+#define CRYPTO_SPI_VERSION_5 5
+
+#define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
+#define CRYPTO_PROVIDER_OFFSET(f) \
+ offsetof(crypto_provider_management_ops_t, f)
+#define CRYPTO_OBJECT_OFFSET(f) offsetof(crypto_object_ops_t, f)
+#define CRYPTO_SESSION_OFFSET(f) offsetof(crypto_session_ops_t, f)
+
+#endif
+
+/*
+ * Provider-private handle. This handle is specified by a provider
+ * when it registers by means of the pi_provider_handle field of
+ * the crypto_provider_info structure, and passed to the provider
+ * when its entry points are invoked.
+ */
+typedef void *crypto_provider_handle_t;
+
+/*
+ * Context templates can be used to by software providers to pre-process
+ * keying material, such as key schedules. They are allocated by
+ * a software provider create_ctx_template(9E) entry point, and passed
+ * as argument to initialization and atomic provider entry points.
+ */
+typedef void *crypto_spi_ctx_template_t;
+
+/*
+ * Request handles are used by the kernel to identify an asynchronous
+ * request being processed by a provider. It is passed by the kernel
+ * to a hardware provider when submitting a request, and must be
+ * specified by a provider when calling crypto_op_notification(9F)
+ */
+typedef void *crypto_req_handle_t;
+
+/*
+ * The context structure is passed from kcf to a provider in kernel and
+ * internally in libsoftcrypto between ucrypto and the algorithm.
+ * It contains the information needed to process a multi-part or
+ * single part operation. The context structure is not used
+ * by atomic operations.
+ *
+ * Parameters needed to perform a cryptographic operation, such
+ * as keys, mechanisms, input and output buffers, are passed
+ * as separate arguments to Provider routines.
+ */
+typedef struct crypto_ctx {
+ crypto_provider_handle_t cc_provider;
+ crypto_session_id_t cc_session;
+ void *cc_provider_private; /* owned by provider */
+ void *cc_framework_private; /* owned by framework */
+ uint32_t cc_flags; /* flags */
+ void *cc_opstate; /* state */
+} crypto_ctx_t;
+
+#ifdef _KERNEL
+
+/* Values for cc_flags field */
+#define CRYPTO_INIT_OPSTATE 0x00000001 /* allocate and init cc_opstate */
+#define CRYPTO_USE_OPSTATE 0x00000002 /* .. start using it as context */
+
+/*
+ * Extended provider information.
+ */
+
+/*
+ * valid values for ei_flags field of extended info structure
+ * They match the RSA Security, Inc PKCS#11 tokenInfo flags.
+ */
+#define CRYPTO_EXTF_RNG 0x00000001
+#define CRYPTO_EXTF_WRITE_PROTECTED 0x00000002
+#define CRYPTO_EXTF_LOGIN_REQUIRED 0x00000004
+#define CRYPTO_EXTF_USER_PIN_INITIALIZED 0x00000008
+#define CRYPTO_EXTF_CLOCK_ON_TOKEN 0x00000040
+#define CRYPTO_EXTF_PROTECTED_AUTHENTICATION_PATH 0x00000100
+#define CRYPTO_EXTF_DUAL_CRYPTO_OPERATIONS 0x00000200
+#define CRYPTO_EXTF_TOKEN_INITIALIZED 0x00000400
+#define CRYPTO_EXTF_USER_PIN_COUNT_LOW 0x00010000
+#define CRYPTO_EXTF_USER_PIN_FINAL_TRY 0x00020000
+#define CRYPTO_EXTF_USER_PIN_LOCKED 0x00040000
+#define CRYPTO_EXTF_USER_PIN_TO_BE_CHANGED 0x00080000
+#define CRYPTO_EXTF_SO_PIN_COUNT_LOW 0x00100000
+#define CRYPTO_EXTF_SO_PIN_FINAL_TRY 0x00200000
+#define CRYPTO_EXTF_SO_PIN_LOCKED 0x00400000
+#define CRYPTO_EXTF_SO_PIN_TO_BE_CHANGED 0x00800000
+
+/*
+ * The crypto_control_ops structure contains pointers to control
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_control_ops {
+ void (*provider_status)(crypto_provider_handle_t, uint_t *);
+} crypto_control_ops_t;
+
+/*
+ * The crypto_ctx_ops structure contains points to context and context
+ * templates management operations for cryptographic providers. It is
+ * passed through the crypto_ops(9S) structure when providers register
+ * with the kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_ctx_ops {
+ int (*create_ctx_template)(crypto_provider_handle_t,
+ crypto_mechanism_t *, crypto_key_t *,
+ crypto_spi_ctx_template_t *, size_t *, crypto_req_handle_t);
+ int (*free_context)(crypto_ctx_t *);
+} crypto_ctx_ops_t;
+
+/*
+ * The crypto_digest_ops structure contains pointers to digest
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_digest_ops {
+ int (*digest_init)(crypto_ctx_t *, crypto_mechanism_t *,
+ crypto_req_handle_t);
+ int (*digest)(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+ int (*digest_update)(crypto_ctx_t *, crypto_data_t *,
+ crypto_req_handle_t);
+ int (*digest_key)(crypto_ctx_t *, crypto_key_t *, crypto_req_handle_t);
+ int (*digest_final)(crypto_ctx_t *, crypto_data_t *,
+ crypto_req_handle_t);
+ int (*digest_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_data_t *,
+ crypto_data_t *, crypto_req_handle_t);
+} crypto_digest_ops_t;
+
+/*
+ * The crypto_cipher_ops structure contains pointers to encryption
+ * and decryption operations for cryptographic providers. It is
+ * passed through the crypto_ops(9S) structure when providers register
+ * with the kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_cipher_ops {
+ int (*encrypt_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+ int (*encrypt)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*encrypt_update)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*encrypt_final)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*encrypt_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
+
+ int (*decrypt_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+ int (*decrypt)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*decrypt_update)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*decrypt_final)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*decrypt_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
+} crypto_cipher_ops_t;
+
+/*
+ * The crypto_mac_ops structure contains pointers to MAC
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_mac_ops {
+ int (*mac_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+ int (*mac)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*mac_update)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*mac_final)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*mac_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*mac_verify_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+} crypto_mac_ops_t;
+
+/*
+ * The crypto_sign_ops structure contains pointers to signing
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_sign_ops {
+ int (*sign_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*sign)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*sign_update)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*sign_final)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*sign_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*sign_recover_init)(crypto_ctx_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*sign_recover)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*sign_recover_atomic)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
+ crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+} crypto_sign_ops_t;
+
+/*
+ * The crypto_verify_ops structure contains pointers to verify
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_verify_ops {
+ int (*verify_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*verify)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*verify_update)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*verify_final)(crypto_ctx_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*verify_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*verify_recover_init)(crypto_ctx_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+ int (*verify_recover)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*verify_recover_atomic)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
+ crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_req_handle_t);
+} crypto_verify_ops_t;
+
+/*
+ * The crypto_dual_ops structure contains pointers to dual
+ * cipher and sign/verify operations for cryptographic providers.
+ * It is passed through the crypto_ops(9S) structure when
+ * providers register with the kernel using
+ * crypto_register_provider(9F).
+ */
+typedef struct crypto_dual_ops {
+ int (*digest_encrypt_update)(
+ crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*decrypt_digest_update)(
+ crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*sign_encrypt_update)(
+ crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
+ crypto_data_t *, crypto_req_handle_t);
+ int (*decrypt_verify_update)(
+ crypto_ctx_t *, crypto_ctx_t *, crypto_data_t *,
+ crypto_data_t *, crypto_req_handle_t);
+} crypto_dual_ops_t;
+
+/*
+ * The crypto_dual_cipher_mac_ops structure contains pointers to dual
+ * cipher and MAC operations for cryptographic providers.
+ * It is passed through the crypto_ops(9S) structure when
+ * providers register with the kernel using
+ * crypto_register_provider(9F).
+ */
+typedef struct crypto_dual_cipher_mac_ops {
+ int (*encrypt_mac_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_spi_ctx_template_t,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+ int (*encrypt_mac)(crypto_ctx_t *,
+ crypto_data_t *, crypto_dual_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+ int (*encrypt_mac_update)(crypto_ctx_t *,
+ crypto_data_t *, crypto_dual_data_t *, crypto_req_handle_t);
+ int (*encrypt_mac_final)(crypto_ctx_t *,
+ crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*encrypt_mac_atomic)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_data_t *, crypto_dual_data_t *,
+ crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+
+ int (*mac_decrypt_init)(crypto_ctx_t *,
+ crypto_mechanism_t *, crypto_key_t *, crypto_mechanism_t *,
+ crypto_key_t *, crypto_spi_ctx_template_t,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+ int (*mac_decrypt)(crypto_ctx_t *,
+ crypto_dual_data_t *, crypto_data_t *, crypto_data_t *,
+ crypto_req_handle_t);
+ int (*mac_decrypt_update)(crypto_ctx_t *,
+ crypto_dual_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*mac_decrypt_final)(crypto_ctx_t *,
+ crypto_data_t *, crypto_data_t *, crypto_req_handle_t);
+ int (*mac_decrypt_atomic)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
+ crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
+ crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+ int (*mac_verify_decrypt_atomic)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *,
+ crypto_mechanism_t *, crypto_key_t *, crypto_dual_data_t *,
+ crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t,
+ crypto_spi_ctx_template_t, crypto_req_handle_t);
+} crypto_dual_cipher_mac_ops_t;
+
+/*
+ * The crypto_random_number_ops structure contains pointers to random
+ * number operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_random_number_ops {
+ int (*seed_random)(crypto_provider_handle_t, crypto_session_id_t,
+ uchar_t *, size_t, uint_t, uint32_t, crypto_req_handle_t);
+ int (*generate_random)(crypto_provider_handle_t, crypto_session_id_t,
+ uchar_t *, size_t, crypto_req_handle_t);
+} crypto_random_number_ops_t;
+
+/*
+ * Flag values for seed_random.
+ */
+#define CRYPTO_SEED_NOW 0x00000001
+
+/*
+ * The crypto_session_ops structure contains pointers to session
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_session_ops {
+ int (*session_open)(crypto_provider_handle_t, crypto_session_id_t *,
+ crypto_req_handle_t);
+ int (*session_close)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_req_handle_t);
+ int (*session_login)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_user_type_t, char *, size_t, crypto_req_handle_t);
+ int (*session_logout)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_req_handle_t);
+} crypto_session_ops_t;
+
+/*
+ * The crypto_object_ops structure contains pointers to object
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_object_ops {
+ int (*object_create)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
+ crypto_req_handle_t);
+ int (*object_copy)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_object_id_t, crypto_object_attribute_t *, uint_t,
+ crypto_object_id_t *, crypto_req_handle_t);
+ int (*object_destroy)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_object_id_t, crypto_req_handle_t);
+ int (*object_get_size)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_object_id_t, size_t *, crypto_req_handle_t);
+ int (*object_get_attribute_value)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_object_id_t,
+ crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
+ int (*object_set_attribute_value)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_object_id_t,
+ crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
+ int (*object_find_init)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_object_attribute_t *, uint_t, void **,
+ crypto_req_handle_t);
+ int (*object_find)(crypto_provider_handle_t, void *,
+ crypto_object_id_t *, uint_t, uint_t *, crypto_req_handle_t);
+ int (*object_find_final)(crypto_provider_handle_t, void *,
+ crypto_req_handle_t);
+} crypto_object_ops_t;
+
+/*
+ * The crypto_key_ops structure contains pointers to key
+ * operations for cryptographic providers. It is passed through
+ * the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_key_ops {
+ int (*key_generate)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_object_attribute_t *, uint_t,
+ crypto_object_id_t *, crypto_req_handle_t);
+ int (*key_generate_pair)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_object_attribute_t *, uint_t,
+ crypto_object_attribute_t *, uint_t, crypto_object_id_t *,
+ crypto_object_id_t *, crypto_req_handle_t);
+ int (*key_wrap)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_object_id_t *,
+ uchar_t *, size_t *, crypto_req_handle_t);
+ int (*key_unwrap)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, uchar_t *, size_t *,
+ crypto_object_attribute_t *, uint_t,
+ crypto_object_id_t *, crypto_req_handle_t);
+ int (*key_derive)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *,
+ uint_t, crypto_object_id_t *, crypto_req_handle_t);
+ int (*key_check)(crypto_provider_handle_t, crypto_mechanism_t *,
+ crypto_key_t *);
+} crypto_key_ops_t;
+
+/*
+ * The crypto_provider_management_ops structure contains pointers
+ * to management operations for cryptographic providers. It is passed
+ * through the crypto_ops(9S) structure when providers register with the
+ * kernel using crypto_register_provider(9F).
+ */
+typedef struct crypto_provider_management_ops {
+ int (*ext_info)(crypto_provider_handle_t,
+ crypto_provider_ext_info_t *, crypto_req_handle_t);
+ int (*init_token)(crypto_provider_handle_t, char *, size_t,
+ char *, crypto_req_handle_t);
+ int (*init_pin)(crypto_provider_handle_t, crypto_session_id_t,
+ char *, size_t, crypto_req_handle_t);
+ int (*set_pin)(crypto_provider_handle_t, crypto_session_id_t,
+ char *, size_t, char *, size_t, crypto_req_handle_t);
+} crypto_provider_management_ops_t;
+
+typedef struct crypto_mech_ops {
+ int (*copyin_mechanism)(crypto_provider_handle_t,
+ crypto_mechanism_t *, crypto_mechanism_t *, int *, int);
+ int (*copyout_mechanism)(crypto_provider_handle_t,
+ crypto_mechanism_t *, crypto_mechanism_t *, int *, int);
+ int (*free_mechanism)(crypto_provider_handle_t, crypto_mechanism_t *);
+} crypto_mech_ops_t;
+
+typedef struct crypto_nostore_key_ops {
+ int (*nostore_key_generate)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_mechanism_t *,
+ crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
+ uint_t, crypto_req_handle_t);
+ int (*nostore_key_generate_pair)(crypto_provider_handle_t,
+ crypto_session_id_t, crypto_mechanism_t *,
+ crypto_object_attribute_t *, uint_t, crypto_object_attribute_t *,
+ uint_t, crypto_object_attribute_t *, uint_t,
+ crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
+ int (*nostore_key_derive)(crypto_provider_handle_t, crypto_session_id_t,
+ crypto_mechanism_t *, crypto_key_t *, crypto_object_attribute_t *,
+ uint_t, crypto_object_attribute_t *, uint_t, crypto_req_handle_t);
+} crypto_nostore_key_ops_t;
+
+/*
+ * crypto_fips140_ops provides a function for FIPS 140 Power-On Self Test for
+ * those providers that are part of the Cryptographic Framework bounday. See
+ * crypto_fips140_ops(9s) for details.
+ */
+typedef struct crypto_fips140_ops {
+ void (*fips140_post)(int *);
+} crypto_fips140_ops_t;
+
+/*
+ * The crypto_ops(9S) structure contains the structures containing
+ * the pointers to functions implemented by cryptographic providers.
+ * It is specified as part of the crypto_provider_info(9S)
+ * supplied by a provider when it registers with the kernel
+ * by calling crypto_register_provider(9F).
+ */
+typedef struct crypto_ops_v1 {
+ crypto_control_ops_t *co_control_ops;
+ crypto_digest_ops_t *co_digest_ops;
+ crypto_cipher_ops_t *co_cipher_ops;
+ crypto_mac_ops_t *co_mac_ops;
+ crypto_sign_ops_t *co_sign_ops;
+ crypto_verify_ops_t *co_verify_ops;
+ crypto_dual_ops_t *co_dual_ops;
+ crypto_dual_cipher_mac_ops_t *co_dual_cipher_mac_ops;
+ crypto_random_number_ops_t *co_random_ops;
+ crypto_session_ops_t *co_session_ops;
+ crypto_object_ops_t *co_object_ops;
+ crypto_key_ops_t *co_key_ops;
+ crypto_provider_management_ops_t *co_provider_ops;
+ crypto_ctx_ops_t *co_ctx_ops;
+} crypto_ops_v1_t;
+
+typedef struct crypto_ops_v2 {
+ crypto_ops_v1_t v1_ops;
+ crypto_mech_ops_t *co_mech_ops;
+} crypto_ops_v2_t;
+
+typedef struct crypto_ops_v3 {
+ crypto_ops_v2_t v2_ops;
+ crypto_nostore_key_ops_t *co_nostore_key_ops;
+} crypto_ops_v3_t;
+
+typedef struct crypto_ops_v4 {
+ crypto_ops_v3_t v3_ops;
+ crypto_fips140_ops_t *co_fips140_ops;
+} crypto_ops_v4_t;
+
+typedef struct crypto_ops_v5 {
+ crypto_ops_v4_t v4_ops;
+ boolean_t co_uio_userspace_ok;
+} crypto_ops_v5_t;
+
+typedef struct crypto_ops {
+ union {
+ crypto_ops_v5_t cou_v5;
+ crypto_ops_v4_t cou_v4;
+ crypto_ops_v3_t cou_v3;
+ crypto_ops_v2_t cou_v2;
+ crypto_ops_v1_t cou_v1;
+ } cou;
+} crypto_ops_t;
+
+#define co_control_ops cou.cou_v1.co_control_ops
+#define co_digest_ops cou.cou_v1.co_digest_ops
+#define co_cipher_ops cou.cou_v1.co_cipher_ops
+#define co_mac_ops cou.cou_v1.co_mac_ops
+#define co_sign_ops cou.cou_v1.co_sign_ops
+#define co_verify_ops cou.cou_v1.co_verify_ops
+#define co_dual_ops cou.cou_v1.co_dual_ops
+#define co_dual_cipher_mac_ops cou.cou_v1.co_dual_cipher_mac_ops
+#define co_random_ops cou.cou_v1.co_random_ops
+#define co_session_ops cou.cou_v1.co_session_ops
+#define co_object_ops cou.cou_v1.co_object_ops
+#define co_key_ops cou.cou_v1.co_key_ops
+#define co_provider_ops cou.cou_v1.co_provider_ops
+#define co_ctx_ops cou.cou_v1.co_ctx_ops
+#define co_mech_ops cou.cou_v2.co_mech_ops
+#define co_nostore_key_ops cou.cou_v3.co_nostore_key_ops
+#define co_fips140_ops cou.cou_v4.co_fips140_ops
+#define co_uio_userspace_ok cou.cou_v5.co_uio_userspace_ok
+
+/*
+ * Provider device specification passed during registration.
+ *
+ * Software providers set the pi_provider_type field of provider_info_t
+ * to CRYPTO_SW_PROVIDER, and set the pd_sw field of
+ * crypto_provider_dev_t to the address of their modlinkage.
+ *
+ * Hardware providers set the pi_provider_type field of provider_info_t
+ * to CRYPTO_HW_PROVIDER, and set the pd_hw field of
+ * crypto_provider_dev_t to the dev_info structure corresponding
+ * to the device instance being registered.
+ *
+ * Logical providers set the pi_provider_type field of provider_info_t
+ * to CRYPTO_LOGICAL_PROVIDER, and set the pd_hw field of
+ * crypto_provider_dev_t to the dev_info structure corresponding
+ * to the device instance being registered.
+ */
+
+typedef union crypto_provider_dev {
+ struct modlinkage *pd_sw; /* for CRYPTO_SW_PROVIDER */
+ dev_info_t *pd_hw; /* for CRYPTO_HW_PROVIDER */
+} crypto_provider_dev_t;
+
+/*
+ * The mechanism info structure crypto_mech_info_t contains a function group
+ * bit mask cm_func_group_mask. This field, of type crypto_func_group_t,
+ * specifies the provider entry point that can be used a particular
+ * mechanism. The function group mask is a combination of the following values.
+ */
+
+typedef uint32_t crypto_func_group_t;
+
+#endif /* _KERNEL */
+
+#define CRYPTO_FG_ENCRYPT 0x00000001 /* encrypt_init() */
+#define CRYPTO_FG_DECRYPT 0x00000002 /* decrypt_init() */
+#define CRYPTO_FG_DIGEST 0x00000004 /* digest_init() */
+#define CRYPTO_FG_SIGN 0x00000008 /* sign_init() */
+#define CRYPTO_FG_SIGN_RECOVER 0x00000010 /* sign_recover_init() */
+#define CRYPTO_FG_VERIFY 0x00000020 /* verify_init() */
+#define CRYPTO_FG_VERIFY_RECOVER 0x00000040 /* verify_recover_init() */
+#define CRYPTO_FG_GENERATE 0x00000080 /* key_generate() */
+#define CRYPTO_FG_GENERATE_KEY_PAIR 0x00000100 /* key_generate_pair() */
+#define CRYPTO_FG_WRAP 0x00000200 /* key_wrap() */
+#define CRYPTO_FG_UNWRAP 0x00000400 /* key_unwrap() */
+#define CRYPTO_FG_DERIVE 0x00000800 /* key_derive() */
+#define CRYPTO_FG_MAC 0x00001000 /* mac_init() */
+#define CRYPTO_FG_ENCRYPT_MAC 0x00002000 /* encrypt_mac_init() */
+#define CRYPTO_FG_MAC_DECRYPT 0x00004000 /* decrypt_mac_init() */
+#define CRYPTO_FG_ENCRYPT_ATOMIC 0x00008000 /* encrypt_atomic() */
+#define CRYPTO_FG_DECRYPT_ATOMIC 0x00010000 /* decrypt_atomic() */
+#define CRYPTO_FG_MAC_ATOMIC 0x00020000 /* mac_atomic() */
+#define CRYPTO_FG_DIGEST_ATOMIC 0x00040000 /* digest_atomic() */
+#define CRYPTO_FG_SIGN_ATOMIC 0x00080000 /* sign_atomic() */
+#define CRYPTO_FG_SIGN_RECOVER_ATOMIC 0x00100000 /* sign_recover_atomic() */
+#define CRYPTO_FG_VERIFY_ATOMIC 0x00200000 /* verify_atomic() */
+#define CRYPTO_FG_VERIFY_RECOVER_ATOMIC 0x00400000 /* verify_recover_atomic() */
+#define CRYPTO_FG_ENCRYPT_MAC_ATOMIC 0x00800000 /* encrypt_mac_atomic() */
+#define CRYPTO_FG_MAC_DECRYPT_ATOMIC 0x01000000 /* mac_decrypt_atomic() */
+#define CRYPTO_FG_RESERVED 0x80000000
+
+/*
+ * Maximum length of the pi_provider_description field of the
+ * crypto_provider_info structure.
+ */
+#define CRYPTO_PROVIDER_DESCR_MAX_LEN 64
+
+#ifdef _KERNEL
+
+/* Bit mask for all the simple operations */
+#define CRYPTO_FG_SIMPLEOP_MASK (CRYPTO_FG_ENCRYPT | CRYPTO_FG_DECRYPT | \
+ CRYPTO_FG_DIGEST | CRYPTO_FG_SIGN | CRYPTO_FG_VERIFY | CRYPTO_FG_MAC | \
+ CRYPTO_FG_ENCRYPT_ATOMIC | CRYPTO_FG_DECRYPT_ATOMIC | \
+ CRYPTO_FG_MAC_ATOMIC | CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_SIGN_ATOMIC | \
+ CRYPTO_FG_VERIFY_ATOMIC)
+
+/* Bit mask for all the dual operations */
+#define CRYPTO_FG_MAC_CIPHER_MASK (CRYPTO_FG_ENCRYPT_MAC | \
+ CRYPTO_FG_MAC_DECRYPT | CRYPTO_FG_ENCRYPT_MAC_ATOMIC | \
+ CRYPTO_FG_MAC_DECRYPT_ATOMIC)
+
+/* Add other combos to CRYPTO_FG_DUAL_MASK */
+#define CRYPTO_FG_DUAL_MASK CRYPTO_FG_MAC_CIPHER_MASK
+
+/*
+ * The crypto_mech_info structure specifies one of the mechanisms
+ * supported by a cryptographic provider. The pi_mechanisms field of
+ * the crypto_provider_info structure contains a pointer to an array
+ * of crypto_mech_info's.
+ */
+typedef struct crypto_mech_info {
+ crypto_mech_name_t cm_mech_name;
+ crypto_mech_type_t cm_mech_number;
+ crypto_func_group_t cm_func_group_mask;
+ ssize_t cm_min_key_length;
+ ssize_t cm_max_key_length;
+ uint32_t cm_mech_flags;
+} crypto_mech_info_t;
+
+/* Alias the old name to the new name for compatibility. */
+#define cm_keysize_unit cm_mech_flags
+
+/*
+ * crypto_kcf_provider_handle_t is a handle allocated by the kernel.
+ * It is returned after the provider registers with
+ * crypto_register_provider(), and must be specified by the provider
+ * when calling crypto_unregister_provider(), and
+ * crypto_provider_notification().
+ */
+typedef uint_t crypto_kcf_provider_handle_t;
+
+/*
+ * Provider information. Passed as argument to crypto_register_provider(9F).
+ * Describes the provider and its capabilities. Multiple providers can
+ * register for the same device instance. In this case, the same
+ * pi_provider_dev must be specified with a different pi_provider_handle.
+ */
+typedef struct crypto_provider_info_v1 {
+ uint_t pi_interface_version;
+ char *pi_provider_description;
+ crypto_provider_type_t pi_provider_type;
+ crypto_provider_dev_t pi_provider_dev;
+ crypto_provider_handle_t pi_provider_handle;
+ crypto_ops_t *pi_ops_vector;
+ uint_t pi_mech_list_count;
+ crypto_mech_info_t *pi_mechanisms;
+ uint_t pi_logical_provider_count;
+ crypto_kcf_provider_handle_t *pi_logical_providers;
+} crypto_provider_info_v1_t;
+
+typedef struct crypto_provider_info_v2 {
+ crypto_provider_info_v1_t v1_info;
+ uint_t pi_flags;
+} crypto_provider_info_v2_t;
+
+typedef struct crypto_provider_info {
+ union {
+ crypto_provider_info_v2_t piu_v2;
+ crypto_provider_info_v1_t piu_v1;
+ } piu;
+} crypto_provider_info_t;
+
+#define pi_interface_version piu.piu_v1.pi_interface_version
+#define pi_provider_description piu.piu_v1.pi_provider_description
+#define pi_provider_type piu.piu_v1.pi_provider_type
+#define pi_provider_dev piu.piu_v1.pi_provider_dev
+#define pi_provider_handle piu.piu_v1.pi_provider_handle
+#define pi_ops_vector piu.piu_v1.pi_ops_vector
+#define pi_mech_list_count piu.piu_v1.pi_mech_list_count
+#define pi_mechanisms piu.piu_v1.pi_mechanisms
+#define pi_logical_provider_count piu.piu_v1.pi_logical_provider_count
+#define pi_logical_providers piu.piu_v1.pi_logical_providers
+#define pi_flags piu.piu_v2.pi_flags
+
+/* hidden providers can only be accessed via a logical provider */
+#define CRYPTO_HIDE_PROVIDER 0x00000001
+/*
+ * provider can not do multi-part digest (updates) and has a limit
+ * on maximum input data that it can digest. The provider sets
+ * this value in crypto_provider_ext_info_t by implementing
+ * the ext_info entry point in the co_provider_ops vector.
+ */
+#define CRYPTO_HASH_NO_UPDATE 0x00000002
+/*
+ * provider can not do multi-part HMAC (updates) and has a limit
+ * on maximum input data that it can hmac. The provider sets
+ * this value in crypto_provider_ext_info_t by implementing
+ * the ext_info entry point in the co_provider_ops vector.
+ */
+#define CRYPTO_HMAC_NO_UPDATE 0x00000008
+
+/* provider can handle the request without returning a CRYPTO_QUEUED */
+#define CRYPTO_SYNCHRONOUS 0x00000004
+
+#define CRYPTO_PIFLAGS_RESERVED2 0x40000000
+#define CRYPTO_PIFLAGS_RESERVED1 0x80000000
+
+/*
+ * Provider status passed by a provider to crypto_provider_notification(9F)
+ * and returned by the provider_stauts(9E) entry point.
+ */
+#define CRYPTO_PROVIDER_READY 0
+#define CRYPTO_PROVIDER_BUSY 1
+#define CRYPTO_PROVIDER_FAILED 2
+
+/*
+ * Functions exported by Solaris to cryptographic providers. Providers
+ * call these functions to register and unregister, notify the kernel
+ * of state changes, and notify the kernel when a asynchronous request
+ * completed.
+ */
+extern int crypto_register_provider(crypto_provider_info_t *,
+ crypto_kcf_provider_handle_t *);
+extern int crypto_unregister_provider(crypto_kcf_provider_handle_t);
+extern void crypto_provider_notification(crypto_kcf_provider_handle_t, uint_t);
+extern void crypto_op_notification(crypto_req_handle_t, int);
+extern int crypto_kmflag(crypto_req_handle_t);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_CRYPTO_SPI_H */
--- a/jdk/test/TEST.groups Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/test/TEST.groups Tue Oct 21 13:56:58 2014 -0700
@@ -120,6 +120,7 @@
jdk_security2 = \
javax/crypto \
javax/xml/crypto \
+ com/oracle/security/ucrypto \
com/sun/crypto
jdk_security3 = \
@@ -390,6 +391,10 @@
:jdk_desktop \
com/sun/corba \
com/sun/jndi/cosnaming \
+ com/oracle/security/ucrypto/Test8004873.java \
+ com/oracle/security/ucrypto/TestAES.java \
+ com/oracle/security/ucrypto/TestDigest.java \
+ com/oracle/security/ucrypto/TestRSA.java \
sun/net/ftp \
sun/net/www/protocol/ftp \
sun/security/tools/policytool \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/CipherSignNotSupported.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8029849
+ * @summary Make sure signing via encrypt and verifying via decrypt are not
+ * supported by OracleUcrypto provider.
+ * @author Anthony Scarpino
+ */
+
+import java.util.Random;
+import java.security.KeyPairGenerator;
+import java.security.KeyPair;
+import javax.crypto.Cipher;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Provider;
+
+public class CipherSignNotSupported extends UcryptoTest {
+
+ public static void main(String[] args) throws Exception {
+ main(new CipherSignNotSupported(), null);
+ }
+
+ public void doTest(Provider p) throws Exception {
+ Cipher c = null;
+ Random random = new Random();
+ byte[] pt = new byte[117];
+ byte[] ct = new byte[200];
+ random.nextBytes(pt);
+
+ try {
+ c = Cipher.getInstance("RSA/ECB/PKCS1Padding", p);
+ } catch (NoSuchAlgorithmException e) {
+ if (System.getProperty("os.version").compareTo("5.10") == 0) {
+ System.out.println("RSA not supported in S10");
+ return;
+ }
+ throw e;
+ }
+
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ kpg.initialize(1024);
+ KeyPair kp = kpg.generateKeyPair();
+
+ // Encryption
+ c.init(Cipher.ENCRYPT_MODE, kp.getPublic());
+ ct = c.doFinal(pt);
+ // Decryption
+ c.init(Cipher.DECRYPT_MODE, kp.getPrivate());
+ c.doFinal(ct);
+ // Sign
+ try {
+ c.init(Cipher.ENCRYPT_MODE, kp.getPrivate());
+ ct = c.doFinal(pt);
+ throw new RuntimeException("Encrypt operation should have failed.");
+ } catch (InvalidKeyException e) {
+ if (e.getMessage().compareTo("RSAPublicKey required for " +
+ "encryption") != 0) {
+ System.out.println("Wrong exception thrown.");
+ throw e;
+ }
+ }
+ // Verify
+ try {
+ c.init(Cipher.DECRYPT_MODE, kp.getPublic());
+ c.doFinal(ct);
+ throw new RuntimeException("Decrypt operation should have failed.");
+ } catch (InvalidKeyException e) {
+ if (e.getMessage().compareTo("RSAPrivateCrtKey required for " +
+ "decryption") != 0) {
+ System.out.println("Wrong exception thrown.");
+ throw e;
+ }
+ }
+
+ System.out.println("Pass");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/Test8004873.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8004873
+ * @summary Need to include data buffered by Padding impl when calculating
+ * output buffer sizes.
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class Test8004873 extends UcryptoTest {
+
+ private static final String[] PADDEDCIPHER_ALGOS = {
+ "AES/ECB/PKCS5Padding",
+ "AES/CBC/PKCS5Padding",
+ "AES/CFB128/PKCS5Padding"
+ };
+
+ private static final SecretKey AES_KEY;
+
+ static {
+ byte[] keyValue = {
+ 62, 124, -2, -15, 86, -25, 18, -112, 110, 31, 96, 59,
+ 89, 70, 60, 103};
+ AES_KEY = new SecretKeySpec(keyValue, "AES");
+ }
+
+ public static void main(String[] args) throws Exception {
+ main(new Test8004873(), null);
+ }
+
+ public void doTest(Provider prov) throws Exception {
+ boolean result = true;
+ for (String algo : PADDEDCIPHER_ALGOS) {
+ if (!testOOS(algo, prov)) {
+ result = false;
+ System.out.println(algo + " Test Failed!");
+ }
+ }
+ if (!result) {
+ throw new Exception("One or more test failed!");
+ }
+ }
+
+ private boolean testOOS(String algo, Provider prov)
+ throws Exception {
+
+ String password = "abcd1234";
+ Cipher c;
+ try {
+ c = Cipher.getInstance(algo, prov);
+ } catch(NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Unsupported algo: " + algo);
+ return true;
+ }
+ c.init(Cipher.ENCRYPT_MODE, AES_KEY);
+ AlgorithmParameters params = c.getParameters();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ CipherOutputStream cos = new CipherOutputStream(baos, c);
+ ObjectOutputStream oos = new ObjectOutputStream(cos);
+ oos.writeObject(password);
+ oos.flush();
+ oos.close();
+ byte[] encrypted = baos.toByteArray();
+
+ c.init(Cipher.DECRYPT_MODE, AES_KEY, params);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(encrypted);
+ CipherInputStream cis = new CipherInputStream(bais, c);
+ ObjectInputStream ois = new ObjectInputStream(cis);
+
+ String recovered = (String) ois.readObject();
+ return recovered.equals(password);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestAES.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7088989 8014374
+ * @summary Ensure the AES ciphers of OracleUcrypto provider works correctly
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class TestAES extends UcryptoTest {
+
+ private static final String[] PADDEDCIPHER_ALGOS = {
+ "AES/ECB/PKCS5Padding",
+ "AES/CBC/PKCS5Padding",
+ "AES/CFB128/PKCS5Padding"
+ };
+
+ private static final String[] CIPHER_ALGOS = {
+ "AES/ECB/NoPadding",
+ "AES/CBC/NoPadding",
+ "AES/CFB128/NoPadding",
+ "AES/CTR/NoPadding",
+ };
+
+ private static final SecretKey CIPHER_KEY =
+ new SecretKeySpec(new byte[16], "AES");
+
+ public static void main(String[] args) throws Exception {
+ main(new TestAES(), null);
+ }
+
+ public void doTest(Provider prov) throws Exception {
+ // Provider for testing Interoperability
+ Provider sunJCEProv = Security.getProvider("SunJCE");
+
+ testCipherInterop(CIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
+ testCipherInterop(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
+
+ testCipherOffset(CIPHER_ALGOS, CIPHER_KEY, prov);
+ testCipherOffset(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov);
+
+ testCipherKeyWrapping(PADDEDCIPHER_ALGOS, CIPHER_KEY, prov, sunJCEProv);
+ testCipherGCM(CIPHER_KEY, prov);
+ }
+
+ private static void testCipherInterop(String[] algos, SecretKey key,
+ Provider p,
+ Provider interopP) {
+ boolean testPassed = true;
+ byte[] in = new byte[32];
+ (new SecureRandom()).nextBytes(in);
+
+ for (String algo : algos) {
+ try {
+ // check ENC
+ Cipher c;
+ try {
+ c = Cipher.getInstance(algo, p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Unsupported CIP algo: " + algo);
+ continue;
+ }
+ c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null);
+ byte[] eout = c.doFinal(in, 0, in.length);
+
+ AlgorithmParameters params = c.getParameters();
+ Cipher c2 = Cipher.getInstance(algo, interopP);
+ c2.init(Cipher.ENCRYPT_MODE, key, params, null);
+ byte[] eout2 = c2.doFinal(in, 0, in.length);
+
+ if (!Arrays.equals(eout, eout2)) {
+ System.out.println(algo + ": DIFF FAILED");
+ testPassed = false;
+ } else {
+ System.out.println(algo + ": ENC Passed");
+ }
+
+ // check DEC
+ c.init(Cipher.DECRYPT_MODE, key, params, null);
+ byte[] dout = c.doFinal(eout);
+ c2.init(Cipher.DECRYPT_MODE, key, params, null);
+ byte[] dout2 = c2.doFinal(eout2);
+
+ if (!Arrays.equals(dout, dout2)) {
+ System.out.println(algo + ": DIFF FAILED");
+ testPassed = false;
+ } else {
+ System.out.println(algo + ": DEC Passed");
+ }
+ } catch(Exception ex) {
+ System.out.println("Unexpected Exception: " + algo);
+ ex.printStackTrace();
+ testPassed = false;
+ }
+ }
+
+ if (!testPassed) {
+ throw new RuntimeException("One or more CIPHER test failed!");
+ } else {
+ System.out.println("CIPHER Interop Tests Passed");
+ }
+ }
+
+ private static void testCipherOffset(String[] algos, SecretKey key,
+ Provider p) {
+ boolean testPassed = true;
+ byte[] in = new byte[16];
+ (new SecureRandom()).nextBytes(in);
+ int blockSize = 16;
+
+ for (int j = 1; j < (in.length - 1); j++) {
+ System.out.println("Input offset size: " + j);
+ for (int i = 0; i < algos.length; i++) {
+ try {
+ // check ENC
+ Cipher c;
+ try {
+ c = Cipher.getInstance(algos[i], p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skip Unsupported CIP algo: " + algos[i]);
+ continue;
+ }
+ c.init(Cipher.ENCRYPT_MODE, key, (AlgorithmParameters)null, null);
+ byte[] eout = new byte[c.getOutputSize(in.length)];
+ int firstPartLen = in.length - j - 1;
+ //System.out.print("1st UPDATE: " + firstPartLen);
+ int k = c.update(in, 0, firstPartLen, eout, 0);
+ k += c.update(in, firstPartLen, 1, eout, k);
+ k += c.doFinal(in, firstPartLen+1, j, eout, k);
+
+ AlgorithmParameters params = c.getParameters();
+
+ Cipher c2 = Cipher.getInstance(algos[i], p);
+ c2.init(Cipher.ENCRYPT_MODE, key, params, null);
+ byte[] eout2 = new byte[c2.getOutputSize(in.length)];
+ int k2 = c2.update(in, 0, j, eout2, 0);
+ k2 += c2.update(in, j, 1, eout2, k2);
+ k2 += c2.doFinal(in, j+1, firstPartLen, eout2, k2);
+
+ if (!checkArrays(eout, k, eout2, k2)) testPassed = false;
+
+ // check DEC
+ c.init(Cipher.DECRYPT_MODE, key, params, null);
+ byte[] dout = new byte[c.getOutputSize(eout.length)];
+ k = c.update(eout, 0, firstPartLen, dout, 0);
+ k += c.update(eout, firstPartLen, 1, dout, k);
+ k += c.doFinal(eout, firstPartLen+1, eout.length - firstPartLen - 1, dout, k);
+ if (!checkArrays(in, in.length, dout, k)) testPassed = false;
+ } catch(Exception ex) {
+ System.out.println("Unexpected Exception: " + algos[i]);
+ ex.printStackTrace();
+ testPassed = false;
+ }
+ }
+ }
+ if (!testPassed) {
+ throw new RuntimeException("One or more CIPHER test failed!");
+ } else {
+ System.out.println("CIPHER Offset Tests Passed");
+ }
+ }
+
+ private static void testCipherKeyWrapping(String[] algos, SecretKey key,
+ Provider p, Provider interopP)
+ throws NoSuchAlgorithmException {
+ boolean testPassed = true;
+
+ // Test SecretKey, PrivateKey and PublicKey
+ Key[] tbwKeys = new Key[3];
+ int[] tbwKeyTypes = { Cipher.SECRET_KEY, Cipher.PRIVATE_KEY, Cipher.PUBLIC_KEY };
+ tbwKeys[0] = new SecretKeySpec(new byte[20], "Blowfish");
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ kpg.initialize(1024);
+ KeyPair kp = kpg.generateKeyPair();
+ tbwKeys[1] = kp.getPrivate();
+ tbwKeys[2] = kp.getPublic();
+
+ for (int i = 0; i < algos.length; i++) {
+ try {
+ System.out.println(algos[i] + " - Native WRAP/Java UNWRAP");
+
+ Cipher c1;
+ try {
+ c1 = Cipher.getInstance(algos[i], p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Unsupported CIP algo: " + algos[i]);
+ continue;
+ }
+ c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null);
+ AlgorithmParameters params = c1.getParameters();
+ Cipher c2 = Cipher.getInstance(algos[i], interopP);
+ c2.init(Cipher.UNWRAP_MODE, key, params, null);
+
+ for (int j = 0; j < tbwKeys.length ; j++) {
+ byte[] wrappedKey = c1.wrap(tbwKeys[j]);
+ Key recovered = c2.unwrap(wrappedKey,
+ tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]);
+ if (!checkKeys(tbwKeys[j], recovered)) testPassed = false;
+ }
+
+ System.out.println(algos[i] + " - Java WRAP/Native UNWRAP");
+ c1 = Cipher.getInstance(algos[i], interopP);
+ c1.init(Cipher.WRAP_MODE, key, (AlgorithmParameters)null, null);
+ params = c1.getParameters();
+ c2 = Cipher.getInstance(algos[i], p);
+ c2.init(Cipher.UNWRAP_MODE, key, params, null);
+
+ for (int j = 0; j < tbwKeys.length ; j++) {
+ byte[] wrappedKey = c1.wrap(tbwKeys[j]);
+ Key recovered = c2.unwrap(wrappedKey,
+ tbwKeys[j].getAlgorithm(), tbwKeyTypes[j]);
+ if (!checkKeys(tbwKeys[j], recovered)) testPassed = false;
+ }
+
+ } catch(Exception ex) {
+ System.out.println("Unexpected Exception: " + algos[i]);
+ ex.printStackTrace();
+ testPassed = false;
+ }
+ }
+ if (!testPassed) {
+ throw new RuntimeException("One or more CIPHER test failed!");
+ } else {
+ System.out.println("CIPHER KeyWrapping Tests Passed");
+ }
+ }
+
+
+ private static void testCipherGCM(SecretKey key,
+ Provider p) {
+ boolean testPassed = true;
+ byte[] in = new byte[16];
+ (new SecureRandom()).nextBytes(in);
+
+ byte[] iv = new byte[16];
+ (new SecureRandom()).nextBytes(iv);
+
+
+ String algo = "AES/GCM/NoPadding";
+ int tagLen[] = { 128, 120, 112, 104, 96, 64, 32 };
+
+ try {
+ Cipher c;
+ try {
+ c = Cipher.getInstance(algo, p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Unsupported CIP algo: " + algo);
+ return;
+ }
+ for (int i = 0; i < tagLen.length; i++) {
+ // change iv value to pass the key+iv uniqueness cehck for
+ // GCM encryption
+ iv[0] += 1;
+ AlgorithmParameterSpec paramSpec = new GCMParameterSpec(tagLen[i], iv);
+ // check ENC
+ c.init(Cipher.ENCRYPT_MODE, key, paramSpec, null);
+ c.updateAAD(iv);
+ byte[] eout = c.doFinal(in, 0, in.length);
+
+ AlgorithmParameters param = c.getParameters();
+ // check DEC
+ c.init(Cipher.DECRYPT_MODE, key, param, null);
+ c.updateAAD(iv);
+ byte[] dout = c.doFinal(eout, 0, eout.length);
+
+ if (!Arrays.equals(dout, in)) {
+ System.out.println(algo + ": PT and RT DIFF FAILED");
+ testPassed = false;
+ } else {
+ System.out.println(algo + ": tagLen " + tagLen[i] + " done");
+ }
+ }
+ } catch(Exception ex) {
+ System.out.println("Unexpected Exception: " + algo);
+ ex.printStackTrace();
+ testPassed = false;
+ }
+ if (!testPassed) {
+ throw new RuntimeException("One or more CIPHER test failed!");
+ } else {
+ System.out.println("CIPHER GCM Tests Passed");
+ }
+ }
+
+ private static boolean checkArrays(byte[] a1, int a1Len, byte[] a2, int a2Len) {
+ boolean equal = true;
+ if (a1Len != a2Len) {
+ System.out.println("DIFFERENT OUT LENGTH");
+ equal = false;
+ } else {
+ for (int p = 0; p < a1Len; p++) {
+ if (a1[p] != a2[p]) {
+ System.out.println("DIFF FAILED");
+ equal = false;
+ break;
+ }
+ }
+ }
+ return equal;
+ }
+
+ private static boolean checkKeys(Key k1, Key k2) {
+ boolean equal = true;
+ if (!k1.getAlgorithm().equalsIgnoreCase(k2.getAlgorithm())) {
+ System.out.println("DIFFERENT Key Algorithm");
+ equal = false;
+ } else if (!k1.getFormat().equalsIgnoreCase(k2.getFormat())) {
+ System.out.println("DIFFERENT Key Format");
+ equal = false;
+ } else if (!Arrays.equals(k1.getEncoded(), k2.getEncoded())) {
+ System.out.println("DIFFERENT Key Encoding");
+ equal = false;
+ }
+ return equal;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestCICOWithGCM.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014374
+ * @summary Test basic CipherInputStream/OutputStream func w/ GCM mode.
+ * @author Valerie Peng
+ */
+
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.math.*;
+import java.io.*;
+import com.sun.crypto.provider.*;
+
+import java.util.*;
+
+public class TestCICOWithGCM extends UcryptoTest {
+ public static void main(String[] args) throws Exception {
+ main(new TestCICOWithGCM(), null);
+ }
+
+ public void doTest(Provider p) throws Exception {
+ // check if GCM support exists
+ try {
+ Cipher.getInstance("AES/GCM/NoPadding", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Test due to no GCM support");
+ return;
+ }
+
+ Random rdm = new Random();
+
+ //init Secret Key
+ byte[] keyValue = new byte[16];
+ rdm.nextBytes(keyValue);
+ SecretKey key = new SecretKeySpec(keyValue, "AES");
+
+ //do initialization of the plainText
+ byte[] plainText = new byte[800];
+ rdm.nextBytes(plainText);
+
+ //init ciphers
+ Cipher encCipher = Cipher.getInstance("AES/GCM/NoPadding", p);
+ encCipher.init(Cipher.ENCRYPT_MODE, key);
+ Cipher decCipher = Cipher.getInstance("AES/GCM/NoPadding", p);
+ decCipher.init(Cipher.DECRYPT_MODE, key, encCipher.getParameters());
+
+ //init cipher streams
+ ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
+ CipherInputStream ciInput = new CipherInputStream(baInput, encCipher);
+ ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
+ CipherOutputStream ciOutput = new CipherOutputStream(baOutput, decCipher);
+
+ //do test
+ byte[] buffer = new byte[800];
+ int len = ciInput.read(buffer);
+ System.out.println("read " + len + " bytes from input buffer");
+
+ while (len != -1) {
+ ciOutput.write(buffer, 0, len);
+ System.out.println("wite " + len + " bytes to output buffer");
+ len = ciInput.read(buffer);
+ if (len != -1) {
+ System.out.println("read " + len + " bytes from input buffer");
+ } else {
+ System.out.println("finished reading");
+ }
+ }
+
+ ciOutput.flush();
+ ciInput.close();
+ ciOutput.close();
+ byte[] recovered = baOutput.toByteArray();
+ System.out.println("recovered " + recovered.length + " bytes");
+ if (!Arrays.equals(plainText, recovered)) {
+ throw new RuntimeException("diff check failed!");
+ } else {
+ System.out.println("diff check passed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014374
+ * @summary Test CipherInputStream/OutputStream func w/ GCM mode and AAD.
+ * @author Valerie Peng
+ */
+
+import java.io.*;
+import java.security.*;
+import java.util.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class TestCICOWithGCMAndAAD extends UcryptoTest {
+ public static void main(String[] args) throws Exception {
+ main(new TestCICOWithGCMAndAAD(), null);
+ }
+
+ public void doTest(Provider p) throws Exception {
+ // check if GCM support exists
+ try {
+ Cipher.getInstance("AES/GCM/NoPadding", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Test due to no GCM support");
+ return;
+ }
+
+ Random rdm = new Random();
+
+ //init Secret Key
+ byte[] keyValue = new byte[16];
+ rdm.nextBytes(keyValue);
+ SecretKey key = new SecretKeySpec(keyValue, "AES");
+
+ //Do initialization of the plainText
+ byte[] plainText = new byte[400];
+ rdm.nextBytes(plainText);
+
+ byte[] aad = new byte[128];
+ rdm.nextBytes(aad);
+ byte[] aad2 = aad.clone();
+ aad2[50]++;
+
+ GCMParameterSpec spec = new GCMParameterSpec(128, new byte[16]);
+ Cipher encCipher = Cipher.getInstance("AES/GCM/NoPadding", p);
+ encCipher.init(Cipher.ENCRYPT_MODE, key, spec);
+ encCipher.updateAAD(aad);
+ Cipher decCipher = Cipher.getInstance("AES/GCM/NoPadding", p);
+ decCipher.init(Cipher.DECRYPT_MODE, key, spec); //encCipher.getParameters());
+ decCipher.updateAAD(aad);
+
+ byte[] recovered = test(encCipher, decCipher, plainText);
+ if (!Arrays.equals(plainText, recovered)) {
+ throw new Exception("sameAAD: diff check failed!");
+ } else System.out.println("sameAAD: passed");
+
+ encCipher.init(Cipher.ENCRYPT_MODE, key);
+ encCipher.updateAAD(aad2);
+ recovered = test(encCipher, decCipher, plainText);
+ if (recovered != null && recovered.length != 0) {
+ throw new Exception("diffAAD: no data should be returned!");
+ } else System.out.println("diffAAD: passed");
+ }
+
+ private static byte[] test(Cipher encCipher, Cipher decCipher, byte[] plainText)
+ throws Exception {
+ //init cipher streams
+ ByteArrayInputStream baInput = new ByteArrayInputStream(plainText);
+ CipherInputStream ciInput = new CipherInputStream(baInput, encCipher);
+ ByteArrayOutputStream baOutput = new ByteArrayOutputStream();
+ CipherOutputStream ciOutput = new CipherOutputStream(baOutput, decCipher);
+
+ //do test
+ byte[] buffer = new byte[200];
+ int len = ciInput.read(buffer);
+ System.out.println("read " + len + " bytes from input buffer");
+
+ while (len != -1) {
+ ciOutput.write(buffer, 0, len);
+ System.out.println("wite " + len + " bytes to output buffer");
+ len = ciInput.read(buffer);
+ if (len != -1) {
+ System.out.println("read " + len + " bytes from input buffer");
+ } else {
+ System.out.println("finished reading");
+ }
+ }
+
+ ciOutput.flush();
+ ciInput.close();
+ ciOutput.close();
+
+ return baOutput.toByteArray();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestDigest.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7088989
+ * @summary Ensure the various message digests works correctly
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class TestDigest extends UcryptoTest {
+
+ private static final String[] MD_ALGOS = {
+ "MD5",
+ "SHA",
+ "SHA-256",
+ "SHA-384",
+ "SHA-512"
+ };
+
+ public static void main(String[] args) throws Exception {
+ main(new TestDigest(), null);
+ }
+
+ public void doTest(Provider p) {
+ boolean testPassed = true;
+ byte[] msg = new byte[200];
+ (new SecureRandom()).nextBytes(msg);
+ String interopProvName = "SUN";
+
+ for (String a : MD_ALGOS) {
+ try {
+ MessageDigest md, md2;
+ try {
+ md = MessageDigest.getInstance(a, p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Unsupported MD algo: " + a);
+ continue;
+ }
+ md2 = MessageDigest.getInstance(a, interopProvName);
+ // Test Interoperability for update+digest calls
+ for (int i = 0; i < 3; i++) {
+ md.update(msg);
+ byte[] digest = md.digest();
+ md2.update(msg);
+ byte[] digest2 = md2.digest();
+ if (!Arrays.equals(digest, digest2)) {
+ System.out.println("DIFF1 FAILED for: " + a + " at iter " + i);
+ testPassed = false;
+ }
+ }
+
+ // Test Interoperability for digest calls
+ md = MessageDigest.getInstance(a, p);
+ md2 = MessageDigest.getInstance(a, interopProvName);
+
+ for (int i = 0; i < 3; i++) {
+ byte[] digest = md.digest();
+ byte[] digest2 = md2.digest();
+ if (!Arrays.equals(digest, digest2)) {
+ System.out.println("DIFF2 FAILED for: " + a + " at iter " + i);
+ testPassed = false;
+ }
+ }
+
+ // Test Cloning functionality
+ md = MessageDigest.getInstance(a, p);
+ md2 = (MessageDigest) md.clone(); // clone right after construction
+ byte[] digest = md.digest();
+ byte[] digest2 = md2.digest();
+ if (!Arrays.equals(digest, digest2)) {
+ System.out.println("DIFF-3.1 FAILED for: " + a);
+ testPassed = false;
+ }
+ md.update(msg);
+ md2 = (MessageDigest) md.clone(); // clone again after update call
+ digest = md.digest();
+ digest2 = md2.digest();
+ if (!Arrays.equals(digest, digest2)) {
+ System.out.println("DIFF-3.2 FAILED for: " + a);
+ testPassed = false;
+ }
+ md2 = (MessageDigest) md.clone(); // clone after digest
+ digest = md.digest();
+ digest2 = md2.digest();
+ if (!Arrays.equals(digest, digest2)) {
+ System.out.println("DIFF-3.3 FAILED for: " + a);
+ testPassed = false;
+ }
+ } catch(Exception ex) {
+ System.out.println("Unexpected Exception: " + a);
+ ex.printStackTrace();
+ testPassed = false;
+ }
+ }
+ if (!testPassed) {
+ throw new RuntimeException("One or more MD test failed!");
+ } else {
+ System.out.println("MD Tests Passed");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014374
+ * @summary Ensure that same key+iv can't be repeatedly used for encryption.
+ * @author Valerie Peng
+ */
+
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.math.*;
+import com.sun.crypto.provider.*;
+
+import java.util.*;
+
+public class TestGCMKeyAndIvCheck extends UcryptoTest {
+
+ private static final byte[] AAD = new byte[5];
+ private static final byte[] PT = new byte[33];
+
+ private static void checkISE(Cipher c) throws Exception {
+ // Subsequent encryptions should fail
+ try {
+ c.updateAAD(AAD);
+ throw new Exception("Should throw ISE for updateAAD()");
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+
+ try {
+ c.update(PT);
+ throw new Exception("Should throw ISE for update()");
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ try {
+ c.doFinal(PT);
+ throw new Exception("Should throw ISE for doFinal()");
+ } catch (IllegalStateException ise) {
+ // expected
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ main(new TestGCMKeyAndIvCheck(), null);
+ }
+
+ public void doTest(Provider p) throws Exception {
+ Cipher c;
+ try {
+ c = Cipher.getInstance("AES/GCM/NoPadding", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Test due to No GCM support");
+ return;
+ }
+
+ SecretKey key = new SecretKeySpec(new byte[16], "AES");
+ // First try parameter-less init.
+ c.init(Cipher.ENCRYPT_MODE, key);
+ c.updateAAD(AAD);
+ byte[] ctPlusTag = c.doFinal(PT);
+
+ // subsequent encryption should fail unless re-init w/ different key+iv
+ checkISE(c);
+
+ // Validate the retrieved parameters against the IV and tag length.
+ AlgorithmParameters params = c.getParameters();
+ if (params == null) {
+ throw new Exception("getParameters() should not return null");
+ }
+ GCMParameterSpec spec = params.getParameterSpec(GCMParameterSpec.class);
+ if (spec.getTLen() != (ctPlusTag.length - PT.length)*8) {
+ throw new Exception("Parameters contains incorrect TLen value");
+ }
+ if (!Arrays.equals(spec.getIV(), c.getIV())) {
+ throw new Exception("Parameters contains incorrect IV value");
+ }
+
+ // Should be ok to use the same key+iv for decryption
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ c.updateAAD(AAD);
+ byte[] recovered = c.doFinal(ctPlusTag);
+ if (!Arrays.equals(recovered, PT)) {
+ throw new Exception("decryption result mismatch");
+ }
+
+ // Now try to encrypt again using the same key+iv; should fail also
+ try {
+ c.init(Cipher.ENCRYPT_MODE, key, params);
+ throw new Exception("Should throw exception when same key+iv is used");
+ } catch (InvalidAlgorithmParameterException iape) {
+ // expected
+ }
+
+ // Now try to encrypt again using parameter-less init; should work
+ c.init(Cipher.ENCRYPT_MODE, key);
+ c.doFinal(PT);
+
+ // make sure a different iv is used
+ byte[] iv = c.getIV();
+ if (Arrays.equals(spec.getIV(), iv)) {
+ throw new Exception("IV should be different now");
+ }
+
+ // Now try to encrypt again using a different parameter; should work
+ c.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, new byte[30]));
+ c.updateAAD(AAD);
+ c.doFinal(PT);
+ // subsequent encryption should fail unless re-init w/ different key+iv
+ checkISE(c);
+
+ // Now try decryption twice in a row; no re-init required and
+ // same parameters is used.
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ c.updateAAD(AAD);
+ recovered = c.doFinal(ctPlusTag);
+
+ c.updateAAD(AAD);
+ recovered = c.doFinal(ctPlusTag);
+ if (!Arrays.equals(recovered, PT)) {
+ throw new Exception("decryption result mismatch");
+ }
+
+ // Now try decryption again and re-init using the same parameters
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ c.updateAAD(AAD);
+ recovered = c.doFinal(ctPlusTag);
+
+ // init to decrypt w/o parameters; should fail with IKE as
+ // javadoc specified
+ try {
+ c.init(Cipher.DECRYPT_MODE, key);
+ throw new Exception("Should throw IKE for dec w/o params");
+ } catch (InvalidKeyException ike) {
+ // expected
+ }
+
+ // Lastly, try encryption AND decryption w/ wrong type of parameters,
+ // e.g. IvParameterSpec
+ try {
+ c.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
+ throw new Exception("Should throw IAPE");
+ } catch (InvalidAlgorithmParameterException iape) {
+ // expected
+ }
+ try {
+ c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
+ throw new Exception("Should throw IAPE");
+ } catch (InvalidAlgorithmParameterException iape) {
+ // expected
+ }
+
+ System.out.println("Test Passed!");
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestGCMKeyWrap.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014374
+ * @summary Ensure key wrap/unwrap works using AES/GCM/NoPadding
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class TestGCMKeyWrap extends UcryptoTest {
+
+ public static void main(String[] args) throws Exception {
+ main(new TestGCMKeyWrap(), null);
+ }
+
+ public void doTest(Provider p) throws Exception {
+ // check if GCM support exists
+ try {
+ Cipher.getInstance("AES/GCM/NoPadding", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Test due to no GCM support");
+ return;
+ }
+
+ Random rdm = new Random();
+
+ //init Secret Key
+ byte[] keyValue = new byte[16];
+ rdm.nextBytes(keyValue);
+ SecretKey key = new SecretKeySpec(keyValue, "AES");
+
+ Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", p);
+ cipher.init(Cipher.WRAP_MODE, key);
+
+ byte[] wrappedKey = cipher.wrap(key);
+
+ try { // make sure ISE is thrown if re-using the same key/IV
+ wrappedKey = cipher.wrap(key);
+ throw new Exception("FAIL: expected ISE not thrown");
+ } catch(IllegalStateException ise){
+ System.out.println("Expected ISE thrown for re-wrapping");
+ }
+
+ //unwrap the key
+ AlgorithmParameters params = cipher.getParameters();
+ cipher.init(Cipher.UNWRAP_MODE, key, params);
+ Key unwrappedKey = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
+
+ //check if we can unwrap second time
+ unwrappedKey = cipher.unwrap(wrappedKey, "AES", Cipher.SECRET_KEY);
+
+ // Comparison
+ if (!Arrays.equals(key.getEncoded(), unwrappedKey.getEncoded())) {
+ throw new Exception("FAIL: keys are not equal");
+ } else {
+ System.out.println("Passed key equality check");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestGCMWithSBE.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8036970
+ * @summary Ensure that Cipher object is still usable after SBE.
+ * @author Valerie Peng
+ */
+
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.math.*;
+import com.sun.crypto.provider.*;
+
+import java.util.*;
+
+public class TestGCMWithSBE extends UcryptoTest {
+
+ private static final byte[] PT = new byte[32];
+ private static final byte[] ONE_BYTE = new byte[1];
+
+ public static void main(String[] args) throws Exception {
+ main(new TestGCMWithSBE(), null);
+ }
+
+ public void doTest(Provider p) throws Exception {
+ Cipher c;
+ try {
+ c = Cipher.getInstance("AES/GCM/NoPadding", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Test due to No GCM support");
+ return;
+ }
+
+ SecretKey key = new SecretKeySpec(new byte[16], "AES");
+ c.init(Cipher.ENCRYPT_MODE, key);
+
+ // test SBE with update calls
+ byte[] ct1 = null;
+ try {
+ c.update(PT, 0, PT.length, ONE_BYTE);
+ } catch (ShortBufferException sbe) {
+ // retry should work
+ ct1 = c.update(PT, 0, PT.length);
+ }
+
+ byte[] ct2PlusTag = null;
+ // test SBE with doFinal calls
+ try {
+ c.doFinal(ONE_BYTE, 0);
+ } catch (ShortBufferException sbe) {
+ // retry should work
+ ct2PlusTag = c.doFinal();
+ }
+
+ // Validate the retrieved parameters against the IV and tag length.
+ AlgorithmParameters params = c.getParameters();
+ if (params == null) {
+ throw new Exception("getParameters() should not return null");
+ }
+ GCMParameterSpec spec = params.getParameterSpec(GCMParameterSpec.class);
+ if (spec.getTLen() != (ct1.length + ct2PlusTag.length - PT.length)*8) {
+ throw new Exception("Parameters contains incorrect TLen value");
+ }
+ if (!Arrays.equals(spec.getIV(), c.getIV())) {
+ throw new Exception("Parameters contains incorrect IV value");
+ }
+
+ // Should be ok to use the same key+iv for decryption
+ c.init(Cipher.DECRYPT_MODE, key, params);
+ byte[] pt1 = c.update(ct1);
+ if (pt1 != null && pt1.length != 0) {
+ throw new Exception("Recovered text should not be returned "
+ + "to caller before tag verification");
+ }
+
+ byte[] pt2 = null;
+ try {
+ c.doFinal(ct2PlusTag, 0, ct2PlusTag.length, ONE_BYTE);
+ } catch (ShortBufferException sbe) {
+ // retry should work
+ pt2 = c.doFinal(ct2PlusTag);
+ }
+ if (!Arrays.equals(pt2, PT)) {
+ throw new Exception("decryption result mismatch");
+ }
+
+ System.out.println("Test Passed!");
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestKATForGCM.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8014374
+ * @summary Known Answer Test for AES cipher with GCM mode
+ * @author Valerie Peng
+ */
+
+import java.security.*;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.math.*;
+
+import java.util.*;
+
+public class TestKATForGCM extends UcryptoTest {
+ public static void main(String[] args) throws Exception {
+ main(new TestKATForGCM(), null);
+ }
+
+ // Utility methods
+ private static byte[] HexToBytes(String hexVal) {
+ if (hexVal == null) return new byte[0];
+ byte[] result = new byte[hexVal.length()/2];
+ for (int i = 0; i < result.length; i++) {
+ // 2 characters at a time
+ String byteVal = hexVal.substring(2*i, 2*i +2);
+ result[i] = Integer.valueOf(byteVal, 16).byteValue();
+ }
+ return result;
+ }
+
+ private static class TestVector {
+ SecretKey key;
+ byte[] plainText;
+ byte[] aad;
+ byte[] cipherText;
+ byte[] tag;
+ GCMParameterSpec spec;
+ String info;
+
+ TestVector(String key, String iv, String pt, String aad,
+ String ct, String tag) {
+ this.key = new SecretKeySpec(HexToBytes(key), "AES");
+ this.plainText = HexToBytes(pt);
+ this.aad = HexToBytes(aad);
+ this.cipherText = HexToBytes(ct);
+ this.tag = HexToBytes(tag);
+ this.spec = new GCMParameterSpec(this.tag.length * 8, HexToBytes(iv));
+ this.info = "key=" + key + ", iv=" + iv + ", pt=" + pt +
+ ",aad=" + aad + ", ct=" + ct + ", tag=" + tag;
+ }
+
+ public String toString() {
+ return info;
+ }
+ }
+
+ // These test vectors are found off NIST's CAVP page
+ // http://csrc.nist.gov/groups/STM/cavp/index.html
+ // inside the link named "GCM Test Vectors", i.e.
+ // http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip
+ // CAVS 14.0, set of test vectors w/ count = 0, keysize = 128
+ private static TestVector[] testValues = {
+ // 96-bit iv w/ 128/120/112/104/96-bit tags
+ // no plain text, no aad
+ new TestVector("11754cd72aec309bf52f7687212e8957",
+ "3c819d9a9bed087615030b65",
+ null, null, null,
+ "250327c674aaf477aef2675748cf6971"),
+ new TestVector("272f16edb81a7abbea887357a58c1917",
+ "794ec588176c703d3d2a7a07",
+ null, null, null,
+ "b6e6f197168f5049aeda32dafbdaeb"),
+ new TestVector("81b6844aab6a568c4556a2eb7eae752f",
+ "ce600f59618315a6829bef4d",
+ null, null, null,
+ "89b43e9dbc1b4f597dbbc7655bb5"),
+ new TestVector("cde2f9a9b1a004165ef9dc981f18651b",
+ "29512c29566c7322e1e33e8e",
+ null, null, null,
+ "2e58ce7dabd107c82759c66a75"),
+ new TestVector("b01e45cc3088aaba9fa43d81d481823f",
+ "5a2c4a66468713456a4bd5e1",
+ null, null, null,
+ "014280f944f53c681164b2ff"),
+ // 96-bit iv w/ 128/120/112/104/96-bit tags
+ // no plain text, 16-byte aad
+ new TestVector("77be63708971c4e240d1cb79e8d77feb",
+ "e0e00f19fed7ba0136a797f3",
+ null,
+ "7a43ec1d9c0a5a78a0b16533a6213cab",
+ null,
+ "209fcc8d3675ed938e9c7166709dd946"),
+ new TestVector("da0b615656135194ba6d3c851099bc48",
+ "d39d4b4d3cc927885090e6c3",
+ null,
+ "e7e5e6f8dac913036cb2ff29e8625e0e",
+ null,
+ "ab967711a5770461724460b07237e2"),
+ new TestVector("7e0986937a88eef894235aba4a2f43b2",
+ "92c4a631695907166b422d60",
+ null,
+ "85c185f8518f9f2cd597a8f9208fc76b",
+ null,
+ "3bb916b728df94fe9d1916736be1"),
+ new TestVector("c3db570d7f0c21e86b028f11465d1dc9",
+ "f86970f58ceef89fc7cb679e",
+ null,
+ "c095240708c0f57c288d86090ae34ee1",
+ null,
+ "e043c52160d652e82c7262fcf4"),
+ new TestVector("bea48ae4980d27f357611014d4486625",
+ "32bddb5c3aa998a08556454c",
+ null,
+ "8a50b0b8c7654bced884f7f3afda2ead",
+ null,
+ "8e0f6d8bf05ffebe6f500eb1"),
+ // 96-bit iv w/ 128/120/112/104/96-bit tags
+ // no plain text, 20-byte aad
+ new TestVector("2fb45e5b8f993a2bfebc4b15b533e0b4",
+ "5b05755f984d2b90f94b8027",
+ null,
+ "e85491b2202caf1d7dce03b97e09331c32473941",
+ null,
+ "c75b7832b2a2d9bd827412b6ef5769db"),
+ new TestVector("9bf406339fcef9675bbcf156aa1a0661",
+ "8be4a9543d40f542abacac95",
+ null,
+ "7167cbf56971793186333a6685bbd58d47d379b3",
+ null,
+ "5e7968d7bbd5ba58cfcc750e2ef8f1"),
+ new TestVector("a2e962fff70fd0f4d63be728b80556fc",
+ "1fa7103483de43d09bc23db4",
+ null,
+ "2a58edf1d53f46e4e7ee5e77ee7aeb60fc360658",
+ null,
+ "fa37f2dbbefab1451eae1d0d74ca"),
+ new TestVector("6bf4fdce82926dcdfc52616ed5f23695",
+ "cc0f5899a10615567e1193ed",
+ null,
+ "3340655592374c1da2f05aac3ee111014986107f",
+ null,
+ "8ad3385cce3b5e7c985908192c"),
+ new TestVector("4df7a13e43c3d7b66b1a72fac5ba398e",
+ "97179a3a2d417908dcf0fb28",
+ null,
+ "cbb7fc0010c255661e23b07dbd804b1e06ae70ac",
+ null,
+ "37791edae6c137ea946cfb40"),
+ // 96-bit iv w/ 128-bit tags, 13/16/32/51-byte plain text, no aad
+ new TestVector("fe9bb47deb3a61e423c2231841cfd1fb",
+ "4d328eb776f500a2f7fb47aa",
+ "f1cc3818e421876bb6b8bbd6c9",
+ null,
+ "b88c5c1977b35b517b0aeae967",
+ "43fd4727fe5cdb4b5b42818dea7ef8c9"),
+ new TestVector("7fddb57453c241d03efbed3ac44e371c",
+ "ee283a3fc75575e33efd4887",
+ "d5de42b461646c255c87bd2962d3b9a2",
+ null,
+ "2ccda4a5415cb91e135c2a0f78c9b2fd",
+ "b36d1df9b9d5e596f83e8b7f52971cb3"),
+ new TestVector("9971071059abc009e4f2bd69869db338",
+ "07a9a95ea3821e9c13c63251",
+ "f54bc3501fed4f6f6dfb5ea80106df0bd836e6826225b75c0222f6e859b35983",
+ null,
+ "0556c159f84ef36cb1602b4526b12009c775611bffb64dc0d9ca9297cd2c6a01",
+ "7870d9117f54811a346970f1de090c41"),
+ new TestVector("594157ec4693202b030f33798b07176d",
+ "49b12054082660803a1df3df",
+
+"3feef98a976a1bd634f364ac428bb59cd51fb159ec1789946918dbd50ea6c9d594a3a31a5269b0da6936c29d063a5fa2cc8a1c",
+ null,
+
+"c1b7a46a335f23d65b8db4008a49796906e225474f4fe7d39e55bf2efd97fd82d4167de082ae30fa01e465a601235d8d68bc69",
+ "ba92d3661ce8b04687e8788d55417dc2"),
+ // 96-bit iv w/ 128-bit tags, 16-byte plain text, 16/20/48/90-byte aad
+ new TestVector("c939cc13397c1d37de6ae0e1cb7c423c",
+ "b3d8cc017cbb89b39e0f67e2",
+ "c3b3c41f113a31b73d9a5cd432103069",
+ "24825602bd12a984e0092d3e448eda5f",
+ "93fe7d9e9bfd10348a5606e5cafa7354",
+ "0032a1dc85f1c9786925a2e71d8272dd"),
+ new TestVector("d4a22488f8dd1d5c6c19a7d6ca17964c",
+ "f3d5837f22ac1a0425e0d1d5",
+ "7b43016a16896497fb457be6d2a54122",
+ "f1c5d424b83f96c6ad8cb28ca0d20e475e023b5a",
+ "c2bd67eef5e95cac27e3b06e3031d0a8",
+ "f23eacf9d1cdf8737726c58648826e9c"),
+ new TestVector("89850dd398e1f1e28443a33d40162664",
+ "e462c58482fe8264aeeb7231",
+ "2805cdefb3ef6cc35cd1f169f98da81a",
+"d74e99d1bdaa712864eec422ac507bddbe2b0d4633cd3dff29ce5059b49fe868526c59a2a3a604457bc2afea866e7606",
+ "ba80e244b7fc9025cd031d0f63677e06",
+ "d84a8c3eac57d1bb0e890a8f461d1065"),
+ new TestVector("bd7c5c63b7542b56a00ebe71336a1588",
+ "87721f23ba9c3c8ea5571abc",
+ "de15ddbb1e202161e8a79af6a55ac6f3",
+"a6ec8075a0d3370eb7598918f3b93e48444751624997b899a87fa6a9939f844e008aa8b70e9f4c3b1a19d3286bf543e7127bfecba1ad17a5ec53fccc26faecacc4c75369498eaa7d706aef634d0009279b11e4ba6c993e5e9ed9",
+ "41eb28c0fee4d762de972361c863bc80",
+ "9cb567220d0b252eb97bff46e4b00ff8"),
+ // 8/1024-bit iv w/ 128-bit tag, no plain text, no aad
+ new TestVector("1672c3537afa82004c6b8a46f6f0d026",
+ "05",
+ null, null, null,
+ "8e2ad721f9455f74d8b53d3141f27e8e"),
+ new TestVector("d0f1f4defa1e8c08b4b26d576392027c",
+"42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
+ null, null, null,
+ "7ab49b57ddf5f62c427950111c5c4f0d"),
+ // 8-bit iv w/ 128-bit tag, 13-byte plain text, 90-byte aad
+ new TestVector("9f79239f0904eace50784b863e723f6b",
+ "d9",
+ "bdb0bb10c87965acd34d146171",
+"44db436089327726c5f01139e1f339735c9e85514ccc2f167bad728010fb34a9072a9794c8a5e7361b1d0dbcdc9ac4091e354bb2896561f0486645252e9c78c86beece91bfa4f7cc4a8794ce1f305b1b735efdbf1ed1563c0be0",
+ "7e5a7c8dadb3f0c7335b4d9d8d",
+ "6b6ef1f53723a89f3bb7c6d043840717"),
+ // 1024-bit iv w/ 128-bit tag, 51-byte plain text, 48-byte aad
+ new TestVector("141f1ce91989b07e7eb6ae1dbd81ea5e",
+
+"49451da24bd6074509d3cebc2c0394c972e6934b45a1d91f3ce1d3ca69e194aa1958a7c21b6f21d530ce6d2cc5256a3f846b6f9d2f38df0102c4791e57df038f6e69085646007df999751e248e06c47245f4cd3b8004585a7470dee1690e9d2d63169a58d243c0b57b3e5b4a481a3e4e8c60007094ef3adea2e8f05dd3a1396f",
+"d384305af2388699aa302f510913fed0f2cb63ba42efa8c5c9de2922a2ec2fe87719dadf1eb0aef212b51e74c9c5b934104a43",
+"630cf18a91cc5a6481ac9eefd65c24b1a3c93396bd7294d6b8ba323951727666c947a21894a079ef061ee159c05beeb4",
+"f4c34e5fbe74c0297313268296cd561d59ccc95bbfcdfcdc71b0097dbd83240446b28dc088abd42b0fc687f208190ff24c0548",
+ "dbb93bbb56d0439cd09f620a57687f5d"),
+ };
+
+ public void doTest(Provider p) throws Exception {
+ boolean testFailed = false;
+ Cipher c = null;
+ try {
+ c = Cipher.getInstance("AES/GCM/NoPadding", p);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping Test due to no GCM support");
+ return;
+ }
+
+ for (int i = 0; i < testValues.length; i++) {
+ try {
+ c.init(Cipher.ENCRYPT_MODE, testValues[i].key, testValues[i].spec);
+ c.updateAAD(testValues[i].aad);
+ byte[] ctPlusTag = c.doFinal(testValues[i].plainText);
+
+ c.init(Cipher.DECRYPT_MODE, testValues[i].key, testValues[i].spec);
+ c.updateAAD(testValues[i].aad);
+ byte[] pt = c.doFinal(ctPlusTag); // should fail if tag mismatched
+
+ // check encryption/decryption results just to be sure
+ if (!Arrays.equals(testValues[i].plainText, pt)) {
+ System.out.println("PlainText diff failed for test# " + i);
+ testFailed = true;
+ }
+ int ctLen = testValues[i].cipherText.length;
+ if (!Arrays.equals(testValues[i].cipherText,
+ Arrays.copyOf(ctPlusTag, ctLen))) {
+ System.out.println("CipherText diff failed for test# " + i);
+ testFailed = true;
+ }
+ int tagLen = testValues[i].tag.length;
+ if (!Arrays.equals
+ (testValues[i].tag,
+ Arrays.copyOfRange(ctPlusTag, ctLen, ctLen+tagLen))) {
+ System.out.println("Tag diff failed for test# " + i);
+ testFailed = true;
+ }
+ } catch (Exception ex) {
+ // continue testing other test vectors
+ System.out.println("Failed Test Vector: " + testValues[i]);
+ ex.printStackTrace();
+ testFailed = true;
+ continue;
+ }
+ }
+ if (testFailed) {
+ throw new Exception("Test Failed");
+ }
+ // passed all tests...hooray!
+ System.out.println("Test Passed");
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestMalformedRSA.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8024606
+ * @summary NegativeArraySizeException in NativeRSACipher
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import java.math.*;
+import javax.crypto.*;
+
+public class TestMalformedRSA extends UcryptoTest {
+
+ // KAT
+ private static final byte PLAINTEXT[] = Arrays.copyOf
+ (new String("Known plaintext message utilized" +
+ "for RSA Encryption & Decryption" +
+ "block, SHA1, SHA256, SHA384 and" +
+ "SHA512 RSA Signature KAT tests.").getBytes(), 128);
+
+ private static final byte MOD[] = {
+ (byte)0xd5, (byte)0x84, (byte)0x95, (byte)0x07, (byte)0xf4, (byte)0xd0,
+ (byte)0x1f, (byte)0x82, (byte)0xf3, (byte)0x79, (byte)0xf4, (byte)0x99,
+ (byte)0x48, (byte)0x10, (byte)0xe1, (byte)0x71, (byte)0xa5, (byte)0x62,
+ (byte)0x22, (byte)0xa3, (byte)0x4b, (byte)0x00, (byte)0xe3, (byte)0x5b,
+ (byte)0x3a, (byte)0xcc, (byte)0x10, (byte)0x83, (byte)0xe0, (byte)0xaf,
+ (byte)0x61, (byte)0x13, (byte)0x54, (byte)0x6a, (byte)0xa2, (byte)0x6a,
+ (byte)0x2c, (byte)0x5e, (byte)0xb3, (byte)0xcc, (byte)0xa3, (byte)0x71,
+ (byte)0x9a, (byte)0xb2, (byte)0x3e, (byte)0x78, (byte)0xec, (byte)0xb5,
+ (byte)0x0e, (byte)0x6e, (byte)0x31, (byte)0x3b, (byte)0x77, (byte)0x1f,
+ (byte)0x6e, (byte)0x94, (byte)0x41, (byte)0x60, (byte)0xd5, (byte)0x6e,
+ (byte)0xd9, (byte)0xc6, (byte)0xf9, (byte)0x29, (byte)0xc3, (byte)0x40,
+ (byte)0x36, (byte)0x25, (byte)0xdb, (byte)0xea, (byte)0x0b, (byte)0x07,
+ (byte)0xae, (byte)0x76, (byte)0xfd, (byte)0x99, (byte)0x29, (byte)0xf4,
+ (byte)0x22, (byte)0xc1, (byte)0x1a, (byte)0x8f, (byte)0x05, (byte)0xfe,
+ (byte)0x98, (byte)0x09, (byte)0x07, (byte)0x05, (byte)0xc2, (byte)0x0f,
+ (byte)0x0b, (byte)0x11, (byte)0x83, (byte)0x39, (byte)0xca, (byte)0xc7,
+ (byte)0x43, (byte)0x63, (byte)0xff, (byte)0x33, (byte)0x80, (byte)0xe7,
+ (byte)0xc3, (byte)0x78, (byte)0xae, (byte)0xf1, (byte)0x73, (byte)0x52,
+ (byte)0x98, (byte)0x1d, (byte)0xde, (byte)0x5c, (byte)0x53, (byte)0x6e,
+ (byte)0x01, (byte)0x73, (byte)0x0d, (byte)0x12, (byte)0x7e, (byte)0x77,
+ (byte)0x03, (byte)0xf1, (byte)0xef, (byte)0x1b, (byte)0xc8, (byte)0xa8,
+ (byte)0x0f, (byte)0x97
+ };
+
+ private static final byte PUB_EXP[] = {(byte)0x01, (byte)0x00, (byte)0x01};
+
+ private static final byte PRIV_EXP[] = {
+ (byte)0x85, (byte)0x27, (byte)0x47, (byte)0x61, (byte)0x4c, (byte)0xd4,
+ (byte)0xb5, (byte)0xb2, (byte)0x0e, (byte)0x70, (byte)0x91, (byte)0x8f,
+ (byte)0x3d, (byte)0x97, (byte)0xf9, (byte)0x5f, (byte)0xcc, (byte)0x09,
+ (byte)0x65, (byte)0x1c, (byte)0x7c, (byte)0x5b, (byte)0xb3, (byte)0x6d,
+ (byte)0x63, (byte)0x3f, (byte)0x7b, (byte)0x55, (byte)0x22, (byte)0xbb,
+ (byte)0x7c, (byte)0x48, (byte)0x77, (byte)0xae, (byte)0x80, (byte)0x56,
+ (byte)0xc2, (byte)0x10, (byte)0xd5, (byte)0x03, (byte)0xdb, (byte)0x31,
+ (byte)0xaf, (byte)0x8d, (byte)0x54, (byte)0xd4, (byte)0x48, (byte)0x99,
+ (byte)0xa8, (byte)0xc4, (byte)0x23, (byte)0x43, (byte)0xb8, (byte)0x48,
+ (byte)0x0b, (byte)0xc7, (byte)0xbc, (byte)0xf5, (byte)0xcc, (byte)0x64,
+ (byte)0x72, (byte)0xbf, (byte)0x59, (byte)0x06, (byte)0x04, (byte)0x1c,
+ (byte)0x32, (byte)0xf5, (byte)0x14, (byte)0x2e, (byte)0x6e, (byte)0xe2,
+ (byte)0x0f, (byte)0x5c, (byte)0xde, (byte)0x36, (byte)0x3c, (byte)0x6e,
+ (byte)0x7c, (byte)0x4d, (byte)0xcc, (byte)0xd3, (byte)0x00, (byte)0x6e,
+ (byte)0xe5, (byte)0x45, (byte)0x46, (byte)0xef, (byte)0x4d, (byte)0x25,
+ (byte)0x46, (byte)0x6d, (byte)0x7f, (byte)0xed, (byte)0xbb, (byte)0x4f,
+ (byte)0x4d, (byte)0x9f, (byte)0xda, (byte)0x87, (byte)0x47, (byte)0x8f,
+ (byte)0x74, (byte)0x44, (byte)0xb7, (byte)0xbe, (byte)0x9d, (byte)0xf5,
+ (byte)0xdd, (byte)0xd2, (byte)0x4c, (byte)0xa5, (byte)0xab, (byte)0x74,
+ (byte)0xe5, (byte)0x29, (byte)0xa1, (byte)0xd2, (byte)0x45, (byte)0x3b,
+ (byte)0x33, (byte)0xde, (byte)0xd5, (byte)0xae, (byte)0xf7, (byte)0x03,
+ (byte)0x10, (byte)0x21
+ };
+
+ private static final byte PRIME_P[] = {
+ (byte)0xf9, (byte)0x74, (byte)0x8f, (byte)0x16, (byte)0x02, (byte)0x6b,
+ (byte)0xa0, (byte)0xee, (byte)0x7f, (byte)0x28, (byte)0x97, (byte)0x91,
+ (byte)0xdc, (byte)0xec, (byte)0xc0, (byte)0x7c, (byte)0x49, (byte)0xc2,
+ (byte)0x85, (byte)0x76, (byte)0xee, (byte)0x66, (byte)0x74, (byte)0x2d,
+ (byte)0x1a, (byte)0xb8, (byte)0xf7, (byte)0x2f, (byte)0x11, (byte)0x5b,
+ (byte)0x36, (byte)0xd8, (byte)0x46, (byte)0x33, (byte)0x3b, (byte)0xd8,
+ (byte)0xf3, (byte)0x2d, (byte)0xa1, (byte)0x03, (byte)0x83, (byte)0x2b,
+ (byte)0xec, (byte)0x35, (byte)0x43, (byte)0x32, (byte)0xff, (byte)0xdd,
+ (byte)0x81, (byte)0x7c, (byte)0xfd, (byte)0x65, (byte)0x13, (byte)0x04,
+ (byte)0x7c, (byte)0xfc, (byte)0x03, (byte)0x97, (byte)0xf0, (byte)0xd5,
+ (byte)0x62, (byte)0xdc, (byte)0x0d, (byte)0xbf
+ };
+
+ private static final byte PRIME_Q[] = {
+ (byte)0xdb, (byte)0x1e, (byte)0xa7, (byte)0x3d, (byte)0xe7, (byte)0xfa,
+ (byte)0x8b, (byte)0x04, (byte)0x83, (byte)0x48, (byte)0xf3, (byte)0xa5,
+ (byte)0x31, (byte)0x9d, (byte)0x35, (byte)0x5e, (byte)0x4d, (byte)0x54,
+ (byte)0x77, (byte)0xcc, (byte)0x84, (byte)0x09, (byte)0xf3, (byte)0x11,
+ (byte)0x0d, (byte)0x54, (byte)0xed, (byte)0x85, (byte)0x39, (byte)0xa9,
+ (byte)0xca, (byte)0xa8, (byte)0xea, (byte)0xae, (byte)0x19, (byte)0x9c,
+ (byte)0x75, (byte)0xdb, (byte)0x88, (byte)0xb8, (byte)0x04, (byte)0x8d,
+ (byte)0x54, (byte)0xc6, (byte)0xa4, (byte)0x80, (byte)0xf8, (byte)0x93,
+ (byte)0xf0, (byte)0xdb, (byte)0x19, (byte)0xef, (byte)0xd7, (byte)0x87,
+ (byte)0x8a, (byte)0x8f, (byte)0x5a, (byte)0x09, (byte)0x2e, (byte)0x54,
+ (byte)0xf3, (byte)0x45, (byte)0x24, (byte)0x29
+ };
+
+ private static final byte EXP_P[] = {
+ (byte)0x6a, (byte)0xd1, (byte)0x25, (byte)0x80, (byte)0x18, (byte)0x33,
+ (byte)0x3c, (byte)0x2b, (byte)0x44, (byte)0x19, (byte)0xfe, (byte)0xa5,
+ (byte)0x40, (byte)0x03, (byte)0xc4, (byte)0xfc, (byte)0xb3, (byte)0x9c,
+ (byte)0xef, (byte)0x07, (byte)0x99, (byte)0x58, (byte)0x17, (byte)0xc1,
+ (byte)0x44, (byte)0xa3, (byte)0x15, (byte)0x7d, (byte)0x7b, (byte)0x22,
+ (byte)0x22, (byte)0xdf, (byte)0x03, (byte)0x58, (byte)0x66, (byte)0xf5,
+ (byte)0x24, (byte)0x54, (byte)0x52, (byte)0x91, (byte)0x2d, (byte)0x76,
+ (byte)0xfe, (byte)0x63, (byte)0x64, (byte)0x4e, (byte)0x0f, (byte)0x50,
+ (byte)0x2b, (byte)0x65, (byte)0x79, (byte)0x1f, (byte)0xf1, (byte)0xbf,
+ (byte)0xc7, (byte)0x41, (byte)0x26, (byte)0xcc, (byte)0xc6, (byte)0x1c,
+ (byte)0xa9, (byte)0x83, (byte)0x6f, (byte)0x03
+ };
+
+ private static final byte EXP_Q[] = {
+ (byte)0x12, (byte)0x84, (byte)0x1a, (byte)0x99, (byte)0xce, (byte)0x9a,
+ (byte)0x8b, (byte)0x58, (byte)0xcc, (byte)0x47, (byte)0x43, (byte)0xdf,
+ (byte)0x77, (byte)0xbb, (byte)0xd3, (byte)0x20, (byte)0xae, (byte)0xe4,
+ (byte)0x2e, (byte)0x63, (byte)0x67, (byte)0xdc, (byte)0xf7, (byte)0x5f,
+ (byte)0x3f, (byte)0x83, (byte)0x27, (byte)0xb7, (byte)0x14, (byte)0x52,
+ (byte)0x56, (byte)0xbf, (byte)0xc3, (byte)0x65, (byte)0x06, (byte)0xe1,
+ (byte)0x03, (byte)0xcc, (byte)0x93, (byte)0x57, (byte)0x09, (byte)0x7b,
+ (byte)0x6f, (byte)0xe8, (byte)0x81, (byte)0x4a, (byte)0x2c, (byte)0xb7,
+ (byte)0x43, (byte)0xa9, (byte)0x20, (byte)0x1d, (byte)0xf6, (byte)0x56,
+ (byte)0x8b, (byte)0xcc, (byte)0xe5, (byte)0x4c, (byte)0xd5, (byte)0x4f,
+ (byte)0x74, (byte)0x67, (byte)0x29, (byte)0x51
+ };
+
+ private static final byte CRT_COEFF[] = {
+ (byte)0x23, (byte)0xab, (byte)0xf4, (byte)0x03, (byte)0x2f, (byte)0x29,
+ (byte)0x95, (byte)0x74, (byte)0xac, (byte)0x1a, (byte)0x33, (byte)0x96,
+ (byte)0x62, (byte)0xed, (byte)0xf7, (byte)0xf6, (byte)0xae, (byte)0x07,
+ (byte)0x2a, (byte)0x2e, (byte)0xe8, (byte)0xab, (byte)0xfb, (byte)0x1e,
+ (byte)0xb9, (byte)0xb2, (byte)0x88, (byte)0x1e, (byte)0x85, (byte)0x05,
+ (byte)0x42, (byte)0x64, (byte)0x03, (byte)0xb2, (byte)0x8b, (byte)0xc1,
+ (byte)0x81, (byte)0x75, (byte)0xd7, (byte)0xba, (byte)0xaa, (byte)0xd4,
+ (byte)0x31, (byte)0x3c, (byte)0x8a, (byte)0x96, (byte)0x23, (byte)0x9d,
+ (byte)0x3f, (byte)0x06, (byte)0x3e, (byte)0x44, (byte)0xa9, (byte)0x62,
+ (byte)0x2f, (byte)0x61, (byte)0x5a, (byte)0x51, (byte)0x82, (byte)0x2c,
+ (byte)0x04, (byte)0x85, (byte)0x73, (byte)0xd1
+ };
+
+ private static KeyPair genPredefinedRSAKeyPair() throws Exception {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ BigInteger mod = new BigInteger(MOD);
+ BigInteger pub = new BigInteger(PUB_EXP);
+
+ PrivateKey privKey = kf.generatePrivate
+ (new RSAPrivateCrtKeySpec
+ (mod, pub, new BigInteger(PRIV_EXP),
+ new BigInteger(PRIME_P), new BigInteger(PRIME_Q),
+ new BigInteger(EXP_P), new BigInteger(EXP_Q),
+ new BigInteger(CRT_COEFF)));
+ PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(mod, pub));
+ return new KeyPair(pubKey, privKey);
+ }
+
+ private static final String CIP_ALGOS[] = {
+ "RSA/ECB/NoPadding",
+ "RSA/ECB/PKCS1Padding"
+ };
+ private static final int INPUT_SIZE_REDUCTION[] = {
+ 0,
+ 11,
+ };
+
+ private static KeyPair kp[] = null;
+
+ public static void main(String argv[]) throws Exception {
+ main(new TestMalformedRSA(), null);
+ }
+
+ public void doTest(Provider prov) throws Exception {
+ // first test w/ predefine KeyPair
+ KeyPair pkp = genPredefinedRSAKeyPair();
+ System.out.println("Test against Predefined RSA Key Pair");
+ testCipher(pkp, 128, false, prov);
+ }
+
+
+ private static void testCipher(KeyPair kp, int inputSizeInBytes,
+ boolean checkInterop, Provider prov)
+ throws Exception {
+ Cipher c1, c2;
+ for (int i = 0; i < CIP_ALGOS.length; i++) {
+ String algo = CIP_ALGOS[i];
+ try {
+ c1 = Cipher.getInstance(algo, prov);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skip unsupported Cipher algo: " + algo);
+ continue;
+ }
+
+ if (checkInterop) {
+ c2 = Cipher.getInstance(algo, "SunJCE");
+ } else {
+ c2 = Cipher.getInstance(algo, prov);
+ }
+ byte[] data = Arrays.copyOf
+ (PLAINTEXT, inputSizeInBytes - INPUT_SIZE_REDUCTION[i]);
+
+ testEncryption(c1, c2, kp, data);
+ }
+ }
+
+ private static void testEncryption(Cipher c1, Cipher c2,
+ KeyPair kp, byte[] data) throws Exception {
+
+ // C1 Encrypt + C2 Decrypt
+ byte[] out1 = null;
+ byte[] recoveredText = null;
+ try {
+ c1.init(Cipher.ENCRYPT_MODE, kp.getPublic());
+ out1 = c1.doFinal(data);
+
+ // damage the cipher text
+ out1[out1.length - 1] = (byte)(out1[out1.length - 1] ^ 0xFF);
+
+ c2.init(Cipher.DECRYPT_MODE, kp.getPrivate());
+ recoveredText = c2.doFinal(out1);
+
+ // Note that decryption of "RSA/ECB/NoPadding" don't throw
+ // BadPaddingException
+ System.out.println("\t=> PASS: " + c2.getAlgorithm());
+ } catch (BadPaddingException ex) {
+ System.out.println("\tDEC ERROR: " + c2.getAlgorithm());
+ System.out.println("\t=> PASS: expected BadPaddingException");
+ ex.printStackTrace();
+ }
+
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/TestRSA.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 7088989
+ * @summary Ensure the RSA ciphers and signatures works correctly
+ */
+
+import java.io.*;
+import java.security.*;
+import java.security.spec.*;
+import java.util.*;
+import java.math.*;
+import javax.crypto.*;
+
+public class TestRSA extends UcryptoTest {
+
+ // KAT
+ private static final byte PLAINTEXT[] = Arrays.copyOf
+ (new String("Known plaintext message utilized" +
+ "for RSA Encryption & Decryption" +
+ "block, SHA1, SHA256, SHA384 and" +
+ "SHA512 RSA Signature KAT tests.").getBytes(), 128);
+
+ private static final byte MOD[] = {
+ (byte)0xd5, (byte)0x84, (byte)0x95, (byte)0x07, (byte)0xf4, (byte)0xd0,
+ (byte)0x1f, (byte)0x82, (byte)0xf3, (byte)0x79, (byte)0xf4, (byte)0x99,
+ (byte)0x48, (byte)0x10, (byte)0xe1, (byte)0x71, (byte)0xa5, (byte)0x62,
+ (byte)0x22, (byte)0xa3, (byte)0x4b, (byte)0x00, (byte)0xe3, (byte)0x5b,
+ (byte)0x3a, (byte)0xcc, (byte)0x10, (byte)0x83, (byte)0xe0, (byte)0xaf,
+ (byte)0x61, (byte)0x13, (byte)0x54, (byte)0x6a, (byte)0xa2, (byte)0x6a,
+ (byte)0x2c, (byte)0x5e, (byte)0xb3, (byte)0xcc, (byte)0xa3, (byte)0x71,
+ (byte)0x9a, (byte)0xb2, (byte)0x3e, (byte)0x78, (byte)0xec, (byte)0xb5,
+ (byte)0x0e, (byte)0x6e, (byte)0x31, (byte)0x3b, (byte)0x77, (byte)0x1f,
+ (byte)0x6e, (byte)0x94, (byte)0x41, (byte)0x60, (byte)0xd5, (byte)0x6e,
+ (byte)0xd9, (byte)0xc6, (byte)0xf9, (byte)0x29, (byte)0xc3, (byte)0x40,
+ (byte)0x36, (byte)0x25, (byte)0xdb, (byte)0xea, (byte)0x0b, (byte)0x07,
+ (byte)0xae, (byte)0x76, (byte)0xfd, (byte)0x99, (byte)0x29, (byte)0xf4,
+ (byte)0x22, (byte)0xc1, (byte)0x1a, (byte)0x8f, (byte)0x05, (byte)0xfe,
+ (byte)0x98, (byte)0x09, (byte)0x07, (byte)0x05, (byte)0xc2, (byte)0x0f,
+ (byte)0x0b, (byte)0x11, (byte)0x83, (byte)0x39, (byte)0xca, (byte)0xc7,
+ (byte)0x43, (byte)0x63, (byte)0xff, (byte)0x33, (byte)0x80, (byte)0xe7,
+ (byte)0xc3, (byte)0x78, (byte)0xae, (byte)0xf1, (byte)0x73, (byte)0x52,
+ (byte)0x98, (byte)0x1d, (byte)0xde, (byte)0x5c, (byte)0x53, (byte)0x6e,
+ (byte)0x01, (byte)0x73, (byte)0x0d, (byte)0x12, (byte)0x7e, (byte)0x77,
+ (byte)0x03, (byte)0xf1, (byte)0xef, (byte)0x1b, (byte)0xc8, (byte)0xa8,
+ (byte)0x0f, (byte)0x97
+ };
+
+ private static final byte PUB_EXP[] = {(byte)0x01, (byte)0x00, (byte)0x01};
+
+ private static final byte PRIV_EXP[] = {
+ (byte)0x85, (byte)0x27, (byte)0x47, (byte)0x61, (byte)0x4c, (byte)0xd4,
+ (byte)0xb5, (byte)0xb2, (byte)0x0e, (byte)0x70, (byte)0x91, (byte)0x8f,
+ (byte)0x3d, (byte)0x97, (byte)0xf9, (byte)0x5f, (byte)0xcc, (byte)0x09,
+ (byte)0x65, (byte)0x1c, (byte)0x7c, (byte)0x5b, (byte)0xb3, (byte)0x6d,
+ (byte)0x63, (byte)0x3f, (byte)0x7b, (byte)0x55, (byte)0x22, (byte)0xbb,
+ (byte)0x7c, (byte)0x48, (byte)0x77, (byte)0xae, (byte)0x80, (byte)0x56,
+ (byte)0xc2, (byte)0x10, (byte)0xd5, (byte)0x03, (byte)0xdb, (byte)0x31,
+ (byte)0xaf, (byte)0x8d, (byte)0x54, (byte)0xd4, (byte)0x48, (byte)0x99,
+ (byte)0xa8, (byte)0xc4, (byte)0x23, (byte)0x43, (byte)0xb8, (byte)0x48,
+ (byte)0x0b, (byte)0xc7, (byte)0xbc, (byte)0xf5, (byte)0xcc, (byte)0x64,
+ (byte)0x72, (byte)0xbf, (byte)0x59, (byte)0x06, (byte)0x04, (byte)0x1c,
+ (byte)0x32, (byte)0xf5, (byte)0x14, (byte)0x2e, (byte)0x6e, (byte)0xe2,
+ (byte)0x0f, (byte)0x5c, (byte)0xde, (byte)0x36, (byte)0x3c, (byte)0x6e,
+ (byte)0x7c, (byte)0x4d, (byte)0xcc, (byte)0xd3, (byte)0x00, (byte)0x6e,
+ (byte)0xe5, (byte)0x45, (byte)0x46, (byte)0xef, (byte)0x4d, (byte)0x25,
+ (byte)0x46, (byte)0x6d, (byte)0x7f, (byte)0xed, (byte)0xbb, (byte)0x4f,
+ (byte)0x4d, (byte)0x9f, (byte)0xda, (byte)0x87, (byte)0x47, (byte)0x8f,
+ (byte)0x74, (byte)0x44, (byte)0xb7, (byte)0xbe, (byte)0x9d, (byte)0xf5,
+ (byte)0xdd, (byte)0xd2, (byte)0x4c, (byte)0xa5, (byte)0xab, (byte)0x74,
+ (byte)0xe5, (byte)0x29, (byte)0xa1, (byte)0xd2, (byte)0x45, (byte)0x3b,
+ (byte)0x33, (byte)0xde, (byte)0xd5, (byte)0xae, (byte)0xf7, (byte)0x03,
+ (byte)0x10, (byte)0x21
+ };
+
+ private static final byte PRIME_P[] = {
+ (byte)0xf9, (byte)0x74, (byte)0x8f, (byte)0x16, (byte)0x02, (byte)0x6b,
+ (byte)0xa0, (byte)0xee, (byte)0x7f, (byte)0x28, (byte)0x97, (byte)0x91,
+ (byte)0xdc, (byte)0xec, (byte)0xc0, (byte)0x7c, (byte)0x49, (byte)0xc2,
+ (byte)0x85, (byte)0x76, (byte)0xee, (byte)0x66, (byte)0x74, (byte)0x2d,
+ (byte)0x1a, (byte)0xb8, (byte)0xf7, (byte)0x2f, (byte)0x11, (byte)0x5b,
+ (byte)0x36, (byte)0xd8, (byte)0x46, (byte)0x33, (byte)0x3b, (byte)0xd8,
+ (byte)0xf3, (byte)0x2d, (byte)0xa1, (byte)0x03, (byte)0x83, (byte)0x2b,
+ (byte)0xec, (byte)0x35, (byte)0x43, (byte)0x32, (byte)0xff, (byte)0xdd,
+ (byte)0x81, (byte)0x7c, (byte)0xfd, (byte)0x65, (byte)0x13, (byte)0x04,
+ (byte)0x7c, (byte)0xfc, (byte)0x03, (byte)0x97, (byte)0xf0, (byte)0xd5,
+ (byte)0x62, (byte)0xdc, (byte)0x0d, (byte)0xbf
+ };
+
+ private static final byte PRIME_Q[] = {
+ (byte)0xdb, (byte)0x1e, (byte)0xa7, (byte)0x3d, (byte)0xe7, (byte)0xfa,
+ (byte)0x8b, (byte)0x04, (byte)0x83, (byte)0x48, (byte)0xf3, (byte)0xa5,
+ (byte)0x31, (byte)0x9d, (byte)0x35, (byte)0x5e, (byte)0x4d, (byte)0x54,
+ (byte)0x77, (byte)0xcc, (byte)0x84, (byte)0x09, (byte)0xf3, (byte)0x11,
+ (byte)0x0d, (byte)0x54, (byte)0xed, (byte)0x85, (byte)0x39, (byte)0xa9,
+ (byte)0xca, (byte)0xa8, (byte)0xea, (byte)0xae, (byte)0x19, (byte)0x9c,
+ (byte)0x75, (byte)0xdb, (byte)0x88, (byte)0xb8, (byte)0x04, (byte)0x8d,
+ (byte)0x54, (byte)0xc6, (byte)0xa4, (byte)0x80, (byte)0xf8, (byte)0x93,
+ (byte)0xf0, (byte)0xdb, (byte)0x19, (byte)0xef, (byte)0xd7, (byte)0x87,
+ (byte)0x8a, (byte)0x8f, (byte)0x5a, (byte)0x09, (byte)0x2e, (byte)0x54,
+ (byte)0xf3, (byte)0x45, (byte)0x24, (byte)0x29
+ };
+
+ private static final byte EXP_P[] = {
+ (byte)0x6a, (byte)0xd1, (byte)0x25, (byte)0x80, (byte)0x18, (byte)0x33,
+ (byte)0x3c, (byte)0x2b, (byte)0x44, (byte)0x19, (byte)0xfe, (byte)0xa5,
+ (byte)0x40, (byte)0x03, (byte)0xc4, (byte)0xfc, (byte)0xb3, (byte)0x9c,
+ (byte)0xef, (byte)0x07, (byte)0x99, (byte)0x58, (byte)0x17, (byte)0xc1,
+ (byte)0x44, (byte)0xa3, (byte)0x15, (byte)0x7d, (byte)0x7b, (byte)0x22,
+ (byte)0x22, (byte)0xdf, (byte)0x03, (byte)0x58, (byte)0x66, (byte)0xf5,
+ (byte)0x24, (byte)0x54, (byte)0x52, (byte)0x91, (byte)0x2d, (byte)0x76,
+ (byte)0xfe, (byte)0x63, (byte)0x64, (byte)0x4e, (byte)0x0f, (byte)0x50,
+ (byte)0x2b, (byte)0x65, (byte)0x79, (byte)0x1f, (byte)0xf1, (byte)0xbf,
+ (byte)0xc7, (byte)0x41, (byte)0x26, (byte)0xcc, (byte)0xc6, (byte)0x1c,
+ (byte)0xa9, (byte)0x83, (byte)0x6f, (byte)0x03
+ };
+
+ private static final byte EXP_Q[] = {
+ (byte)0x12, (byte)0x84, (byte)0x1a, (byte)0x99, (byte)0xce, (byte)0x9a,
+ (byte)0x8b, (byte)0x58, (byte)0xcc, (byte)0x47, (byte)0x43, (byte)0xdf,
+ (byte)0x77, (byte)0xbb, (byte)0xd3, (byte)0x20, (byte)0xae, (byte)0xe4,
+ (byte)0x2e, (byte)0x63, (byte)0x67, (byte)0xdc, (byte)0xf7, (byte)0x5f,
+ (byte)0x3f, (byte)0x83, (byte)0x27, (byte)0xb7, (byte)0x14, (byte)0x52,
+ (byte)0x56, (byte)0xbf, (byte)0xc3, (byte)0x65, (byte)0x06, (byte)0xe1,
+ (byte)0x03, (byte)0xcc, (byte)0x93, (byte)0x57, (byte)0x09, (byte)0x7b,
+ (byte)0x6f, (byte)0xe8, (byte)0x81, (byte)0x4a, (byte)0x2c, (byte)0xb7,
+ (byte)0x43, (byte)0xa9, (byte)0x20, (byte)0x1d, (byte)0xf6, (byte)0x56,
+ (byte)0x8b, (byte)0xcc, (byte)0xe5, (byte)0x4c, (byte)0xd5, (byte)0x4f,
+ (byte)0x74, (byte)0x67, (byte)0x29, (byte)0x51
+ };
+
+ private static final byte CRT_COEFF[] = {
+ (byte)0x23, (byte)0xab, (byte)0xf4, (byte)0x03, (byte)0x2f, (byte)0x29,
+ (byte)0x95, (byte)0x74, (byte)0xac, (byte)0x1a, (byte)0x33, (byte)0x96,
+ (byte)0x62, (byte)0xed, (byte)0xf7, (byte)0xf6, (byte)0xae, (byte)0x07,
+ (byte)0x2a, (byte)0x2e, (byte)0xe8, (byte)0xab, (byte)0xfb, (byte)0x1e,
+ (byte)0xb9, (byte)0xb2, (byte)0x88, (byte)0x1e, (byte)0x85, (byte)0x05,
+ (byte)0x42, (byte)0x64, (byte)0x03, (byte)0xb2, (byte)0x8b, (byte)0xc1,
+ (byte)0x81, (byte)0x75, (byte)0xd7, (byte)0xba, (byte)0xaa, (byte)0xd4,
+ (byte)0x31, (byte)0x3c, (byte)0x8a, (byte)0x96, (byte)0x23, (byte)0x9d,
+ (byte)0x3f, (byte)0x06, (byte)0x3e, (byte)0x44, (byte)0xa9, (byte)0x62,
+ (byte)0x2f, (byte)0x61, (byte)0x5a, (byte)0x51, (byte)0x82, (byte)0x2c,
+ (byte)0x04, (byte)0x85, (byte)0x73, (byte)0xd1
+ };
+
+ private static KeyPair genRSAKey(int keyLength) throws Exception {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ kpg.initialize(keyLength);
+ return kpg.generateKeyPair();
+ }
+
+ private static KeyPair genPredefinedRSAKeyPair() throws Exception {
+ KeyFactory kf = KeyFactory.getInstance("RSA");
+ BigInteger mod = new BigInteger(MOD);
+ BigInteger pub = new BigInteger(PUB_EXP);
+
+ PrivateKey privKey = kf.generatePrivate
+ (new RSAPrivateCrtKeySpec
+ (mod, pub, new BigInteger(PRIV_EXP),
+ new BigInteger(PRIME_P), new BigInteger(PRIME_Q),
+ new BigInteger(EXP_P), new BigInteger(EXP_Q),
+ new BigInteger(CRT_COEFF)));
+ PublicKey pubKey = kf.generatePublic(new RSAPublicKeySpec(mod, pub));
+ return new KeyPair(pubKey, privKey);
+ }
+
+ private static final String CIP_ALGOS[] = {
+ "RSA/ECB/NoPadding",
+ "RSA/ECB/PKCS1Padding"
+ };
+ private static final int INPUT_SIZE_REDUCTION[] = {
+ 0,
+ 11,
+ };
+ private static final String SIG_ALGOS[] = {
+ "MD5WithRSA",
+ "SHA1WithRSA",
+ "SHA256WithRSA",
+ "SHA384WithRSA",
+ "SHA512WithRSA"
+ };
+
+ private static KeyPair kp[] = null;
+
+ public static void main(String argv[]) throws Exception {
+ main(new TestRSA(), null);
+ }
+
+ public void doTest(Provider prov) throws Exception {
+ // first test w/ predefine KeyPair
+ KeyPair pkp = genPredefinedRSAKeyPair();
+ System.out.println("Test against Predefined RSA Key Pair");
+ testCipher(pkp, 128, true, prov);
+ testSignature(pkp, true, prov);
+
+ for (int i = 0; i < 10; i++) {
+ // then test w/ various key lengths
+ int keyLens[] = { 1024, 2048 };
+ kp = new KeyPair[keyLens.length];
+
+ testCipher(keyLens, false, prov);
+ testSignature(keyLens, false, prov);
+ }
+ }
+
+
+ private static void testCipher(KeyPair kp, int inputSizeInBytes,
+ boolean checkInterop, Provider prov)
+ throws Exception {
+ Cipher c1, c2;
+ for (int i = 0; i < CIP_ALGOS.length; i++) {
+ String algo = CIP_ALGOS[i];
+ try {
+ c1 = Cipher.getInstance(algo, prov);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skip unsupported Cipher algo: " + algo);
+ continue;
+ }
+
+ if (checkInterop) {
+ c2 = Cipher.getInstance(algo, "SunJCE");
+ } else {
+ c2 = Cipher.getInstance(algo, prov);
+ }
+ byte[] data = Arrays.copyOf
+ (PLAINTEXT, inputSizeInBytes - INPUT_SIZE_REDUCTION[i]);
+
+ testEncryption(c1, c2, kp, data);
+ }
+ }
+
+ private static void testCipher(int keyLens[], boolean checkInterop,
+ Provider prov)
+ throws Exception {
+ // RSA CipherText will always differ due to the random nonce in padding
+ // so we check whether both
+ // 1) Java Encrypt/C Decrypt
+ // 2) C Encrypt/Java Decrypt
+ // works
+ Cipher c1, c2;
+ for (int i = 0; i < CIP_ALGOS.length; i++) {
+ String algo = CIP_ALGOS[i];
+ try {
+ c1 = Cipher.getInstance(algo, prov);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skip unsupported Cipher algo: " + algo);
+ continue;
+ }
+
+ if (checkInterop) {
+ c2 = Cipher.getInstance(algo, "SunJCE");
+ } else {
+ c2 = Cipher.getInstance(algo, prov);
+ }
+
+ for (int h = 0; h < keyLens.length; h++) {
+ // Defer key pair generation until now when it'll soon be used.
+ if (kp[h] == null) {
+ kp[h] = genRSAKey(keyLens[h]);
+ }
+ System.out.println("\tTesting Cipher " + algo + " w/ KeySize " + keyLens[h]);
+ byte[] data = Arrays.copyOf
+ (PLAINTEXT, keyLens[h]/8 - INPUT_SIZE_REDUCTION[i]);
+ testEncryption(c1, c2, kp[h], data);
+ }
+ }
+ }
+
+ private static void testEncryption(Cipher c1, Cipher c2, KeyPair kp, byte[] data)
+ throws Exception {
+ // C1 Encrypt + C2 Decrypt
+ byte[] out1 = null;
+ byte[] recoveredText = null;
+ try {
+ c1.init(Cipher.ENCRYPT_MODE, kp.getPublic());
+ out1 = c1.doFinal(data);
+ c2.init(Cipher.DECRYPT_MODE, kp.getPrivate());
+ recoveredText = c2.doFinal(out1);
+ } catch (Exception ex) {
+ System.out.println("\tDEC ERROR: unexpected exception");
+ ex.printStackTrace();
+ throw ex;
+ }
+ if(!Arrays.equals(recoveredText, data)) {
+ throw new RuntimeException("\tDEC ERROR: different PT bytes!");
+ }
+ // C2 Encrypt + C1 Decrypt
+ byte[] cipherText = null;
+ try {
+ c2.init(Cipher.ENCRYPT_MODE, kp.getPublic());
+ cipherText = c2.doFinal(data);
+ c1.init(Cipher.DECRYPT_MODE, kp.getPrivate());
+ try {
+ out1 = c1.doFinal(cipherText);
+ } catch (Exception ex) {
+ System.out.println("\tENC ERROR: invalid encrypted output");
+ ex.printStackTrace();
+ throw ex;
+ }
+ } catch (Exception ex) {
+ System.out.println("\tENC ERROR: unexpected exception");
+ ex.printStackTrace();
+ throw ex;
+ }
+ if (!Arrays.equals(out1, data)) {
+ throw new RuntimeException("\tENC ERROR: Decrypted result DIFF!");
+ }
+ System.out.println("\t=> PASS");
+ }
+
+ private static void testSignature(KeyPair kp, boolean checkInterop,
+ Provider prov) throws Exception {
+ byte[] data = PLAINTEXT;
+ Signature sig1, sig2;
+ for (int i = 0; i < SIG_ALGOS.length; i++) {
+ String algo = SIG_ALGOS[i];
+ try {
+ sig1 = Signature.getInstance(algo, prov);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skip unsupported Signature algo: " + algo);
+ continue;
+ }
+
+ if (checkInterop) {
+ sig2 = Signature.getInstance(algo, "SunRsaSign");
+ } else {
+ sig2 = Signature.getInstance(algo, prov);
+ }
+ testSigning(sig1, sig2, kp, data);
+ }
+ }
+
+ private static void testSignature(int keyLens[], boolean checkInterop,
+ Provider prov) throws Exception {
+ byte[] data = PLAINTEXT;
+ Signature sig1, sig2;
+ for (int i = 0; i < SIG_ALGOS.length; i++) {
+ String algo = SIG_ALGOS[i];
+ try {
+ sig1 = Signature.getInstance(algo, prov);
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skip unsupported Signature algo: " + algo);
+ continue;
+ }
+
+ if (checkInterop) {
+ sig2 = Signature.getInstance(algo, "SunRsaSign");
+ } else {
+ sig2 = Signature.getInstance(algo, prov);
+ }
+
+ for (int h = 0; h < keyLens.length; h++) {
+ // Defer key pair generation until now when it'll soon be used.
+ if (kp[h] == null) {
+ kp[h] = genRSAKey(keyLens[h]);
+ }
+ System.out.println("\tTesting Signature " + algo + " w/ KeySize " + keyLens[h]);
+
+ testSigning(sig1, sig2, kp[h], data);
+ }
+ }
+ }
+
+ private static void testSigning(Signature sig1, Signature sig2, KeyPair kp, byte[] data)
+ throws Exception {
+ boolean sameSig = false;
+ byte[] out = null;
+ try {
+ sig1.initSign(kp.getPrivate());
+ sig1.update(data);
+ out = sig1.sign();
+ } catch (Exception ex) {
+ System.out.println("\tSIGN ERROR: unexpected exception!");
+ ex.printStackTrace();
+ }
+
+ sig2.initSign(kp.getPrivate());
+ sig2.update(data);
+ byte[] out2 = sig2.sign();
+ if (!Arrays.equals(out2, out)) {
+ throw new RuntimeException("\tSIGN ERROR: Signature DIFF!");
+ }
+
+ boolean verify = false;
+ try {
+ System.out.println("\tVERIFY1 using native out");
+ sig1.initVerify(kp.getPublic());
+ sig1.update(data);
+ verify = sig1.verify(out);
+ if (!verify) {
+ throw new RuntimeException("VERIFY1 FAIL!");
+ }
+ } catch (Exception ex) {
+ System.out.println("\tVERIFY1 ERROR: unexpected exception!");
+ ex.printStackTrace();
+ throw ex;
+ }
+ System.out.println("\t=> PASS");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/com/oracle/security/ucrypto/UcryptoTest.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+import java.io.*;
+import java.util.*;
+import java.lang.reflect.*;
+import java.security.*;
+
+// common infrastructure for OracleUcrypto provider tests
+public abstract class UcryptoTest {
+
+ protected static final boolean hasUcrypto;
+ static {
+ hasUcrypto = (Security.getProvider("OracleUcrypto") != null);
+ }
+
+ private static Provider getCustomizedUcrypto(String config) throws Exception {
+ Class clazz = Class.forName("com.oracle.security.ucrypto.OracleUcrypto");
+ Constructor cons = clazz.getConstructor(new Class[] {String.class});
+ Object obj = cons.newInstance(new Object[] {config});
+ return (Provider)obj;
+ }
+
+ public abstract void doTest(Provider p) throws Exception;
+
+ public static void main(UcryptoTest test, String config) throws Exception {
+ Provider prov = null;
+ if (hasUcrypto) {
+ if (config != null) {
+ prov = getCustomizedUcrypto(config);
+ } else {
+ prov = Security.getProvider("OracleUcrypto");
+ }
+ }
+ if (prov == null) {
+ // un-available, skip testing...
+ System.out.println("No OracleUcrypto provider found, skipping test");
+ return;
+ }
+ test.doTest(prov);
+ }
+}
--- a/jdk/test/com/sun/tools/attach/StartManagementAgent.java Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/test/com/sun/tools/attach/StartManagementAgent.java Tue Oct 21 13:56:58 2014 -0700
@@ -100,6 +100,7 @@
ex.printStackTrace(System.err);
} catch (Throwable t) {
t.printStackTrace(System.err);
+ throw t;
}
}
@@ -124,6 +125,7 @@
try {
System.err.println("Trying remote agent. Try #" + i);
testRemoteAgent(vm);
+ System.err.println("Successfully connected to remote agent");
success = true;
} catch(Exception ex) {
System.err.println("testRemoteAgent failed with exception:");
@@ -136,7 +138,9 @@
throw new Exception("testRemoteAgent failed after " + MAX_RETRIES + " tries");
}
} finally {
+ System.err.println("Detaching from VM ...");
vm.detach();
+ System.err.println("Detached");
}
}
@@ -176,7 +180,10 @@
mgmtProps.put("com.sun.management.jmxremote.port", port);
mgmtProps.put("com.sun.management.jmxremote.authenticate", "false");
mgmtProps.put("com.sun.management.jmxremote.ssl", "false");
+
+ System.err.println("Starting management agent ...");
vm.startManagementAgent(mgmtProps);
+ System.err.println("Started");
// try to connect - should work
tryConnect(port, true);
@@ -184,9 +191,12 @@
// try to start again - should fail
boolean exception = false;
try {
+ System.err.println("Starting management agent second time ...");
vm.startManagementAgent(mgmtProps);
+ System.err.println("Started");
} catch(AttachOperationFailedException ex) {
// expected
+ System.err.println("Got expected exception: " + ex.getMessage());
exception = true;
}
if (!exception) {
@@ -204,10 +214,14 @@
boolean succeeded;
try {
+ System.err.println("Trying to connect to " + jmxUrlStr);
JMXConnector c = JMXConnectorFactory.connect(url, env);
+ System.err.println("Connected, getting MBeanServerConnection");
c.getMBeanServerConnection();
+ System.err.println("Success");
succeeded = true;
} catch(Exception ex) {
+ ex.printStackTrace(System.err);
succeeded = false;
}
if (succeeded && !shouldSucceed) {
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/StressLoopback.java Tue Oct 21 13:56:58 2014 -0700
@@ -24,6 +24,8 @@
/* @test
* @bug 6834246 6842687
* @summary Stress test connections through the loopback interface
+ * @run main StressLoopback
+ * @run main/othervm -Djdk.net.useFastTcpLoopback StressLoopback
*/
import java.nio.ByteBuffer;
--- a/jdk/test/javax/net/ssl/TLS/CipherTestUtils.java Fri Oct 17 07:58:57 2014 -0700
+++ b/jdk/test/javax/net/ssl/TLS/CipherTestUtils.java Tue Oct 21 13:56:58 2014 -0700
@@ -261,20 +261,20 @@
}
}
- private static volatile CipherTestUtils instnace = null;
+ private static volatile CipherTestUtils instance = null;
public static CipherTestUtils getInstance() throws IOException,
FileNotFoundException, KeyStoreException,
NoSuchAlgorithmException, CertificateException,
UnrecoverableKeyException, InvalidKeySpecException {
- if (instnace == null) {
+ if (instance == null) {
synchronized (CipherTestUtils.class) {
- if (instnace == null) {
- instnace = new CipherTestUtils();
+ if (instance == null) {
+ instance = new CipherTestUtils();
}
}
}
- return instnace;
+ return instance;
}
public static void setTestedArguments(String testedProtocol,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/sql/testng/test/rowset/RowSetWarningTests.java Tue Oct 21 13:56:58 2014 -0700
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package test.rowset;
+
+import java.sql.SQLException;
+import javax.sql.rowset.RowSetWarning;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+import util.BaseTest;
+
+public class RowSetWarningTests extends BaseTest {
+
+ private final String[] warnings = {"Warning 1", "cause 1", "Warning 2",
+ "Warning 3", "cause 2"};
+
+ /*
+ * Create RowSetWarning and setting all objects to null
+ */
+ @Test
+ public void test() {
+ RowSetWarning e = new RowSetWarning(null, null, errorCode);
+ assertTrue(e.getMessage() == null && e.getSQLState() == null
+ && e.getCause() == null && e.getErrorCode() == errorCode);
+ }
+
+ /*
+ * Create RowSetWarning with no-arg constructor
+ */
+ @Test
+ public void test01() {
+ RowSetWarning ex = new RowSetWarning();
+ assertTrue(ex.getMessage() == null
+ && ex.getSQLState() == null
+ && ex.getCause() == null
+ && ex.getErrorCode() == 0);
+ }
+
+ /*
+ * Create RowSetWarning with message
+ */
+ @Test
+ public void test02() {
+ RowSetWarning ex = new RowSetWarning(reason);
+ assertTrue(ex.getMessage().equals(reason)
+ && ex.getSQLState() == null
+ && ex.getCause() == null
+ && ex.getErrorCode() == 0);
+ }
+
+ /*
+ * Create RowSetWarning with message, and SQLState
+ */
+ @Test
+ public void test03() {
+
+ RowSetWarning ex = new RowSetWarning(reason, state);
+ assertTrue(ex.getMessage().equals(reason)
+ && ex.getSQLState().equals(state)
+ && ex.getCause() == null
+ && ex.getErrorCode() == 0);
+ }
+
+ /*
+ * Create RowSetWarning with message, SQLState, and error code
+ */
+ @Test
+ public void test04() {
+ RowSetWarning ex = new RowSetWarning(reason, state, errorCode);
+ assertTrue(ex.getMessage().equals(reason)
+ && ex.getSQLState().equals(state)
+ && ex.getCause() == null
+ && ex.getErrorCode() == errorCode);
+ }
+
+ /*
+ * Serialize a RowSetWarning and make sure you can read it back properly
+ */
+ @Test
+ public void test05() throws Exception {
+ RowSetWarning e = new RowSetWarning(reason, state, errorCode);
+ e.initCause(t);
+ RowSetWarning ex1 = createSerializedException(e);
+ assertTrue(reason.equals(ex1.getMessage())
+ && ex1.getSQLState().equals(state)
+ && cause.equals(ex1.getCause().toString())
+ && ex1.getErrorCode() == errorCode);
+ }
+
+ /*
+ * Validate that the ordering of the returned Exceptions is correct using
+ * for-each loop
+ */
+ @Test
+ public void test06() {
+ RowSetWarning ex = new RowSetWarning("Exception 1");
+ ex.initCause(t1);
+ RowSetWarning ex1 = new RowSetWarning("Exception 2");
+ RowSetWarning ex2 = new RowSetWarning("Exception 3");
+ ex2.initCause(t2);
+ ex.setNextException(ex1);
+ ex.setNextException(ex2);
+ int num = 0;
+ for (Throwable e : ex) {
+ assertTrue(msgs[num++].equals(e.getMessage()));
+ }
+ }
+
+ /*
+ * Validate that the ordering of the returned Exceptions is correct using
+ * traditional while loop
+ */
+ @Test
+ public void test07() {
+ RowSetWarning ex = new RowSetWarning("Exception 1");
+ ex.initCause(t1);
+ RowSetWarning ex1 = new RowSetWarning("Exception 2");
+ RowSetWarning ex2 = new RowSetWarning("Exception 3");
+ ex2.initCause(t2);
+ ex.setNextException(ex1);
+ ex.setNextException(ex2);
+ int num = 0;
+ SQLException sqe = ex;
+ while (sqe != null) {
+ assertTrue(msgs[num++].equals(sqe.getMessage()));
+ Throwable c = sqe.getCause();
+ while (c != null) {
+ assertTrue(msgs[num++].equals(c.getMessage()));
+ c = c.getCause();
+ }
+ sqe = sqe.getNextException();
+ }
+ }
+
+ /*
+ * Validate that the ordering of the returned RowSetWarning is correct using
+ * for-each loop
+ */
+ @Test
+ public void test08() {
+ RowSetWarning ex = new RowSetWarning("Warning 1");
+ ex.initCause(t1);
+ RowSetWarning ex1 = new RowSetWarning("Warning 2");
+ RowSetWarning ex2 = new RowSetWarning("Warning 3");
+ ex2.initCause(t2);
+ ex.setNextWarning(ex1);
+ ex.setNextWarning(ex2);
+ int num = 0;
+ for (Throwable e : ex) {
+ assertTrue(warnings[num++].equals(e.getMessage()));
+ }
+ }
+
+ /**
+ * Validate that the ordering of the returned RowSetWarning is correct using
+ * traditional while loop
+ */
+ @Test
+ public void test09() {
+ RowSetWarning ex = new RowSetWarning("Warning 1");
+ ex.initCause(t1);
+ RowSetWarning ex1 = new RowSetWarning("Warning 2");
+ RowSetWarning ex2 = new RowSetWarning("Warning 3");
+ ex2.initCause(t2);
+ ex.setNextWarning(ex1);
+ ex.setNextWarning(ex2);
+ int num = 0;
+ RowSetWarning sqe = ex;
+ while (sqe != null) {
+ assertTrue(warnings[num++].equals(sqe.getMessage()));
+ Throwable c = sqe.getCause();
+ while (c != null) {
+ assertTrue(msgs[num++].equals(c.getMessage()));
+ c = c.getCause();
+ }
+ sqe = sqe.getNextWarning();
+ }
+ }
+
+ /*
+ * Serialize a RowSetWarning and make sure you can read it back properly
+ */
+ @Test
+ public void test10() throws Exception {
+ RowSetWarning e = new RowSetWarning(reason, state, errorCode);
+ RowSetWarning ex1 = createSerializedException(e);
+ assertTrue(reason.equals(ex1.getMessage())
+ && ex1.getSQLState().equals(state)
+ && ex1.getCause() == null
+ && ex1.getErrorCode() == errorCode);
+ }
+
+ /*
+ * Serialize a RowSetWarning and make sure you can read it back properly.
+ * Validate that the ordering of the returned RowSetWarning is correct using
+ * traditional while loop
+ */
+ @Test
+ public void test11() throws Exception {
+ RowSetWarning ex = new RowSetWarning("Warning 1");
+ ex.initCause(t1);
+ RowSetWarning ex1 = new RowSetWarning("Warning 2");
+ RowSetWarning ex2 = new RowSetWarning("Warning 3");
+ ex2.initCause(t2);
+ ex.setNextWarning(ex1);
+ ex.setNextWarning(ex2);
+ int num = 0;
+ RowSetWarning sqe = createSerializedException(ex);
+ while (sqe != null) {
+ assertTrue(warnings[num++].equals(sqe.getMessage()));
+ Throwable c = sqe.getCause();
+ while (c != null) {
+ assertTrue(msgs[num++].equals(c.getMessage()));
+ c = c.getCause();
+ }
+ sqe = sqe.getNextWarning();
+ }
+ }
+}