Merge
This commit is contained in:
commit
f0c02512ea
jdk
make
src
java.base
share
classes
conf/security
native/libnet
unix/native
windows/native
java.sql.rowset/share/classes/javax/sql/rowset
jdk.crypto.ucrypto/solaris
classes/com/oracle/security/ucrypto
CipherContextRef.javaConfig.javaGCMParameters.javaNativeCipher.javaNativeCipherWithJavaPadding.javaNativeDigest.javaNativeGCMCipher.javaNativeKey.javaNativeRSACipher.javaNativeRSAKeyFactory.javaNativeRSASignature.javaUcryptoException.javaUcryptoMech.javaUcryptoProvider.java
conf/security
native/libj2ucrypto
test
TEST.groups
com
oracle/security/ucrypto
CipherSignNotSupported.javaTest8004873.javaTestAES.javaTestCICOWithGCM.javaTestCICOWithGCMAndAAD.javaTestDigest.javaTestGCMKeyAndIvCheck.javaTestGCMKeyWrap.javaTestGCMWithSBE.javaTestKATForGCM.javaTestMalformedRSA.javaTestRSA.javaUcryptoTest.java
sun/tools/attach
java/nio/channels/AsynchronousSocketChannel
javax
@ -111,6 +111,7 @@ $(eval $(call SetupArchive,BUILD_LOCALEDATA_JAR, \
|
||||
# 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 \
|
||||
|
@ -169,27 +169,25 @@ endif
|
||||
##########################################################################################
|
||||
|
||||
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)
|
||||
|
@ -170,10 +170,7 @@ POLICY_SRC_LIST :=
|
||||
|
||||
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
|
||||
|
49
jdk/make/copy/Copy-jdk.crypto.ucrypto.gmk
Normal file
49
jdk/make/copy/Copy-jdk.crypto.ucrypto.gmk
Normal file
@ -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
|
||||
|
62
jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk
Normal file
62
jdk/make/lib/Lib-jdk.crypto.ucrypto.gmk
Normal file
@ -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
|
@ -110,6 +110,8 @@ SUNWprivate_1.1 {
|
||||
NET_Bind;
|
||||
NET_MapSocketOption;
|
||||
NET_Wait;
|
||||
NET_EnableFastTcpLoopback;
|
||||
NET_ThrowNew;
|
||||
ipv6_available;
|
||||
initInetAddressIDs;
|
||||
|
||||
|
@ -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 @@ public class ProtectionDomain {
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -50,30 +50,8 @@ public class Net {
|
||||
// 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 class Net {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ public class Net {
|
||||
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 @@ public class Net {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,18 @@ grant codeBase "file:${java.home}/lib/ext/nashorn.jar" {
|
||||
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";
|
||||
|
@ -184,9 +184,13 @@ NET_MapSocketOption(jint cmd, int *level, int *optname);
|
||||
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 */
|
||||
|
@ -790,6 +790,11 @@ void parseExclusiveBindProperty(JNIEnv *env) {
|
||||
#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.
|
||||
|
@ -188,7 +188,7 @@ Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
|
||||
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);
|
||||
|
@ -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 @@ jint getDefaultIPv6Interface(JNIEnv *env, struct SOCKADDR_IN6 *target_addr)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -127,7 +127,7 @@ Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl)
|
||||
|
||||
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 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -55,11 +55,6 @@ import java.sql.SQLException;
|
||||
*/
|
||||
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,
|
||||
@ -128,7 +123,15 @@ public class RowSetWarning extends SQLException {
|
||||
* @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 @@ public class RowSetWarning extends SQLException {
|
||||
* @see #getNextWarning
|
||||
*/
|
||||
public void setNextWarning(RowSetWarning warning) {
|
||||
rwarning = warning;
|
||||
setNextException(warning);
|
||||
}
|
||||
|
||||
static final long serialVersionUID = 6678332766434564774L;
|
||||
|
103
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/CipherContextRef.java
Normal file
103
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/CipherContextRef.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
130
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/GCMParameters.java
Normal file
130
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/GCMParameters.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
588
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java
Normal file
588
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipher.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
464
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
Normal file
464
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeCipherWithJavaPadding.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
243
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java
Normal file
243
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeDigest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
422
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java
Normal file
422
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeGCMCipher.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
230
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeKey.java
Normal file
230
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeKey.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
448
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java
Normal file
448
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSACipher.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
80
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSAKeyFactory.java
Normal file
80
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSAKeyFactory.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
445
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
Normal file
445
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/NativeRSASignature.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
179
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java
Normal file
179
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoException.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
119
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java
Normal file
119
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoMech.java
Normal file
@ -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; }
|
||||
}
|
179
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
Normal file
179
jdk/src/jdk.crypto.ucrypto/solaris/classes/com/oracle/security/ucrypto/UcryptoProvider.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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;
|
||||
}
|
@ -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
|
@ -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 */
|
@ -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 */
|
@ -120,6 +120,7 @@ jdk_security1 = \
|
||||
jdk_security2 = \
|
||||
javax/crypto \
|
||||
javax/xml/crypto \
|
||||
com/oracle/security/ucrypto \
|
||||
com/sun/crypto
|
||||
|
||||
jdk_security3 = \
|
||||
@ -390,6 +391,10 @@ needs_jre = \
|
||||
: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 \
|
||||
|
100
jdk/test/com/oracle/security/ucrypto/CipherSignNotSupported.java
Normal file
100
jdk/test/com/oracle/security/ucrypto/CipherSignNotSupported.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
102
jdk/test/com/oracle/security/ucrypto/Test8004873.java
Normal file
102
jdk/test/com/oracle/security/ucrypto/Test8004873.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
343
jdk/test/com/oracle/security/ucrypto/TestAES.java
Normal file
343
jdk/test/com/oracle/security/ucrypto/TestAES.java
Normal file
@ -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;
|
||||
}
|
||||
}
|
104
jdk/test/com/oracle/security/ucrypto/TestCICOWithGCM.java
Normal file
104
jdk/test/com/oracle/security/ucrypto/TestCICOWithGCM.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
118
jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java
Normal file
118
jdk/test/com/oracle/security/ucrypto/TestCICOWithGCMAndAAD.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
128
jdk/test/com/oracle/security/ucrypto/TestDigest.java
Normal file
128
jdk/test/com/oracle/security/ucrypto/TestDigest.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
179
jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java
Normal file
179
jdk/test/com/oracle/security/ucrypto/TestGCMKeyAndIvCheck.java
Normal file
@ -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!");
|
||||
}
|
||||
}
|
||||
|
86
jdk/test/com/oracle/security/ucrypto/TestGCMKeyWrap.java
Normal file
86
jdk/test/com/oracle/security/ucrypto/TestGCMKeyWrap.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
113
jdk/test/com/oracle/security/ucrypto/TestGCMWithSBE.java
Normal file
113
jdk/test/com/oracle/security/ucrypto/TestGCMWithSBE.java
Normal file
@ -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!");
|
||||
}
|
||||
}
|
||||
|
304
jdk/test/com/oracle/security/ucrypto/TestKATForGCM.java
Normal file
304
jdk/test/com/oracle/security/ucrypto/TestKATForGCM.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
||||
|
257
jdk/test/com/oracle/security/ucrypto/TestMalformedRSA.java
Normal file
257
jdk/test/com/oracle/security/ucrypto/TestMalformedRSA.java
Normal file
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
422
jdk/test/com/oracle/security/ucrypto/TestRSA.java
Normal file
422
jdk/test/com/oracle/security/ucrypto/TestRSA.java
Normal file
@ -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");
|
||||
}
|
||||
}
|
61
jdk/test/com/oracle/security/ucrypto/UcryptoTest.java
Normal file
61
jdk/test/com/oracle/security/ucrypto/UcryptoTest.java
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -100,6 +100,7 @@ public class StartManagementAgent {
|
||||
ex.printStackTrace(System.err);
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace(System.err);
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,6 +125,7 @@ public class StartManagementAgent {
|
||||
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 @@ public class StartManagementAgent {
|
||||
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 @@ public class StartManagementAgent {
|
||||
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 @@ public class StartManagementAgent {
|
||||
// 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 @@ public class StartManagementAgent {
|
||||
|
||||
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) {
|
||||
|
@ -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;
|
||||
|
@ -261,20 +261,20 @@ public class CipherTestUtils {
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
238
jdk/test/javax/sql/testng/test/rowset/RowSetWarningTests.java
Normal file
238
jdk/test/javax/sql/testng/test/rowset/RowSetWarningTests.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user