This commit is contained in:
Alejandro Murillo 2014-10-21 13:56:58 -07:00
commit f0c02512ea
54 changed files with 9756 additions and 73 deletions

@ -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

@ -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

@ -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;

@ -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);
}
}

@ -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);
}
}

@ -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);
}
}
}

@ -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);
}
}

@ -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);
}
}
}

@ -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;
}
}
}

@ -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();
}
}
}
}

@ -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;
}
}
}

@ -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();
}
}

@ -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;
}
}

@ -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;
}
}

@ -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; }
}

@ -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 \

@ -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");
}
}

@ -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);
}
}

@ -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;
}
}

@ -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");
}
}
}

@ -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();
}
}

@ -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");
}
}
}

@ -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!");
}
}

@ -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");
}
}
}

@ -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!");
}
}

@ -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");
}
}

@ -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();
}
}
}

@ -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");
}
}

@ -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,

@ -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();
}
}
}