--- a/jdk/make/com/sun/crypto/provider/Makefile Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/make/com/sun/crypto/provider/Makefile Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -87,8 +87,7 @@
# sign Alias for sign-jar
# sign-jar Builds/signs sunjce_provider.jar (no install)
#
-# obfus Builds/obfuscates/signs/installs
-# sunjce_provider.jar
+# obfus Builds/obfuscates/signs sunjce_provider.jar
#
# release Builds all targets in preparation
# for workspace integration.
@@ -101,8 +100,25 @@
BUILDDIR = ../../../..
PACKAGE = com.sun.crypto.provider
PRODUCT = sun
+
+#
+# The following is for when we need to do postprocessing
+# (signing/obfuscation) against a read-only build. If the OUTPUTDIR
+# isn't writable, the build currently crashes out.
+#
+ifndef OPENJDK
+ ifdef ALT_JCE_BUILD_DIR
+ # =====================================================
+ # Where to place the output, in case we're building from a read-only
+ # build area. (e.g. a release engineering build.)
+ JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
+ IGNORE_WRITABLE_OUTPUTDIR_TEST=true
+ else
+ JCE_BUILD_DIR=${TEMPDIR}
+ endif
+endif
+
include $(BUILDDIR)/common/Defs.gmk
-include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
#
# Location for the newly built classfiles.
@@ -147,6 +163,8 @@
#
UNSIGNED_DIR = $(TEMPDIR)/unsigned
+include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
+
# =====================================================
# Build the unsigned sunjce_provider.jar file.
@@ -184,44 +202,66 @@
# Sign the provider jar file. Not needed for OpenJDK.
#
-SIGNED_DIR = $(TEMPDIR)/signed
+SIGNED_DIR = $(JCE_BUILD_DIR)/signed
sign: sign-jar
sign-jar: $(SIGNED_DIR)/sunjce_provider.jar
+ifndef ALT_JCE_BUILD_DIR
$(SIGNED_DIR)/sunjce_provider.jar: $(UNSIGNED_DIR)/sunjce_provider.jar
- $(sign-file)
+else
+#
+# We have to remove the build dependency, otherwise, we'll try to rebuild it
+# which we can't do on a read-only filesystem.
+#
+$(SIGNED_DIR)/sunjce_provider.jar:
+ @if [ ! -r $(UNSIGNED_DIR)/sunjce_provider.jar ] ; then \
+ $(ECHO) "Couldn't find $(UNSIGNED_DIR)/sunjce_provider.jar"; \
+ exit 1; \
+ fi
+endif
+ $(call sign-file, $(UNSIGNED_DIR)/sunjce_provider.jar)
# =====================================================
# Obfuscate/sign/install the JDK build. Not needed for OpenJDK.
#
-OBFUS_DIR = $(TEMPDIR)/obfus
+OBFUS_DIR = $(JCE_BUILD_DIR)/obfus/sunjce
CLOSED_DIR = $(BUILDDIR)/closed/com/sun/crypto/provider
obfus: $(OBFUS_DIR)/sunjce_provider.jar
$(release-warning)
-$(OBFUS_DIR)/sunjce_provider.jar: build-jar $(JCE_MANIFEST_FILE)
+ifndef ALT_JCE_BUILD_DIR
+$(OBFUS_DIR)/sunjce_provider.jar: build-jar $(JCE_MANIFEST_FILE) \
+ $(OBFUS_DIR)/sunjce.dox
+else
+$(OBFUS_DIR)/sunjce_provider.jar: $(JCE_MANIFEST_FILE) $(OBFUS_DIR)/sunjce.dox
+ @if [ ! -d $(CLASSDESTDIR) ] ; then \
+ $(ECHO) "Couldn't find $(CLASSDESTDIR)"; \
+ exit 1; \
+ fi
+endif
+ @$(ECHO) ">>>Obfuscating SunJCE Provider..."
$(presign)
$(preobfus)
- @$(ECHO) ">>>Obfuscating Sun JCE Provider..."
$(prep-target)
$(CD) $(OBFUS_DIR); \
- $(OBFUSCATOR) -fv \
- $(CURRENT_DIRECTORY)/$(CLOSED_DIR)/obfus/sunjce.dox
+ $(OBFUSCATOR) -fv sunjce.dox
@$(CD) $(OBFUS_DIR); $(java-vm-cleanup)
$(BOOT_JAR_CMD) cmf $(JCE_MANIFEST_FILE) $@ \
-C $(OBFUS_DIR)/build com \
$(JAR_JFLAGS)
$(sign-target)
- $(MKDIR) -p $(dir $(JAR_DESTFILE))
- $(RM) $(JAR_DESTFILE)
- $(CP) $@ $(JAR_DESTFILE)
@$(java-vm-cleanup)
+$(OBFUS_DIR)/sunjce.dox: $(CLOSED_DIR)/obfus/sunjce.dox
+ @$(ECHO) ">>>Creating sunjce.dox"
+ $(prep-target)
+ $(SED) "s:@@TEMPDIR@@:$(ABS_TEMPDIR):" $< > $@
+
#
# The current obfuscator has a limitation in that it currently only
# supports up to v49 class file format. Force v49 classfiles in our
@@ -235,9 +275,9 @@
#
release: $(OBFUS_DIR)/sunjce_provider.jar
- $(RM) $(RELEASE_DIR)/sunjce_provider.jar
- $(MKDIR) -p $(RELEASE_DIR)
- $(CP) $(OBFUS_DIR)/sunjce_provider.jar $(RELEASE_DIR)
+ $(RM) $(JCE_BUILD_DIR)/release/sunjce_provider.jar
+ $(MKDIR) -p $(JCE_BUILD_DIR)/release
+ $(CP) $(OBFUS_DIR)/sunjce_provider.jar $(JCE_BUILD_DIR)/release
$(release-warning)
endif # OPENJDK
@@ -275,7 +315,7 @@
#
clobber clean::
- $(RM) -r $(JAR_DESTFILE) $(TEMPDIR)
+ $(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
.PHONY: build-jar jar install-jar
ifndef OPENJDK
--- a/jdk/make/common/shared/Defs.gmk Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/make/common/shared/Defs.gmk Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -449,11 +449,20 @@
# Check for spaces and null value
OUTPUTDIR:=$(call AltCheckSpaces,OUTPUTDIR)
OUTPUTDIR:=$(call AltCheckValue,OUTPUTDIR)
+
+#
+# When signing the JCE framework and provider, we could be using built
+# bits on a read-only filesystem. If so, this test will fail and crash
+# the build.
+#
+ifndef IGNORE_WRITABLE_OUTPUTDIR_TEST
# Create the output directory and make sure it exists and is writable
_create_outputdir:=$(shell $(MKDIR) -p "$(OUTPUTDIR)" > $(DEV_NULL) 2>&1)
ifeq ($(call WriteDirExists,$(OUTPUTDIR),/dev/null),/dev/null)
_outputdir_error:=$(error "ERROR: OUTPUTDIR '$(OUTPUTDIR)' not created or not writable")
endif
+endif
+
# Define absolute path if needed and check for spaces and null value
ifndef ABS_OUTPUTDIR
ABS_OUTPUTDIR:=$(call FullPath,$(OUTPUTDIR))
--- a/jdk/make/javax/crypto/Defs-jce.gmk Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/make/javax/crypto/Defs-jce.gmk Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -31,7 +31,7 @@
JCE_MANIFEST_FILE = $(TEMPDIR)/manifest.mf
$(JCE_MANIFEST_FILE): $(MAINMANIFEST)
$(prep-target)
- ( $(SED) "s/@@RELEASE@@/$(RELEASE)/" $(MAINMANIFEST); \
+ ( $(SED) "s/@@RELEASE@@/$(RELEASE)/" $<; \
$(ECHO) "Extension-Name: javax.crypto"; \
$(ECHO) "Implementation-Vendor-Id: com.sun"; ) > $@
@@ -75,6 +75,7 @@
define sign-target
$(BOOT_JARSIGNER_CMD) -keystore $(SIGNING_KEYSTORE) \
$@ $(SIGNING_ALIAS) < $(SIGNING_PASSPHRASE)
+ @$(java-vm-cleanup)
@$(ECHO) "\nJar codesigning finished."
endef
@@ -88,13 +89,15 @@
endef
#
-# Convenience macro for steps needed to sign a jar file.
+# Convenience macros for signing a jar file.
+#
+# Call through $(call sign-file, target file)
#
define sign-file
$(presign)
- $(install-file)
+ $(prep-target)
+ $(CP) $1 $@
$(sign-target)
- @$(java-vm-cleanup)
endef
#
--- a/jdk/make/javax/crypto/Makefile Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/make/javax/crypto/Makefile Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -96,7 +96,7 @@
# sign-jar Builds/signs jce.jar file (no install)
# sign-policy Builds/signs policy files (no install)
#
-# obfus Builds/obfuscates/signs/installs jce.jar
+# obfus Builds/obfuscates/signs jce.jar
#
# release Builds all targets in preparation
# for workspace integration.
@@ -110,8 +110,24 @@
PACKAGE = javax.crypto
PRODUCT = sun
+#
+# The following is for when we need to do postprocessing
+# (signing/obfuscation) against a read-only build. If the OUTPUTDIR
+# isn't writable, the build currently crashes out.
+#
+ifndef OPENJDK
+ ifdef ALT_JCE_BUILD_DIR
+ # =====================================================
+ # Where to place the output, in case we're building from a read-only
+ # build area. (e.g. a release engineering build.)
+ JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
+ IGNORE_WRITABLE_OUTPUTDIR_TEST=true
+ else
+ JCE_BUILD_DIR=${TEMPDIR}
+ endif
+endif
+
include $(BUILDDIR)/common/Defs.gmk
-include Defs-jce.gmk
#
# Location for the newly built classfiles.
@@ -158,6 +174,8 @@
#
UNSIGNED_DIR = $(TEMPDIR)/unsigned
+include Defs-jce.gmk
+
# =====================================================
# Build the unsigned jce.jar file. Signing/obfuscation comes later.
@@ -299,7 +317,7 @@
# Sign the various jar files. Not needed for OpenJDK.
#
-SIGNED_DIR = $(TEMPDIR)/signed
+SIGNED_DIR = $(JCE_BUILD_DIR)/signed
SIGNED_POLICY_BUILDDIR = $(SIGNED_DIR)/policy
SIGNED_POLICY_FILES = \
@@ -312,61 +330,87 @@
sign-policy: $(SIGNED_POLICY_FILES)
+ifndef ALT_JCE_BUILD_DIR
$(SIGNED_DIR)/jce.jar: $(UNSIGNED_DIR)/jce.jar
- $(sign-file)
+else
+#
+# We have to remove the build dependency, otherwise, we'll try to rebuild it
+# which we can't do on a read-only filesystem.
+#
+$(SIGNED_DIR)/jce.jar:
+ @if [ ! -r $(UNSIGNED_DIR)/jce.jar ] ; then \
+ $(ECHO) "Couldn't find $(UNSIGNED_DIR)/jce.jar"; \
+ exit 1; \
+ fi
+endif
+ $(call sign-file, $(UNSIGNED_DIR)/jce.jar)
$(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar: \
-$(UNSIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar
- $(sign-file)
+ $(UNSIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar
+ $(call sign-file, $<)
$(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar: \
-$(UNSIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar
- $(sign-file)
+ $(UNSIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar
+ $(call sign-file, $<)
$(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar: \
-$(UNSIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar
- $(sign-file)
+ $(UNSIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar
+ $(call sign-file, $<)
$(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar: \
-$(UNSIGNED_POLICY_BUILDDIR)/limited/local_policy.jar
- $(sign-file)
+ $(UNSIGNED_POLICY_BUILDDIR)/limited/local_policy.jar
+ $(call sign-file, $<)
# =====================================================
# Obfuscate/sign/install the JDK build. Not needed for OpenJDK.
#
-OBFUS_DIR = $(TEMPDIR)/obfus
+OBFUS_DIR = $(JCE_BUILD_DIR)/obfus/jce
CLOSED_DIR = $(BUILDDIR)/closed/javax/crypto
obfus: $(OBFUS_DIR)/jce.jar
$(release-warning)
-$(OBFUS_DIR)/jce.jar: build-jar $(JCE_MANIFEST_FILE)
+ifndef ALT_JCE_BUILD_DIR
+$(OBFUS_DIR)/jce.jar: build-jar $(JCE_MANIFEST_FILE) $(OBFUS_DIR)/framework.dox
+else
+#
+# We have to remove the build dependency, otherwise, we'll try to rebuild it
+# which we can't do on a read-only filesystem.
+#
+$(OBFUS_DIR)/jce.jar: $(JCE_MANIFEST_FILE) $(OBFUS_DIR)/framework.dox
+ @if [ ! -d $(CLASSDESTDIR) ] ; then \
+ $(ECHO) "Couldn't find $(CLASSDESTDIR)"; \
+ exit 1; \
+ fi
+endif
+ @$(ECHO) ">>>Obfuscating JCE framework..."
$(presign)
$(preobfus)
- @$(ECHO) ">>>Obfuscating JCE framework..."
$(prep-target)
$(CD) $(OBFUS_DIR); \
- $(OBFUSCATOR) -fv \
- $(CURRENT_DIRECTORY)/$(CLOSED_DIR)/obfus/framework.dox
+ $(OBFUSCATOR) -fv framework.dox
@$(CD) $(OBFUS_DIR); $(java-vm-cleanup)
+ @#
@# The sun.security.internal classes are currently not obfuscated
@# due to an obfus problem. Manually copy them to the build directory
@# so that they are included in the jce.jar file.
+ @#
$(CP) -r $(CLASSDESTDIR)/sun $(OBFUS_DIR)/build
- $(RM) $(UNSIGNED_DIR)/jce.jar
$(BOOT_JAR_CMD) cmf $(JCE_MANIFEST_FILE) $@ \
-C $(OBFUS_DIR)/build javax \
-C $(OBFUS_DIR)/build sun \
$(JAR_JFLAGS)
$(sign-target)
- $(MKDIR) -p $(dir $(JAR_DESTFILE))
- $(RM) $(JAR_DESTFILE)
- $(CP) $@ $(JAR_DESTFILE)
@$(java-vm-cleanup)
+$(OBFUS_DIR)/framework.dox: $(CLOSED_DIR)/obfus/framework.dox
+ @$(ECHO) ">>>Creating framework.dox"
+ $(prep-target)
+ $(SED) "s:@@TEMPDIR@@:$(ABS_TEMPDIR):" $< > $@
+
#
# The current obfuscator has a limitation in that it currently only
# supports up to v49 class file format. Force v49 classfiles in our
@@ -380,26 +424,27 @@
# unlimited policy file distribution, etc.
#
-release: $(OBFUS_DIR)/jce.jar sign-policy
+release: $(OBFUS_DIR)/jce.jar sign-policy $(CLOSED_DIR)/doc/COPYRIGHT.html \
+ $(CLOSED_DIR)/doc/README.txt
$(RM) -r \
- $(RELEASE_DIR)/UnlimitedJCEPolicy \
- $(RELEASE_DIR)/jce.jar \
- $(RELEASE_DIR)/US_export_policy.jar \
- $(RELEASE_DIR)/local_policy.jar \
- $(RELEASE_DIR)/UnlimitedJCEPolicy.zip
- $(MKDIR) -p $(RELEASE_DIR)/UnlimitedJCEPolicy
- $(CP) $(OBFUS_DIR)/jce.jar $(RELEASE_DIR)
- $(CP) -r \
- $(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar \
- $(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar \
- $(RELEASE_DIR)
+ $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy \
+ $(JCE_BUILD_DIR)/release/jce.jar \
+ $(JCE_BUILD_DIR)/release/US_export_policy.jar \
+ $(JCE_BUILD_DIR)/release/local_policy.jar \
+ $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy.zip
+ $(MKDIR) -p $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy
+ $(CP) $(OBFUS_DIR)/jce.jar $(JCE_BUILD_DIR)/release
+ $(CP) \
+ $(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar \
+ $(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar \
+ $(JCE_BUILD_DIR)/release
$(CP) \
$(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar \
- $(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar \
- $(RELEASE_DIR)/UnlimitedJCEPolicy
- $(CP) $(CLOSED_DIR)/doc/COPYRIGHT.html \
- $(CLOSED_DIR)/doc/README.txt $(RELEASE_DIR)/UnlimitedJCEPolicy
- cd $(RELEASE_DIR) ; \
+ $(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar \
+ $(CLOSED_DIR)/doc/COPYRIGHT.html \
+ $(CLOSED_DIR)/doc/README.txt \
+ $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy
+ cd $(JCE_BUILD_DIR)/release ; \
$(ZIPEXE) -qr UnlimitedJCEPolicy.zip UnlimitedJCEPolicy
$(release-warning)
@@ -478,7 +523,8 @@
clobber clean::
$(RM) -r $(JAR_DESTFILE) $(POLICY_DESTDIR)/US_export_policy.jar \
- $(POLICY_DESTDIR)/local_policy.jar $(DELETE_DIRS) $(TEMPDIR)
+ $(POLICY_DESTDIR)/local_policy.jar $(DELETE_DIRS) $(TEMPDIR) \
+ $(JCE_BUILD_DIR)
.PHONY: build-jar jar build-policy unlimited limited install-jar \
install-limited install-unlimited
--- a/jdk/make/sun/security/mscapi/Makefile Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/make/sun/security/mscapi/Makefile Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2005-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -92,8 +92,25 @@
PACKAGE = sun.security.mscapi
LIBRARY = sunmscapi
PRODUCT = sun
+
+#
+# The following is for when we need to do postprocessing
+# (signing/obfuscation) against a read-only build. If the OUTPUTDIR
+# isn't writable, the build currently crashes out.
+#
+ifndef OPENJDK
+ ifdef ALT_JCE_BUILD_DIR
+ # =====================================================
+ # Where to place the output, in case we're building from a read-only
+ # build area. (e.g. a release engineering build.)
+ JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
+ IGNORE_WRITABLE_OUTPUTDIR_TEST=true
+ else
+ JCE_BUILD_DIR=${TEMPDIR}
+ endif
+endif
+
include $(BUILDDIR)/common/Defs.gmk
-include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
CPLUSPLUSLIBRARY=true
@@ -163,6 +180,8 @@
$(build-warning)
endif
+include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
+
# =====================================================
# Build the unsigned sunmscapi.jar file.
@@ -200,14 +219,26 @@
# Sign the provider jar file. Not needed for OpenJDK.
#
-SIGNED_DIR = $(TEMPDIR)/signed
+SIGNED_DIR = $(JCE_BUILD_DIR)/signed
sign: sign-jar
sign-jar: $(SIGNED_DIR)/sunmscapi.jar
+ifndef ALT_JCE_BUILD_DIR
$(SIGNED_DIR)/sunmscapi.jar: $(UNSIGNED_DIR)/sunmscapi.jar
- $(sign-file)
+else
+#
+# We have to remove the build dependency, otherwise, we'll try to rebuild it
+# which we can't do on a read-only filesystem.
+#
+$(SIGNED_DIR)/sunmscapi.jar:
+ @if [ ! -r $(UNSIGNED_DIR)/sunmscapi.jar ] ; then \
+ $(ECHO) "Couldn't find $(UNSIGNED_DIR)/sunmscapi.jar"; \
+ exit 1; \
+ fi
+endif
+ $(call sign-file, $(UNSIGNED_DIR)/sunmscapi.jar)
# =====================================================
@@ -215,9 +246,9 @@
#
release: $(SIGNED_DIR)/sunmscapi.jar
- $(RM) $(RELEASE_DIR)/sunmscapi.jar
- $(MKDIR) -p $(RELEASE_DIR)
- $(CP) $(SIGNED_DIR)/sunmscapi.jar $(RELEASE_DIR)
+ $(RM) $(JCE_BUILD_DIR)/release/sunmscapi.jar
+ $(MKDIR) -p $(JCE_BUILD_DIR)/release
+ $(CP) $(SIGNED_DIR)/sunmscapi.jar $(JCE_BUILD_DIR)/release
$(release-warning)
endif # OPENJDK
@@ -255,7 +286,7 @@
#
clobber clean::
- $(RM) -r $(JAR_DESTFILE) $(TEMPDIR)
+ $(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
.PHONY: build-jar jar install-jar
ifndef OPENJDK
--- a/jdk/make/sun/security/pkcs11/Makefile Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/make/sun/security/pkcs11/Makefile Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
#
-# Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+# Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@@ -92,8 +92,25 @@
PACKAGE = sun.security.pkcs11
LIBRARY = j2pkcs11
PRODUCT = sun
+
+#
+# The following is for when we need to do postprocessing
+# (signing/obfuscation) against a read-only build. If the OUTPUTDIR
+# isn't writable, the build currently crashes out.
+#
+ifndef OPENJDK
+ ifdef ALT_JCE_BUILD_DIR
+ # =====================================================
+ # Where to place the output, in case we're building from a read-only
+ # build area. (e.g. a release engineering build.)
+ JCE_BUILD_DIR=${ALT_JCE_BUILD_DIR}
+ IGNORE_WRITABLE_OUTPUTDIR_TEST=true
+ else
+ JCE_BUILD_DIR=${TEMPDIR}
+ endif
+endif
+
include $(BUILDDIR)/common/Defs.gmk
-include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
#
# C and Java Files
@@ -163,6 +180,8 @@
$(build-warning)
endif
+include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
+
# =====================================================
# Build the unsigned sunpkcs11.jar file.
@@ -200,14 +219,26 @@
# Sign the provider jar file. Not needed for OpenJDK.
#
-SIGNED_DIR = $(TEMPDIR)/signed
+SIGNED_DIR = $(JCE_BUILD_DIR)/signed
sign: sign-jar
sign-jar: $(SIGNED_DIR)/sunpkcs11.jar
+ifndef ALT_JCE_BUILD_DIR
$(SIGNED_DIR)/sunpkcs11.jar: $(UNSIGNED_DIR)/sunpkcs11.jar
- $(sign-file)
+else
+#
+# We have to remove the build dependency, otherwise, we'll try to rebuild it
+# which we can't do on a read-only filesystem.
+#
+$(SIGNED_DIR)/sunpkcs11.jar:
+ @if [ ! -r $(UNSIGNED_DIR)/sunpkcs11.jar ] ; then \
+ $(ECHO) "Couldn't find $(UNSIGNED_DIR)/sunpkcs11.jar"; \
+ exit 1; \
+ fi
+endif
+ $(call sign-file, $(UNSIGNED_DIR)/sunpkcs11.jar)
# =====================================================
@@ -215,9 +246,9 @@
#
release: $(SIGNED_DIR)/sunpkcs11.jar
- $(RM) $(RELEASE_DIR)/sunpkcs11.jar
- $(MKDIR) -p $(RELEASE_DIR)
- $(CP) $(SIGNED_DIR)/sunpkcs11.jar $(RELEASE_DIR)
+ $(RM) $(JCE_BUILD_DIR)/release/sunpkcs11.jar
+ $(MKDIR) -p $(JCE_BUILD_DIR)/release
+ $(CP) $(SIGNED_DIR)/sunpkcs11.jar $(JCE_BUILD_DIR)/release
$(release-warning)
endif # OPENJDK
@@ -255,7 +286,7 @@
#
clobber clean::
- $(RM) -r $(JAR_DESTFILE) $(TEMPDIR)
+ $(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
.PHONY: build-jar jar install-jar
ifndef OPENJDK
--- a/jdk/src/share/classes/sun/net/www/protocol/http/NegotiatorImpl.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/net/www/protocol/http/NegotiatorImpl.java Mon Apr 07 14:19:23 2008 -0700
@@ -91,9 +91,10 @@
GSSManagerImpl manager = new GSSManagerImpl(
GSSUtil.CALLER_HTTP_NEGOTIATE);
- String peerName = "HTTP/" + hostname;
+ String peerName = "HTTP@" + hostname;
- GSSName serverName = manager.createName(peerName, null);
+ GSSName serverName = manager.createName(peerName,
+ GSSName.NT_HOSTBASED_SERVICE);
context = manager.createContext(serverName,
oid,
null,
--- a/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11Cipher.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -22,10 +22,10 @@
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
-
package sun.security.pkcs11;
import java.nio.ByteBuffer;
+import java.util.Arrays;
import java.security.*;
import java.security.spec.*;
@@ -34,7 +34,6 @@
import javax.crypto.spec.*;
import sun.nio.ch.DirectBuffer;
-
import sun.security.pkcs11.wrapper.*;
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
@@ -43,8 +42,8 @@
* DES, DESede, AES, ARCFOUR, and Blowfish.
*
* This class is designed to support ECB and CBC with NoPadding and
- * PKCS5Padding for both. However, currently only CBC/NoPadding (and
- * ECB/NoPadding for stream ciphers) is functional.
+ * PKCS5Padding for both. It will use its own padding impl if the
+ * native mechanism does not support padding.
*
* Note that PKCS#11 current only supports ECB and CBC. There are no
* provisions for other modes such as CFB, OFB, PCBC, or CTR mode.
@@ -62,10 +61,59 @@
private final static int MODE_CBC = 4;
// padding constant for NoPadding
- private final static int PAD_NONE = 5;
+ private final static int PAD_NONE = 5;
// padding constant for PKCS5Padding
private final static int PAD_PKCS5 = 6;
+ private static interface Padding {
+ // ENC: format the specified buffer with padding bytes and return the
+ // actual padding length
+ int setPaddingBytes(byte[] paddingBuffer, int padLen);
+
+ // DEC: return the length of trailing padding bytes given the specified
+ // padded data
+ int unpad(byte[] paddedData, int len)
+ throws BadPaddingException;
+ }
+
+ private static class PKCS5Padding implements Padding {
+
+ private final int blockSize;
+
+ PKCS5Padding(int blockSize)
+ throws NoSuchPaddingException {
+ if (blockSize == 0) {
+ throw new NoSuchPaddingException
+ ("PKCS#5 padding not supported with stream ciphers");
+ }
+ this.blockSize = blockSize;
+ }
+
+ public int setPaddingBytes(byte[] paddingBuffer, int padLen) {
+ Arrays.fill(paddingBuffer, 0, padLen, (byte) (padLen & 0x007f));
+ return padLen;
+ }
+
+ public int unpad(byte[] paddedData, int len)
+ throws BadPaddingException {
+ if (len < 1 || len > paddedData.length) {
+ throw new BadPaddingException("Invalid pad array length!");
+ }
+ byte padValue = paddedData[len - 1];
+ if (padValue < 1 || padValue > blockSize) {
+ throw new BadPaddingException("Invalid pad value!");
+ }
+ // sanity check padding bytes
+ int padStartIndex = len - padValue;
+ for (int i = padStartIndex; i < len; i++) {
+ if (paddedData[i] != padValue) {
+ throw new BadPaddingException("Invalid pad bytes!");
+ }
+ }
+ return padValue;
+ }
+ }
+
// token instance
private final Token token;
@@ -99,65 +147,93 @@
// padding type, on of PAD_* above (PAD_NONE for stream ciphers)
private int paddingType;
+ // when the padding is requested but unsupported by the native mechanism,
+ // we use the following to do padding and necessary data buffering.
+ // padding object which generate padding and unpad the decrypted data
+ private Padding paddingObj;
+ // buffer for holding back the block which contains padding bytes
+ private byte[] padBuffer;
+ private int padBufferLen;
+
// original IV, if in MODE_CBC
private byte[] iv;
- // total number of bytes processed
- private int bytesProcessed;
+ // number of bytes buffered internally by the native mechanism and padBuffer
+ // if we do the padding
+ private int bytesBuffered;
P11Cipher(Token token, String algorithm, long mechanism)
- throws PKCS11Exception {
+ throws PKCS11Exception, NoSuchAlgorithmException {
super();
this.token = token;
this.algorithm = algorithm;
this.mechanism = mechanism;
- keyAlgorithm = algorithm.split("/")[0];
+
+ String algoParts[] = algorithm.split("/");
+ keyAlgorithm = algoParts[0];
+
if (keyAlgorithm.equals("AES")) {
blockSize = 16;
- blockMode = MODE_CBC;
- // XXX change default to PKCS5Padding
- paddingType = PAD_NONE;
- } else if (keyAlgorithm.equals("RC4") || keyAlgorithm.equals("ARCFOUR")) {
+ } else if (keyAlgorithm.equals("RC4") ||
+ keyAlgorithm.equals("ARCFOUR")) {
blockSize = 0;
- blockMode = MODE_ECB;
- paddingType = PAD_NONE;
} else { // DES, DESede, Blowfish
blockSize = 8;
- blockMode = MODE_CBC;
- // XXX change default to PKCS5Padding
- paddingType = PAD_NONE;
+ }
+ this.blockMode =
+ (algoParts.length > 1 ? parseMode(algoParts[1]) : MODE_ECB);
+
+ String defPadding = (blockSize == 0 ? "NoPadding" : "PKCS5Padding");
+ String paddingStr =
+ (algoParts.length > 2 ? algoParts[2] : defPadding);
+ try {
+ engineSetPadding(paddingStr);
+ } catch (NoSuchPaddingException nspe) {
+ // should not happen
+ throw new ProviderException(nspe);
}
session = token.getOpSession();
}
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);
+ }
+
+ private int parseMode(String mode) throws NoSuchAlgorithmException {
mode = mode.toUpperCase();
+ int result;
if (mode.equals("ECB")) {
- this.blockMode = MODE_ECB;
+ result = MODE_ECB;
} else if (mode.equals("CBC")) {
if (blockSize == 0) {
throw new NoSuchAlgorithmException
("CBC mode not supported with stream ciphers");
}
- this.blockMode = MODE_CBC;
+ result = MODE_CBC;
} else {
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
}
+ return result;
}
// see JCE spec
protected void engineSetPadding(String padding)
throws NoSuchPaddingException {
- if (padding.equalsIgnoreCase("NoPadding")) {
+ paddingObj = null;
+ padBuffer = null;
+ padding = padding.toUpperCase();
+ if (padding.equals("NOPADDING")) {
paddingType = PAD_NONE;
- } else if (padding.equalsIgnoreCase("PKCS5Padding")) {
- if (blockSize == 0) {
- throw new NoSuchPaddingException
- ("PKCS#5 padding not supported with stream ciphers");
+ } else if (padding.equals("PKCS5PADDING")) {
+ paddingType = PAD_PKCS5;
+ if (mechanism != CKM_DES_CBC_PAD && mechanism != CKM_DES3_CBC_PAD &&
+ mechanism != CKM_AES_CBC_PAD) {
+ // no native padding support; use our own padding impl
+ paddingObj = new PKCS5Padding(blockSize);
+ padBuffer = new byte[blockSize];
}
- paddingType = PAD_PKCS5;
- // XXX PKCS#5 not yet implemented
- throw new NoSuchPaddingException("pkcs5");
} else {
throw new NoSuchPaddingException("Unsupported padding " + padding);
}
@@ -175,7 +251,7 @@
// see JCE spec
protected byte[] engineGetIV() {
- return (iv == null) ? null : (byte[])iv.clone();
+ return (iv == null) ? null : (byte[]) iv.clone();
}
// see JCE spec
@@ -185,8 +261,9 @@
}
IvParameterSpec ivSpec = new IvParameterSpec(iv);
try {
- AlgorithmParameters params = AlgorithmParameters.getInstance
- (keyAlgorithm, P11Util.getSunJceProvider());
+ AlgorithmParameters params =
+ AlgorithmParameters.getInstance(keyAlgorithm,
+ P11Util.getSunJceProvider());
params.init(ivSpec);
return params;
} catch (GeneralSecurityException e) {
@@ -210,38 +287,38 @@
protected void engineInit(int opmode, Key key,
AlgorithmParameterSpec params, SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- byte[] iv;
+ byte[] ivValue;
if (params != null) {
if (params instanceof IvParameterSpec == false) {
throw new InvalidAlgorithmParameterException
("Only IvParameterSpec supported");
}
- IvParameterSpec ivSpec = (IvParameterSpec)params;
- iv = ivSpec.getIV();
+ IvParameterSpec ivSpec = (IvParameterSpec) params;
+ ivValue = ivSpec.getIV();
} else {
- iv = null;
+ ivValue = null;
}
- implInit(opmode, key, iv, random);
+ implInit(opmode, key, ivValue, random);
}
// see JCE spec
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException {
- byte[] iv;
+ byte[] ivValue;
if (params != null) {
try {
IvParameterSpec ivSpec = (IvParameterSpec)
params.getParameterSpec(IvParameterSpec.class);
- iv = ivSpec.getIV();
+ ivValue = ivSpec.getIV();
} catch (InvalidParameterSpecException e) {
throw new InvalidAlgorithmParameterException
("Could not decode IV", e);
}
} else {
- iv = null;
+ ivValue = null;
}
- implInit(opmode, key, iv, random);
+ implInit(opmode, key, ivValue, random);
}
// actual init() implementation
@@ -250,31 +327,31 @@
throws InvalidKeyException, InvalidAlgorithmParameterException {
cancelOperation();
switch (opmode) {
- case Cipher.ENCRYPT_MODE:
- encrypt = true;
- break;
- case Cipher.DECRYPT_MODE:
- encrypt = false;
- break;
- default:
- throw new InvalidAlgorithmParameterException
- ("Unsupported mode: " + opmode);
+ case Cipher.ENCRYPT_MODE:
+ encrypt = true;
+ break;
+ case Cipher.DECRYPT_MODE:
+ encrypt = false;
+ break;
+ default:
+ throw new InvalidAlgorithmParameterException
+ ("Unsupported mode: " + opmode);
}
if (blockMode == MODE_ECB) { // ECB or stream cipher
if (iv != null) {
if (blockSize == 0) {
throw new InvalidAlgorithmParameterException
- ("IV not used with stream ciphers");
+ ("IV not used with stream ciphers");
} else {
throw new InvalidAlgorithmParameterException
- ("IV not used in ECB mode");
+ ("IV not used in ECB mode");
}
}
} else { // MODE_CBC
if (iv == null) {
if (encrypt == false) {
throw new InvalidAlgorithmParameterException
- ("IV must be specified for decryption in CBC mode");
+ ("IV must be specified for decryption in CBC mode");
}
// generate random IV
if (random == null) {
@@ -285,7 +362,7 @@
} else {
if (iv.length != blockSize) {
throw new InvalidAlgorithmParameterException
- ("IV length must match block size");
+ ("IV length must match block size");
}
}
}
@@ -331,63 +408,43 @@
session = token.getOpSession();
}
if (encrypt) {
- token.p11.C_EncryptInit
- (session.id(), new CK_MECHANISM(mechanism, iv), p11Key.keyID);
+ token.p11.C_EncryptInit(session.id(),
+ new CK_MECHANISM(mechanism, iv), p11Key.keyID);
} else {
- token.p11.C_DecryptInit
- (session.id(), new CK_MECHANISM(mechanism, iv), p11Key.keyID);
+ token.p11.C_DecryptInit(session.id(),
+ new CK_MECHANISM(mechanism, iv), p11Key.keyID);
}
- bytesProcessed = 0;
+ bytesBuffered = 0;
+ padBufferLen = 0;
initialized = true;
}
- // XXX the calculations below assume the PKCS#11 implementation is smart.
- // conceivably, not all implementations are and we may need to estimate
- // more conservatively
-
- private int bytesBuffered(int totalLen) {
- if (paddingType == PAD_NONE) {
- // with NoPadding, buffer only the current unfinished block
- return totalLen & (blockSize - 1);
- } else { // PKCS5
- // with PKCS5Padding in decrypt mode, the buffer must never
- // be empty. Buffer a full block instead of nothing.
- int buffered = totalLen & (blockSize - 1);
- if ((buffered == 0) && (encrypt == false)) {
- buffered = blockSize;
- }
- return buffered;
- }
- }
-
// if update(inLen) is called, how big does the output buffer have to be?
private int updateLength(int inLen) {
if (inLen <= 0) {
return 0;
}
- if (blockSize == 0) {
- return inLen;
- } else {
- // bytes that need to be buffered now
- int buffered = bytesBuffered(bytesProcessed);
- // bytes that need to be buffered after this update
- int newBuffered = bytesBuffered(bytesProcessed + inLen);
- return inLen + buffered - newBuffered;
+
+ int result = inLen + bytesBuffered;
+ if (blockSize != 0) {
+ // minus the number of bytes in the last incomplete block.
+ result -= (result & (blockSize - 1));
}
+ return result;
}
// if doFinal(inLen) is called, how big does the output buffer have to be?
private int doFinalLength(int inLen) {
- if (paddingType == PAD_NONE) {
- return updateLength(inLen);
- }
if (inLen < 0) {
return 0;
}
- int buffered = bytesBuffered(bytesProcessed);
- int newProcessed = bytesProcessed + inLen;
- int paddedProcessed = (newProcessed + blockSize) & ~(blockSize - 1);
- return paddedProcessed - bytesProcessed + buffered;
+
+ int result = inLen + bytesBuffered;
+ if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
+ // add the number of bytes to make the last block complete.
+ result += (blockSize - (result & (blockSize - 1)));
+ }
+ return result;
}
// see JCE spec
@@ -397,6 +454,7 @@
int n = engineUpdate(in, inOfs, inLen, out, 0);
return P11Util.convert(out, 0, n);
} catch (ShortBufferException e) {
+ // convert since the output length is calculated by updateLength()
throw new ProviderException(e);
}
}
@@ -409,6 +467,7 @@
}
// see JCE spec
+ @Override
protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
throws ShortBufferException {
return implUpdate(inBuffer, outBuffer);
@@ -422,14 +481,15 @@
int n = engineDoFinal(in, inOfs, inLen, out, 0);
return P11Util.convert(out, 0, n);
} catch (ShortBufferException e) {
+ // convert since the output length is calculated by doFinalLength()
throw new ProviderException(e);
}
}
// see JCE spec
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
- int outOfs) throws ShortBufferException, IllegalBlockSizeException {
- // BadPaddingException {
+ int outOfs) throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
int n = 0;
if ((inLen != 0) && (in != null)) {
n = engineUpdate(in, inOfs, inLen, out, outOfs);
@@ -440,8 +500,10 @@
}
// see JCE spec
+ @Override
protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
- throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
int n = engineUpdate(inBuffer, outBuffer);
n += implDoFinal(outBuffer);
return n;
@@ -454,18 +516,55 @@
}
try {
ensureInitialized();
- int k;
+ int k = 0;
if (encrypt) {
- k = token.p11.C_EncryptUpdate
- (session.id(), 0, in, inOfs, inLen, 0, out, outOfs, outLen);
+ k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen,
+ 0, out, outOfs, outLen);
} else {
- k = token.p11.C_DecryptUpdate
- (session.id(), 0, in, inOfs, inLen, 0, out, outOfs, outLen);
+ int newPadBufferLen = 0;
+ if (paddingObj != null) {
+ if (padBufferLen != 0) {
+ // NSS throws up when called with data not in multiple
+ // of blocks. Try to work around this by holding the
+ // extra data in padBuffer.
+ if (padBufferLen != padBuffer.length) {
+ int bufCapacity = padBuffer.length - padBufferLen;
+ if (inLen > bufCapacity) {
+ bufferInputBytes(in, inOfs, bufCapacity);
+ inOfs += bufCapacity;
+ inLen -= bufCapacity;
+ } else {
+ bufferInputBytes(in, inOfs, inLen);
+ return 0;
+ }
+ }
+ k = token.p11.C_DecryptUpdate(session.id(),
+ 0, padBuffer, 0, padBufferLen,
+ 0, out, outOfs, outLen);
+ padBufferLen = 0;
+ }
+ newPadBufferLen = inLen & (blockSize - 1);
+ if (newPadBufferLen == 0) {
+ newPadBufferLen = padBuffer.length;
+ }
+ inLen -= newPadBufferLen;
+ }
+ if (inLen > 0) {
+ k += token.p11.C_DecryptUpdate(session.id(), 0, in, inOfs,
+ inLen, 0, out, (outOfs + k), (outLen - k));
+ }
+ // update 'padBuffer' if using our own padding impl.
+ if (paddingObj != null) {
+ bufferInputBytes(in, inOfs + inLen, newPadBufferLen);
+ }
}
- bytesProcessed += inLen;
+ bytesBuffered += (inLen - k);
return k;
} catch (PKCS11Exception e) {
- // XXX throw correct exception
+ if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
+ throw (ShortBufferException)
+ (new ShortBufferException().initCause(e));
+ }
throw new ProviderException("update() failed", e);
}
}
@@ -481,101 +580,167 @@
if (outLen < updateLength(inLen)) {
throw new ShortBufferException();
}
- boolean inPosChanged = false;
+ int origPos = inBuffer.position();
try {
ensureInitialized();
long inAddr = 0;
- int inOfs = inBuffer.position();
+ int inOfs = 0;
byte[] inArray = null;
+
if (inBuffer instanceof DirectBuffer) {
- inAddr = ((DirectBuffer)inBuffer).address();
- } else {
- if (inBuffer.hasArray()) {
- inArray = inBuffer.array();
- inOfs += inBuffer.arrayOffset();
- } else {
- inArray = new byte[inLen];
- inBuffer.get(inArray);
- inOfs = 0;
- inPosChanged = true;
- }
+ inAddr = ((DirectBuffer) inBuffer).address();
+ inOfs = origPos;
+ } else if (inBuffer.hasArray()) {
+ inArray = inBuffer.array();
+ inOfs = (origPos + inBuffer.arrayOffset());
}
long outAddr = 0;
- int outOfs = outBuffer.position();
+ int outOfs = 0;
byte[] outArray = null;
if (outBuffer instanceof DirectBuffer) {
- outAddr = ((DirectBuffer)outBuffer).address();
+ outAddr = ((DirectBuffer) outBuffer).address();
+ outOfs = outBuffer.position();
} else {
if (outBuffer.hasArray()) {
outArray = outBuffer.array();
- outOfs += outBuffer.arrayOffset();
+ outOfs = (outBuffer.position() + outBuffer.arrayOffset());
} else {
outArray = new byte[outLen];
- outOfs = 0;
}
}
- int k;
+ int k = 0;
if (encrypt) {
- k = token.p11.C_EncryptUpdate
- (session.id(), inAddr, inArray, inOfs, inLen,
- outAddr, outArray, outOfs, outLen);
+ if (inAddr == 0 && inArray == null) {
+ inArray = new byte[inLen];
+ inBuffer.get(inArray);
+ } else {
+ inBuffer.position(origPos + inLen);
+ }
+ k = token.p11.C_EncryptUpdate(session.id(),
+ inAddr, inArray, inOfs, inLen,
+ outAddr, outArray, outOfs, outLen);
} else {
- k = token.p11.C_DecryptUpdate
- (session.id(), inAddr, inArray, inOfs, inLen,
- outAddr, outArray, outOfs, outLen);
+ int newPadBufferLen = 0;
+ if (paddingObj != null) {
+ if (padBufferLen != 0) {
+ // NSS throws up when called with data not in multiple
+ // of blocks. Try to work around this by holding the
+ // extra data in padBuffer.
+ if (padBufferLen != padBuffer.length) {
+ int bufCapacity = padBuffer.length - padBufferLen;
+ if (inLen > bufCapacity) {
+ bufferInputBytes(inBuffer, bufCapacity);
+ inOfs += bufCapacity;
+ inLen -= bufCapacity;
+ } else {
+ bufferInputBytes(inBuffer, inLen);
+ return 0;
+ }
+ }
+ k = token.p11.C_DecryptUpdate(session.id(), 0,
+ padBuffer, 0, padBufferLen, outAddr, outArray,
+ outOfs, outLen);
+ padBufferLen = 0;
+ }
+ newPadBufferLen = inLen & (blockSize - 1);
+ if (newPadBufferLen == 0) {
+ newPadBufferLen = padBuffer.length;
+ }
+ inLen -= newPadBufferLen;
+ }
+ if (inLen > 0) {
+ if (inAddr == 0 && inArray == null) {
+ inArray = new byte[inLen];
+ inBuffer.get(inArray);
+ } else {
+ inBuffer.position(inBuffer.position() + inLen);
+ }
+ k += token.p11.C_DecryptUpdate(session.id(), inAddr,
+ inArray, inOfs, inLen, outAddr, outArray,
+ (outOfs + k), (outLen - k));
+ }
+ // update 'padBuffer' if using our own padding impl.
+ if (paddingObj != null && newPadBufferLen != 0) {
+ bufferInputBytes(inBuffer, newPadBufferLen);
+ }
}
- bytesProcessed += inLen;
- if (!inPosChanged) {
- inBuffer.position(inBuffer.position() + inLen);
- }
+ bytesBuffered += (inLen - k);
if (!(outBuffer instanceof DirectBuffer) &&
- !outBuffer.hasArray()) {
+ !outBuffer.hasArray()) {
outBuffer.put(outArray, outOfs, k);
} else {
outBuffer.position(outBuffer.position() + k);
}
return k;
} catch (PKCS11Exception e) {
- // Un-read the bytes back to input buffer
- if (inPosChanged) {
- inBuffer.position(inBuffer.position() - inLen);
+ // Reset input buffer to its original position for
+ inBuffer.position(origPos);
+ if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
+ throw (ShortBufferException)
+ (new ShortBufferException().initCause(e));
}
- // XXX throw correct exception
throw new ProviderException("update() failed", e);
}
}
private int implDoFinal(byte[] out, int outOfs, int outLen)
- throws ShortBufferException, IllegalBlockSizeException {
- if (outLen < doFinalLength(0)) {
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
+ int requiredOutLen = doFinalLength(0);
+ if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
try {
ensureInitialized();
+ int k = 0;
if (encrypt) {
- return token.p11.C_EncryptFinal
- (session.id(), 0, out, outOfs, outLen);
+ if (paddingObj != null) {
+ int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
+ requiredOutLen - bytesBuffered);
+ k = token.p11.C_EncryptUpdate(session.id(),
+ 0, padBuffer, 0, actualPadLen,
+ 0, out, outOfs, outLen);
+ }
+ k += token.p11.C_EncryptFinal(session.id(),
+ 0, out, (outOfs + k), (outLen - k));
} else {
- return token.p11.C_DecryptFinal
- (session.id(), 0, out, outOfs, outLen);
+ if (paddingObj != null) {
+ if (padBufferLen != 0) {
+ k = token.p11.C_DecryptUpdate(session.id(), 0,
+ padBuffer, 0, padBufferLen, 0, padBuffer, 0,
+ padBuffer.length);
+ }
+ k += token.p11.C_DecryptFinal(session.id(), 0, padBuffer, k,
+ padBuffer.length - k);
+ int actualPadLen = paddingObj.unpad(padBuffer, k);
+ k -= actualPadLen;
+ System.arraycopy(padBuffer, 0, out, outOfs, k);
+ } else {
+ k = token.p11.C_DecryptFinal(session.id(), 0, out, outOfs,
+ outLen);
+ }
}
+ return k;
} catch (PKCS11Exception e) {
handleException(e);
throw new ProviderException("doFinal() failed", e);
} finally {
initialized = false;
- bytesProcessed = 0;
+ bytesBuffered = 0;
+ padBufferLen = 0;
session = token.releaseSession(session);
}
}
private int implDoFinal(ByteBuffer outBuffer)
- throws ShortBufferException, IllegalBlockSizeException {
+ throws ShortBufferException, IllegalBlockSizeException,
+ BadPaddingException {
int outLen = outBuffer.remaining();
- if (outLen < doFinalLength(0)) {
+ int requiredOutLen = doFinalLength(0);
+ if (outLen < requiredOutLen) {
throw new ShortBufferException();
}
@@ -583,30 +748,54 @@
ensureInitialized();
long outAddr = 0;
- int outOfs = outBuffer.position();
byte[] outArray = null;
+ int outOfs = 0;
if (outBuffer instanceof DirectBuffer) {
- outAddr = ((DirectBuffer)outBuffer).address();
+ outAddr = ((DirectBuffer) outBuffer).address();
+ outOfs = outBuffer.position();
} else {
if (outBuffer.hasArray()) {
outArray = outBuffer.array();
- outOfs += outBuffer.arrayOffset();
+ outOfs = outBuffer.position() + outBuffer.arrayOffset();
} else {
outArray = new byte[outLen];
- outOfs = 0;
}
}
- int k;
+ int k = 0;
+
if (encrypt) {
- k = token.p11.C_EncryptFinal
- (session.id(), outAddr, outArray, outOfs, outLen);
+ if (paddingObj != null) {
+ int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
+ requiredOutLen - bytesBuffered);
+ k = token.p11.C_EncryptUpdate(session.id(),
+ 0, padBuffer, 0, actualPadLen,
+ outAddr, outArray, outOfs, outLen);
+ }
+ k += token.p11.C_EncryptFinal(session.id(),
+ outAddr, outArray, (outOfs + k), (outLen - k));
} else {
- k = token.p11.C_DecryptFinal
- (session.id(), outAddr, outArray, outOfs, outLen);
+ if (paddingObj != null) {
+ if (padBufferLen != 0) {
+ k = token.p11.C_DecryptUpdate(session.id(),
+ 0, padBuffer, 0, padBufferLen,
+ 0, padBuffer, 0, padBuffer.length);
+ padBufferLen = 0;
+ }
+ k += token.p11.C_DecryptFinal(session.id(),
+ 0, padBuffer, k, padBuffer.length - k);
+ int actualPadLen = paddingObj.unpad(padBuffer, k);
+ k -= actualPadLen;
+ outArray = padBuffer;
+ outOfs = 0;
+ } else {
+ k = token.p11.C_DecryptFinal(session.id(),
+ outAddr, outArray, outOfs, outLen);
+ }
}
- if (!(outBuffer instanceof DirectBuffer) &&
- !outBuffer.hasArray()) {
+ if ((!encrypt && paddingObj != null) ||
+ (!(outBuffer instanceof DirectBuffer) &&
+ !outBuffer.hasArray())) {
outBuffer.put(outArray, outOfs, k);
} else {
outBuffer.position(outBuffer.position() + k);
@@ -617,20 +806,22 @@
throw new ProviderException("doFinal() failed", e);
} finally {
initialized = false;
- bytesProcessed = 0;
+ bytesBuffered = 0;
session = token.releaseSession(session);
}
}
private void handleException(PKCS11Exception e)
- throws IllegalBlockSizeException {
+ throws ShortBufferException, IllegalBlockSizeException {
long errorCode = e.getErrorCode();
- // XXX better check
- if (errorCode == CKR_DATA_LEN_RANGE) {
- throw (IllegalBlockSizeException)new
- IllegalBlockSizeException(e.toString()).initCause(e);
+ if (errorCode == CKR_BUFFER_TOO_SMALL) {
+ throw (ShortBufferException)
+ (new ShortBufferException().initCause(e));
+ } else if (errorCode == CKR_DATA_LEN_RANGE ||
+ errorCode == CKR_ENCRYPTED_DATA_LEN_RANGE) {
+ throw (IllegalBlockSizeException)
+ (new IllegalBlockSizeException(e.toString()).initCause(e));
}
-
}
// see JCE spec
@@ -649,12 +840,14 @@
}
// see JCE spec
+ @Override
protected int engineGetKeySize(Key key) throws InvalidKeyException {
int n = P11SecretKeyFactory.convertKey
- (token, key, keyAlgorithm).keyLength();
+ (token, key, keyAlgorithm).keyLength();
return n;
}
+ @Override
protected void finalize() throws Throwable {
try {
if ((session != null) && token.isValid()) {
@@ -666,4 +859,15 @@
}
}
+ private final void bufferInputBytes(byte[] in, int inOfs, int len) {
+ System.arraycopy(in, inOfs, padBuffer, padBufferLen, len);
+ padBufferLen += len;
+ bytesBuffered += len;
+ }
+
+ private final void bufferInputBytes(ByteBuffer inBuffer, int len) {
+ inBuffer.get(padBuffer, padBufferLen, len);
+ padBufferLen += len;
+ bytesBuffered += len;
+ }
}
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyGenerator.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,10 +65,86 @@
// are supported.
private boolean supportBothKeySizes;
- // min and max key sizes (in bits) for variable-key-length
- // algorithms, e.g. RC4 and Blowfish
- private int minKeySize;
- private int maxKeySize;
+ /**
+ * Utility method for checking if the specified key size is valid
+ * and within the supported range. Return the significant key size
+ * upon successful validation.
+ * @param keyGenMech the PKCS#11 key generation mechanism.
+ * @param keySize the to-be-checked key size for this mechanism.
+ * @param token token which provides this mechanism.
+ * @return the significant key size (in bits) corresponding to the
+ * specified key size.
+ * @throws InvalidParameterException if the specified key size is invalid.
+ * @throws ProviderException if this mechanism isn't supported by SunPKCS11
+ * or underlying native impl.
+ */
+ static int checkKeySize(long keyGenMech, int keySize, Token token)
+ throws InvalidAlgorithmParameterException, ProviderException {
+ int sigKeySize;
+ switch ((int)keyGenMech) {
+ case (int)CKM_DES_KEY_GEN:
+ if ((keySize != 64) && (keySize != 56)) {
+ throw new InvalidAlgorithmParameterException
+ ("DES key length must be 56 bits");
+ }
+ sigKeySize = 56;
+ break;
+ case (int)CKM_DES2_KEY_GEN:
+ case (int)CKM_DES3_KEY_GEN:
+ if ((keySize == 112) || (keySize == 128)) {
+ sigKeySize = 112;
+ } else if ((keySize == 168) || (keySize == 192)) {
+ sigKeySize = 168;
+ } else {
+ throw new InvalidAlgorithmParameterException
+ ("DESede key length must be 112, or 168 bits");
+ }
+ break;
+ default:
+ // Handle all variable-key-length algorithms here
+ CK_MECHANISM_INFO info = null;
+ try {
+ info = token.getMechanismInfo(keyGenMech);
+ } catch (PKCS11Exception p11e) {
+ // Should never happen
+ throw new ProviderException
+ ("Cannot retrieve mechanism info", p11e);
+ }
+ if (info == null) {
+ // XXX Unable to retrieve the supported key length from
+ // the underlying native impl. Skip the checking for now.
+ return keySize;
+ }
+ // PKCS#11 defines these to be in number of bytes except for
+ // RC4 which is in bits. However, some PKCS#11 impls still use
+ // bytes for all mechs, e.g. NSS. We try to detect this
+ // inconsistency if the minKeySize seems unreasonably small.
+ int minKeySize = (int)info.ulMinKeySize;
+ int maxKeySize = (int)info.ulMaxKeySize;
+ if (keyGenMech != CKM_RC4_KEY_GEN || minKeySize < 8) {
+ minKeySize = (int)info.ulMinKeySize << 3;
+ maxKeySize = (int)info.ulMaxKeySize << 3;
+ }
+ // Explicitly disallow keys shorter than 40-bits for security
+ if (minKeySize < 40) minKeySize = 40;
+ if (keySize < minKeySize || keySize > maxKeySize) {
+ throw new InvalidAlgorithmParameterException
+ ("Key length must be between " + minKeySize +
+ " and " + maxKeySize + " bits");
+ }
+ if (keyGenMech == CKM_AES_KEY_GEN) {
+ if ((keySize != 128) && (keySize != 192) &&
+ (keySize != 256)) {
+ throw new InvalidAlgorithmParameterException
+ ("AES key length must be " + minKeySize +
+ (maxKeySize >= 192? ", 192":"") +
+ (maxKeySize >= 256? ", or 256":"") + " bits");
+ }
+ }
+ sigKeySize = keySize;
+ }
+ return sigKeySize;
+ }
P11KeyGenerator(Token token, String algorithm, long mechanism)
throws PKCS11Exception {
@@ -85,72 +161,44 @@
supportBothKeySizes =
(token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
(token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
- } else if (this.mechanism == CKM_RC4_KEY_GEN) {
- CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism);
- // Although PKCS#11 spec documented that these are in bits,
- // NSS, for one, uses bytes. Multiple by 8 if the number seems
- // unreasonably small.
- if (info.ulMinKeySize < 8) {
- minKeySize = (int)info.ulMinKeySize << 3;
- maxKeySize = (int)info.ulMaxKeySize << 3;
- } else {
- minKeySize = (int)info.ulMinKeySize;
- maxKeySize = (int)info.ulMaxKeySize;
- }
- // Explicitly disallow keys shorter than 40-bits for security
- if (minKeySize < 40) minKeySize = 40;
- } else if (this.mechanism == CKM_BLOWFISH_KEY_GEN) {
- CK_MECHANISM_INFO info = token.getMechanismInfo(mechanism);
- maxKeySize = (int)info.ulMaxKeySize << 3;
- minKeySize = (int)info.ulMinKeySize << 3;
- // Explicitly disallow keys shorter than 40-bits for security
- if (minKeySize < 40) minKeySize = 40;
}
-
setDefaultKeySize();
}
// set default keysize and also initialize keyType
private void setDefaultKeySize() {
- // whether to check default key size against the min and max value
- boolean validateKeySize = false;
switch ((int)mechanism) {
case (int)CKM_DES_KEY_GEN:
keySize = 64;
- significantKeySize = 56;
keyType = CKK_DES;
break;
case (int)CKM_DES2_KEY_GEN:
keySize = 128;
- significantKeySize = 112;
keyType = CKK_DES2;
break;
case (int)CKM_DES3_KEY_GEN:
keySize = 192;
- significantKeySize = 168;
keyType = CKK_DES3;
break;
case (int)CKM_AES_KEY_GEN:
+ keySize = 128;
keyType = CKK_AES;
- keySize = 128;
- significantKeySize = 128;
break;
case (int)CKM_RC4_KEY_GEN:
+ keySize = 128;
keyType = CKK_RC4;
- keySize = 128;
- validateKeySize = true;
break;
case (int)CKM_BLOWFISH_KEY_GEN:
+ keySize = 128;
keyType = CKK_BLOWFISH;
- keySize = 128;
- validateKeySize = true;
break;
default:
throw new ProviderException("Unknown mechanism " + mechanism);
}
- if (validateKeySize &&
- ((keySize > maxKeySize) || (keySize < minKeySize))) {
- throw new ProviderException("Unsupported key size");
+ try {
+ significantKeySize = checkKeySize(mechanism, keySize, token);
+ } catch (InvalidAlgorithmParameterException iape) {
+ throw new ProviderException("Unsupported default key size", iape);
}
}
@@ -170,57 +218,32 @@
// see JCE spec
protected void engineInit(int keySize, SecureRandom random) {
token.ensureValid();
- switch ((int)mechanism) {
- case (int)CKM_DES_KEY_GEN:
- if ((keySize != this.keySize) &&
- (keySize != this.significantKeySize)) {
- throw new InvalidParameterException
- ("DES key length must be 56 bits");
- }
- break;
- case (int)CKM_DES2_KEY_GEN:
- case (int)CKM_DES3_KEY_GEN:
- long newMechanism;
- if ((keySize == 112) || (keySize == 128)) {
- newMechanism = CKM_DES2_KEY_GEN;
- } else if ((keySize == 168) || (keySize == 192)) {
- newMechanism = CKM_DES3_KEY_GEN;
- } else {
- throw new InvalidParameterException
- ("DESede key length must be 112, or 168 bits");
- }
+ int newSignificantKeySize;
+ try {
+ newSignificantKeySize = checkKeySize(mechanism, keySize, token);
+ } catch (InvalidAlgorithmParameterException iape) {
+ throw (InvalidParameterException)
+ (new InvalidParameterException().initCause(iape));
+ }
+ if ((mechanism == CKM_DES2_KEY_GEN) ||
+ (mechanism == CKM_DES3_KEY_GEN)) {
+ long newMechanism = (newSignificantKeySize == 112 ?
+ CKM_DES2_KEY_GEN : CKM_DES3_KEY_GEN);
if (mechanism != newMechanism) {
if (supportBothKeySizes) {
mechanism = newMechanism;
- setDefaultKeySize();
+ // Adjust keyType to reflect the mechanism change
+ keyType = (mechanism == CKM_DES2_KEY_GEN ?
+ CKK_DES2 : CKK_DES3);
} else {
throw new InvalidParameterException
- ("Only " + significantKeySize +
- "-bit DESede key length is supported");
+ ("Only " + significantKeySize +
+ "-bit DESede is supported");
}
}
- break;
- case (int)CKM_AES_KEY_GEN:
- if ((keySize != 128) && (keySize != 192) && (keySize != 256)) {
- throw new InvalidParameterException
- ("AES key length must be 128, 192, or 256 bits");
- }
- this.keySize = keySize;
- significantKeySize = keySize;
- break;
- case (int)CKM_RC4_KEY_GEN:
- case (int)CKM_BLOWFISH_KEY_GEN:
- if ((keySize < minKeySize) || (keySize > maxKeySize)) {
- throw new InvalidParameterException
- (algorithm + " key length must be between " +
- minKeySize + " and " + maxKeySize + " bits");
- }
- this.keySize = keySize;
- this.significantKeySize = keySize;
- break;
- default:
- throw new ProviderException("Unknown mechanism " + mechanism);
}
+ this.keySize = keySize;
+ this.significantKeySize = newSignificantKeySize;
}
// see JCE spec
--- a/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11KeyStore.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -156,10 +156,10 @@
// CKA_CLASS - entry type
private CK_ATTRIBUTE type = null;
- // CKA_LABEL of cert
+ // CKA_LABEL of cert and secret key
private String label = null;
- // CKA_ID - of private key/cert
+ // CKA_ID of the private key/cert pair
private byte[] id = null;
// CKA_TRUSTED - true if cert is trusted
@@ -871,10 +871,8 @@
if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
token.provider.login(null, handler);
} else {
-
// token supports protected authentication path
// (external pin-pad, for example)
-
if (handler != null &&
!token.config.getKeyStoreCompatibilityMode()) {
throw new LoginException("can not specify password if token " +
@@ -1130,19 +1128,14 @@
SecretKey skey = ske.getSecretKey();
try {
- // first see if the key already exists.
- // if so, update the CKA_LABEL
- if (!updateSkey(alias)) {
+ // first check if the key already exists
+ AliasInfo aliasInfo = aliasMap.get(alias);
- // key entry does not exist.
- // delete existing entry for alias and
- // create new secret key entry
- // (new entry might be a secret key
- // session object converted into a token object)
+ if (aliasInfo != null) {
+ engineDeleteEntry(alias);
+ }
+ storeSkey(alias, ske);
- engineDeleteEntry(alias);
- storeSkey(alias, ske);
- }
} catch (PKCS11Exception pe) {
throw new KeyStoreException(pe);
}
@@ -1396,41 +1389,6 @@
}
}
- /**
- * return true if update occurred
- */
- private boolean updateSkey(String alias)
- throws KeyStoreException, PKCS11Exception {
-
- Session session = null;
- try {
- session = token.getOpSession();
-
- // first update existing secret key CKA_LABEL
-
- THandle h = getTokenObject(session, ATTR_CLASS_SKEY, null, alias);
- if (h.type != ATTR_CLASS_SKEY) {
- if (debug != null) {
- debug.println("did not find secret key " +
- "with CKA_LABEL [" + alias + "]");
- }
- return false;
- }
- CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
- new CK_ATTRIBUTE(CKA_LABEL, alias) };
- token.p11.C_SetAttributeValue(session.id(), h.handle, attrs);
-
- if (debug != null) {
- debug.println("updateSkey set new alias [" +
- alias +
- "] for secret key entry");
- }
-
- return true;
- } finally {
- token.releaseSession(session);
- }
- }
/**
* XXX On ibutton, when you C_SetAttribute(CKA_ID) for a private key
@@ -1532,30 +1490,6 @@
}
}
- private void updateP11Skey(String alias, P11Key key)
- throws PKCS11Exception {
-
- Session session = null;
- try {
- session = token.getOpSession();
-
- // session key - convert to token key and set CKA_LABEL
-
- CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
- ATTR_TOKEN_TRUE,
- new CK_ATTRIBUTE(CKA_LABEL, alias) };
- token.p11.C_CopyObject(session.id(), key.keyID, attrs);
- if (debug != null) {
- debug.println("updateP11Skey copied secret session key " +
- "for [" +
- alias +
- "] to token entry");
- }
- } finally {
- token.releaseSession(session);
- }
- }
-
private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
throws PKCS11Exception {
@@ -1689,48 +1623,26 @@
throws PKCS11Exception, KeyStoreException {
SecretKey skey = ske.getSecretKey();
- long keyType = CKK_GENERIC_SECRET;
-
- if (skey instanceof P11Key && this.token == ((P11Key)skey).token) {
- updateP11Skey(alias, (P11Key)skey);
- return;
- }
-
- if ("AES".equalsIgnoreCase(skey.getAlgorithm())) {
- keyType = CKK_AES;
- } else if ("Blowfish".equalsIgnoreCase(skey.getAlgorithm())) {
- keyType = CKK_BLOWFISH;
- } else if ("DES".equalsIgnoreCase(skey.getAlgorithm())) {
- keyType = CKK_DES;
- } else if ("DESede".equalsIgnoreCase(skey.getAlgorithm())) {
- keyType = CKK_DES3;
- } else if ("RC4".equalsIgnoreCase(skey.getAlgorithm()) ||
- "ARCFOUR".equalsIgnoreCase(skey.getAlgorithm())) {
- keyType = CKK_RC4;
+ // No need to specify CKA_CLASS, CKA_KEY_TYPE, CKA_VALUE since
+ // they are handled in P11SecretKeyFactory.createKey() method.
+ CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
+ ATTR_SKEY_TOKEN_TRUE,
+ ATTR_PRIVATE_TRUE,
+ new CK_ATTRIBUTE(CKA_LABEL, alias),
+ };
+ try {
+ P11SecretKeyFactory.convertKey(token, skey, null, attrs);
+ } catch (InvalidKeyException ike) {
+ // re-throw KeyStoreException to match javadoc
+ throw new KeyStoreException("Cannot convert to PKCS11 keys", ike);
}
- CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
- ATTR_SKEY_TOKEN_TRUE,
- ATTR_CLASS_SKEY,
- ATTR_PRIVATE_TRUE,
- new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
- new CK_ATTRIBUTE(CKA_LABEL, alias),
- new CK_ATTRIBUTE(CKA_VALUE, skey.getEncoded()) };
- attrs = token.getAttributes
- (TemplateManager.O_IMPORT, CKO_SECRET_KEY, keyType, attrs);
+ // update global alias map
+ aliasMap.put(alias, new AliasInfo(alias));
- // create the new entry
- Session session = null;
- try {
- session = token.getOpSession();
- token.p11.C_CreateObject(session.id(), attrs);
- if (debug != null) {
- debug.println("storeSkey created token secret key for [" +
- alias +
- "]");
- }
- } finally {
- token.releaseSession(session);
+ if (debug != null) {
+ debug.println("storeSkey created token secret key for [" +
+ alias + "]");
}
}
@@ -2492,7 +2404,8 @@
// if there are duplicates (either between secret keys,
// or between a secret key and another object),
// throw an exception
- HashSet<String> sKeySet = new HashSet<String>();
+ HashMap<String, AliasInfo> sKeyMap =
+ new HashMap<String, AliasInfo>();
attrs = new CK_ATTRIBUTE[] {
ATTR_SKEY_TOKEN_TRUE,
@@ -2507,8 +2420,8 @@
// there is a CKA_LABEL
String cka_label = new String(attrs[0].getCharArray());
- if (!sKeySet.contains(cka_label)) {
- sKeySet.add(cka_label);
+ if (sKeyMap.get(cka_label) == null) {
+ sKeyMap.put(cka_label, new AliasInfo(cka_label));
} else {
throw new KeyStoreException("invalid KeyStore state: " +
"found multiple secret keys sharing same " +
@@ -2523,7 +2436,7 @@
ArrayList<AliasInfo> matchedCerts =
mapPrivateKeys(pkeyIDs, certMap);
boolean sharedLabel = mapCerts(matchedCerts, certMap);
- mapSecretKeys(sKeySet);
+ mapSecretKeys(sKeyMap);
return sharedLabel;
@@ -2547,7 +2460,7 @@
HashMap<String, HashSet<AliasInfo>> certMap)
throws PKCS11Exception, CertificateException {
- // global alias map
+ // reset global alias map
aliasMap = new HashMap<String, AliasInfo>();
// list of matched certs that we will return
@@ -2722,18 +2635,17 @@
* If the secret key shares a CKA_LABEL with another entry,
* throw an exception
*/
- private void mapSecretKeys(HashSet<String> sKeySet)
+ private void mapSecretKeys(HashMap<String, AliasInfo> sKeyMap)
throws KeyStoreException {
- for (String label : sKeySet) {
- if (!aliasMap.containsKey(label)) {
- aliasMap.put(label, new AliasInfo(label));
- } else {
+ for (String label : sKeyMap.keySet()) {
+ if (aliasMap.containsKey(label)) {
throw new KeyStoreException("invalid KeyStore state: " +
"found secret key sharing CKA_LABEL [" +
label +
"] with another token object");
}
}
+ aliasMap.putAll(sKeyMap);
}
private void dumpTokenMap() {
--- a/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11RSACipher.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -98,7 +98,6 @@
this.token = token;
this.algorithm = "RSA";
this.mechanism = mechanism;
- session = token.getOpSession();
}
// modes do not make sense for RSA, but allow ECB
@@ -184,7 +183,8 @@
throw new InvalidKeyException
("Wrap has to be used with public keys");
}
- // No further setup needed for C_Wrap(). We remain uninitialized.
+ // No further setup needed for C_Wrap(). We'll initialize later if
+ // we can't use C_Wrap().
return;
} else if (opmode == Cipher.UNWRAP_MODE) {
if (p11Key.isPrivate() == false) {
@@ -383,7 +383,8 @@
return implDoFinal(out, outOfs, out.length - outOfs);
}
- private byte[] doFinal() throws BadPaddingException, IllegalBlockSizeException {
+ private byte[] doFinal() throws BadPaddingException,
+ IllegalBlockSizeException {
byte[] t = new byte[2048];
int n = implDoFinal(t, 0, t.length);
byte[] out = new byte[n];
@@ -394,20 +395,37 @@
// see JCE spec
protected byte[] engineWrap(Key key) throws InvalidKeyException,
IllegalBlockSizeException {
- // XXX Note that if we cannot convert key to a key on this token,
- // we will fail. For example, trying a wrap an AES key on a token that
- // does not support AES.
- // We could implement a fallback that just encrypts the encoding
- // (assuming the key is not sensitive). For now, we are operating under
- // the assumption that this is not necessary.
String keyAlg = key.getAlgorithm();
- P11Key secretKey = P11SecretKeyFactory.convertKey(token, key, keyAlg);
+ P11Key sKey = null;
+ try {
+ // The conversion may fail, e.g. trying to wrap an AES key on
+ // a token that does not support AES, or when the key size is
+ // not within the range supported by the token.
+ sKey = P11SecretKeyFactory.convertKey(token, key, keyAlg);
+ } catch (InvalidKeyException ike) {
+ byte[] toBeWrappedKey = key.getEncoded();
+ if (toBeWrappedKey == null) {
+ throw new InvalidKeyException
+ ("wrap() failed, no encoding available", ike);
+ }
+ // Directly encrypt the key encoding when key conversion failed
+ implInit(Cipher.ENCRYPT_MODE, p11Key);
+ implUpdate(toBeWrappedKey, 0, toBeWrappedKey.length);
+ try {
+ return doFinal();
+ } catch (BadPaddingException bpe) {
+ // should not occur
+ throw new InvalidKeyException("wrap() failed", bpe);
+ } finally {
+ // Restore original mode
+ implInit(Cipher.WRAP_MODE, p11Key);
+ }
+ }
Session s = null;
try {
s = token.getOpSession();
- byte[] b = token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
- p11Key.keyID, secretKey.keyID);
- return b;
+ return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
+ p11Key.keyID, sKey.keyID);
} catch (PKCS11Exception e) {
throw new InvalidKeyException("wrap() failed", e);
} finally {
@@ -431,11 +449,13 @@
};
attributes = token.getAttributes
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
- long keyID = token.p11.C_UnwrapKey(s.id(), new CK_MECHANISM(mechanism),
- p11Key.keyID, wrappedKey, attributes);
- return P11Key.secretKey(session, keyID, algorithm, 48 << 3, attributes);
+ long keyID = token.p11.C_UnwrapKey(s.id(),
+ new CK_MECHANISM(mechanism), p11Key.keyID, wrappedKey,
+ attributes);
+ return P11Key.secretKey(session, keyID, algorithm, 48 << 3,
+ attributes);
} catch (PKCS11Exception e) {
- throw new InvalidKeyException("wrap() failed", e);
+ throw new InvalidKeyException("unwrap() failed", e);
} finally {
token.releaseSession(s);
}
--- a/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/P11SecretKeyFactory.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -104,9 +104,20 @@
/**
* Convert an arbitrary key of algorithm into a P11Key of provider.
- * Used engineTranslateKey(), P11Cipher.init(), and P11Mac.init().
+ * Used in engineTranslateKey(), P11Cipher.init(), and P11Mac.init().
*/
- static P11Key convertKey(Token token, Key key, String algorithm)
+ static P11Key convertKey(Token token, Key key, String algo)
+ throws InvalidKeyException {
+ return convertKey(token, key, algo, null);
+ }
+
+ /**
+ * Convert an arbitrary key of algorithm w/ custom attributes into a
+ * P11Key of provider.
+ * Used in P11KeyStore.storeSkey.
+ */
+ static P11Key convertKey(Token token, Key key, String algo,
+ CK_ATTRIBUTE[] extraAttrs)
throws InvalidKeyException {
token.ensureValid();
if (key == null) {
@@ -115,25 +126,41 @@
if (key instanceof SecretKey == false) {
throw new InvalidKeyException("Key must be a SecretKey");
}
- long algorithmType;
- if (algorithm == null) {
- algorithm = key.getAlgorithm();
- algorithmType = getKeyType(algorithm);
+ long algoType;
+ if (algo == null) {
+ algo = key.getAlgorithm();
+ algoType = getKeyType(algo);
} else {
- algorithmType = getKeyType(algorithm);
+ algoType = getKeyType(algo);
long keyAlgorithmType = getKeyType(key.getAlgorithm());
- if (algorithmType != keyAlgorithmType) {
- if ((algorithmType == PCKK_HMAC) || (algorithmType == PCKK_SSLMAC)) {
+ if (algoType != keyAlgorithmType) {
+ if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) {
// ignore key algorithm for MACs
} else {
throw new InvalidKeyException
- ("Key algorithm must be " + algorithm);
+ ("Key algorithm must be " + algo);
}
}
}
if (key instanceof P11Key) {
P11Key p11Key = (P11Key)key;
if (p11Key.token == token) {
+ if (extraAttrs != null) {
+ Session session = null;
+ try {
+ session = token.getObjSession();
+ long newKeyID = token.p11.C_CopyObject(session.id(),
+ p11Key.keyID, extraAttrs);
+ p11Key = (P11Key) (P11Key.secretKey(p11Key.session,
+ newKeyID, p11Key.algorithm, p11Key.keyLength,
+ extraAttrs));
+ } catch (PKCS11Exception p11e) {
+ throw new InvalidKeyException
+ ("Cannot duplicate the PKCS11 key", p11e);
+ } finally {
+ token.releaseSession(session);
+ }
+ }
return p11Key;
}
}
@@ -141,11 +168,11 @@
if (p11Key != null) {
return p11Key;
}
- if ("RAW".equals(key.getFormat()) == false) {
+ if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
throw new InvalidKeyException("Encoded format must be RAW");
}
byte[] encoded = key.getEncoded();
- p11Key = createKey(token, encoded, algorithm, algorithmType);
+ p11Key = createKey(token, encoded, algo, algoType, extraAttrs);
token.secretCache.put(key, p11Key);
return p11Key;
}
@@ -159,79 +186,79 @@
}
private static P11Key createKey(Token token, byte[] encoded,
- String algorithm, long keyType) throws InvalidKeyException {
- int n = encoded.length;
- int keyLength;
- switch ((int)keyType) {
- case (int)CKK_RC4:
- if ((n < 5) || (n > 128)) {
- throw new InvalidKeyException
- ("ARCFOUR key length must be between 5 and 128 bytes");
- }
- keyLength = n << 3;
- break;
- case (int)CKK_DES:
- if (n != 8) {
- throw new InvalidKeyException
- ("DES key length must be 8 bytes");
- }
- keyLength = 56;
- fixDESParity(encoded, 0);
- break;
- case (int)CKK_DES3:
- if (n == 16) {
- keyType = CKK_DES2;
- } else if (n == 24) {
- keyType = CKK_DES3;
- fixDESParity(encoded, 16);
- } else {
- throw new InvalidKeyException
- ("DESede key length must be 16 or 24 bytes");
+ String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs)
+ throws InvalidKeyException {
+ int n = encoded.length << 3;
+ int keyLength = n;
+ try {
+ switch ((int)keyType) {
+ case (int)CKK_DES:
+ keyLength =
+ P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token);
+ fixDESParity(encoded, 0);
+ break;
+ case (int)CKK_DES3:
+ keyLength =
+ P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token);
+ fixDESParity(encoded, 0);
+ fixDESParity(encoded, 8);
+ if (keyLength == 112) {
+ keyType = CKK_DES2;
+ } else {
+ keyType = CKK_DES3;
+ fixDESParity(encoded, 16);
+ }
+ break;
+ case (int)CKK_AES:
+ keyLength =
+ P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token);
+ break;
+ case (int)CKK_RC4:
+ keyLength =
+ P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token);
+ break;
+ case (int)CKK_BLOWFISH:
+ keyLength =
+ P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n,
+ token);
+ break;
+ case (int)CKK_GENERIC_SECRET:
+ case (int)PCKK_TLSPREMASTER:
+ case (int)PCKK_TLSRSAPREMASTER:
+ case (int)PCKK_TLSMASTER:
+ keyType = CKK_GENERIC_SECRET;
+ break;
+ case (int)PCKK_SSLMAC:
+ case (int)PCKK_HMAC:
+ if (n == 0) {
+ throw new InvalidKeyException
+ ("MAC keys must not be empty");
+ }
+ keyType = CKK_GENERIC_SECRET;
+ break;
+ default:
+ throw new InvalidKeyException("Unknown algorithm " +
+ algorithm);
}
- fixDESParity(encoded, 0);
- fixDESParity(encoded, 8);
- keyLength = n * 7;
- break;
- case (int)CKK_AES:
- if ((n != 16) && (n != 24) && (n != 32)) {
- throw new InvalidKeyException
- ("AES key length must be 16, 24, or 32 bytes");
- }
- keyLength = n << 3;
- break;
- case (int)CKK_BLOWFISH:
- if ((n < 5) || (n > 56)) {
- throw new InvalidKeyException
- ("Blowfish key length must be between 5 and 56 bytes");
- }
- keyLength = n << 3;
- break;
- case (int)CKK_GENERIC_SECRET:
- case (int)PCKK_TLSPREMASTER:
- case (int)PCKK_TLSRSAPREMASTER:
- case (int)PCKK_TLSMASTER:
- keyType = CKK_GENERIC_SECRET;
- keyLength = n << 3;
- break;
- case (int)PCKK_SSLMAC:
- case (int)PCKK_HMAC:
- if (n == 0) {
- throw new InvalidKeyException
- ("MAC keys must not be empty");
- }
- keyType = CKK_GENERIC_SECRET;
- keyLength = n << 3;
- break;
- default:
- throw new InvalidKeyException("Unknown algorithm " + algorithm);
+ } catch (InvalidAlgorithmParameterException iape) {
+ throw new InvalidKeyException("Invalid key for " + algorithm,
+ iape);
+ } catch (ProviderException pe) {
+ throw new InvalidKeyException("Could not create key", pe);
}
Session session = null;
try {
- CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
- new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
- new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
- new CK_ATTRIBUTE(CKA_VALUE, encoded),
- };
+ CK_ATTRIBUTE[] attributes;
+ if (extraAttrs != null) {
+ attributes = new CK_ATTRIBUTE[3 + extraAttrs.length];
+ System.arraycopy(extraAttrs, 0, attributes, 3,
+ extraAttrs.length);
+ } else {
+ attributes = new CK_ATTRIBUTE[3];
+ }
+ attributes[0] = new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY);
+ attributes[1] = new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType);
+ attributes[2] = new CK_ATTRIBUTE(CKA_VALUE, encoded);
attributes = token.getAttributes
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
session = token.getObjSession();
@@ -280,7 +307,7 @@
private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException {
try {
key = engineTranslateKey(key);
- if ("RAW".equals(key.getFormat()) == false) {
+ if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
throw new InvalidKeySpecException
("Could not obtain key bytes");
}
--- a/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -601,14 +601,26 @@
// XXX attributes for Ciphers (supported modes, padding)
d(CIP, "ARCFOUR", P11Cipher, s("RC4"),
m(CKM_RC4));
- // XXX only CBC/NoPadding for block ciphers
d(CIP, "DES/CBC/NoPadding", P11Cipher,
m(CKM_DES_CBC));
+ d(CIP, "DES/CBC/PKCS5Padding", P11Cipher,
+ m(CKM_DES_CBC_PAD, CKM_DES_CBC));
+ d(CIP, "DES/ECB", P11Cipher, s("DES"),
+ m(CKM_DES_ECB));
+
d(CIP, "DESede/CBC/NoPadding", P11Cipher,
m(CKM_DES3_CBC));
+ d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher,
+ m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));
+ d(CIP, "DESede/ECB", P11Cipher, s("DESede"),
+ m(CKM_DES3_ECB));
d(CIP, "AES/CBC/NoPadding", P11Cipher,
m(CKM_AES_CBC));
- d(CIP, "Blowfish/CBC/NoPadding", P11Cipher,
+ d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,
+ m(CKM_AES_CBC_PAD, CKM_AES_CBC));
+ d(CIP, "AES/ECB", P11Cipher, s("AES"),
+ m(CKM_AES_ECB));
+ d(CIP, "Blowfish/CBC", P11Cipher,
m(CKM_BLOWFISH_CBC));
// XXX RSA_X_509, RSA_OAEP not yet supported
--- a/jdk/src/share/classes/sun/security/validator/EndEntityChecker.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/share/classes/sun/security/validator/EndEntityChecker.java Mon Apr 07 14:19:23 2008 -0700
@@ -87,6 +87,9 @@
// the Microsoft Server-Gated-Cryptography EKU extension OID
private final static String OID_EKU_MS_SGC = "1.3.6.1.4.1.311.10.3.3";
+ // the recognized extension OIDs
+ private final static String OID_SUBJECT_ALT_NAME = "2.5.29.17";
+
private final static String NSCT_SSL_CLIENT =
NetscapeCertTypeExtension.SSL_CLIENT;
@@ -171,6 +174,13 @@
throws CertificateException {
// basic constraints irrelevant in EE certs
exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);
+
+ // If the subject field contains an empty sequence, the subjectAltName
+ // extension MUST be marked critical.
+ // We do not check the validity of the critical extension, just mark
+ // it recognizable here.
+ exts.remove(OID_SUBJECT_ALT_NAME);
+
if (!exts.isEmpty()) {
throw new CertificateException("Certificate contains unsupported "
+ "critical extensions: " + exts);
--- a/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/src/solaris/native/sun/security/pkcs11/wrapper/p11_md.c Mon Apr 07 14:19:23 2008 -0700
@@ -123,7 +123,10 @@
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr);
(*env)->ReleaseStringUTFChars(env, jGetFunctionList, getFunctionListStr);
}
- if ((C_GetFunctionList == NULL) || ((systemErrorMessage = dlerror()) != NULL)){
+ if (C_GetFunctionList == NULL) {
+ throwIOException(env, "ERROR: C_GetFunctionList == NULL");
+ return;
+ } else if ( (systemErrorMessage = dlerror()) != NULL ){
throwIOException(env, systemErrorMessage);
return;
}
--- a/jdk/test/javax/crypto/Cipher/TestGetInstance.java Tue Apr 01 14:45:23 2008 +0200
+++ b/jdk/test/javax/crypto/Cipher/TestGetInstance.java Mon Apr 07 14:19:23 2008 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -46,9 +46,7 @@
Cipher c;
- c = Cipher.getInstance("des");
- same(p, c.getProvider());
- c = Cipher.getInstance("des/cbc/pkcs5padding");
+ c = Cipher.getInstance("PBEWithMD5AndTripleDES");
same(p, c.getProvider());
c = Cipher.getInstance("des", "SunJCE");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java Mon Apr 07 14:19:23 2008 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6572331
+ * @summary basic test for RSA cipher key wrapping functionality
+ * @author Valerie Peng
+ * @library ..
+ */
+import java.io.*;
+import java.util.*;
+
+import java.security.*;
+
+import javax.crypto.*;
+import javax.crypto.spec.SecretKeySpec;
+
+public class TestRSACipherWrap extends PKCS11Test {
+
+ private static final String RSA_ALGO = "RSA/ECB/PKCS1Padding";
+
+ public void main(Provider p) throws Exception {
+ try {
+ Cipher.getInstance(RSA_ALGO, p);
+ } catch (GeneralSecurityException e) {
+ System.out.println("Not supported by provider, skipping");
+ return;
+ }
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", p);
+ kpg.initialize(1024);
+ KeyPair kp = kpg.generateKeyPair();
+ PublicKey publicKey = kp.getPublic();
+ PrivateKey privateKey = kp.getPrivate();
+
+ Cipher cipherPKCS11 = Cipher.getInstance(RSA_ALGO, p);
+ Cipher cipherJce = Cipher.getInstance(RSA_ALGO, "SunJCE");
+
+ String algos[] = {"AES", "RC2", "Blowfish"};
+ int keySizes[] = {128, 256};
+
+ for (int j = 0; j < algos.length; j++) {
+ String algorithm = algos[j];
+ KeyGenerator keygen =
+ KeyGenerator.getInstance(algorithm);
+
+ for (int i = 0; i < keySizes.length; i++) {
+ SecretKey secretKey = null;
+ System.out.print("Generate " + keySizes[i] + "-bit " +
+ algorithm + " key using ");
+ try {
+ keygen.init(keySizes[i]);
+ secretKey = keygen.generateKey();
+ System.out.println(keygen.getProvider().getName());
+ } catch (InvalidParameterException ipe) {
+ secretKey = new SecretKeySpec(new byte[32], algorithm);
+ System.out.println("SecretKeySpec class");
+ }
+ test(kp, secretKey, cipherPKCS11, cipherJce);
+ test(kp, secretKey, cipherPKCS11, cipherPKCS11);
+ test(kp, secretKey, cipherJce, cipherPKCS11);
+ }
+ }
+ }
+
+ private static void test(KeyPair kp, SecretKey secretKey,
+ Cipher wrapCipher, Cipher unwrapCipher)
+ throws Exception {
+ String algo = secretKey.getAlgorithm();
+ wrapCipher.init(Cipher.WRAP_MODE, kp.getPublic());
+ byte[] wrappedKey = wrapCipher.wrap(secretKey);
+ unwrapCipher.init(Cipher.UNWRAP_MODE, kp.getPrivate());
+ Key unwrappedKey =
+ unwrapCipher.unwrap(wrappedKey, algo, Cipher.SECRET_KEY);
+
+ System.out.println("Test " + wrapCipher.getProvider().getName() +
+ "/" + unwrapCipher.getProvider().getName() + ": ");
+ if (!Arrays.equals(secretKey.getEncoded(),
+ unwrappedKey.getEncoded())) {
+ throw new Exception("Test Failed!");
+ }
+ System.out.println("Passed");
+ }
+
+ public static void main(String[] args) throws Exception {
+ main(new TestRSACipherWrap());
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/Cipher/TestSymmCiphers.java Mon Apr 07 14:19:23 2008 -0700
@@ -0,0 +1,282 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modi
+fy it
+ * under the terms of the GNU General Public License version 2 onl
+y, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, bu
+t WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABIL
+ITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public L
+icense
+ * version 2 for more details (a copy is included in the LICENSE f
+ile that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public Licen
+se version
+ * 2 along with this work; if not, write to the Free Software Foun
+dation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, San
+ta Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional inform
+ation or
+ * have any questions.
+ */
+
+/**
+ * @test %I% %E%
+ * @bug 4898461
+ * @summary basic test for symmetric ciphers with padding
+ * @author Valerie Peng
+ * @library ..
+ */
+import java.io.*;
+import java.nio.*;
+import java.util.*;
+
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.*;
+import javax.crypto.spec.IvParameterSpec;
+
+public class TestSymmCiphers extends PKCS11Test {
+
+ private static class CI { // class for holding Cipher Information
+
+ String transformation;
+ String keyAlgo;
+ int dataSize;
+
+ CI(String transformation, String keyAlgo, int dataSize) {
+ this.transformation = transformation;
+ this.keyAlgo = keyAlgo;
+ this.dataSize = dataSize;
+ }
+ }
+ private static final CI[] TEST_LIST = {
+ new CI("ARCFOUR", "ARCFOUR", 400),
+ new CI("RC4", "RC4", 401),
+ new CI("DES/CBC/NoPadding", "DES", 400),
+ new CI("DESede/CBC/NoPadding", "DESede", 160),
+ new CI("AES/CBC/NoPadding", "AES", 4800),
+ new CI("Blowfish/CBC/NoPadding", "Blowfish", 24),
+ new CI("DES/cbc/PKCS5Padding", "DES", 6401),
+ new CI("DESede/CBC/PKCS5Padding", "DESede", 402),
+ new CI("AES/CBC/PKCS5Padding", "AES", 30),
+ new CI("Blowfish/CBC/PKCS5Padding", "Blowfish", 19),
+ new CI("DES/ECB/NoPadding", "DES", 400),
+ new CI("DESede/ECB/NoPadding", "DESede", 160),
+ new CI("AES/ECB/NoPadding", "AES", 4800),
+ new CI("DES/ECB/PKCS5Padding", "DES", 32),
+ new CI("DES/ECB/PKCS5Padding", "DES", 6400),
+ new CI("DESede/ECB/PKCS5Padding", "DESede", 400),
+ new CI("AES/ECB/PKCS5Padding", "AES", 64),
+ new CI("DES", "DES", 6400),
+ new CI("DESede", "DESede", 408),
+ new CI("AES", "AES", 128)
+ };
+ private static StringBuffer debugBuf = new StringBuffer();
+
+ public void main(Provider p) throws Exception {
+ // NSS reports CKR_DEVICE_ERROR when the data passed to
+ // its EncryptUpdate/DecryptUpdate is not multiple of blocks
+ int firstBlkSize = 16;
+ boolean status = true;
+ Random random = new Random();
+ try {
+ for (int i = 0; i < TEST_LIST.length; i++) {
+ CI currTest = TEST_LIST[i];
+ System.out.println("===" + currTest.transformation + "===");
+ try {
+ KeyGenerator kg =
+ KeyGenerator.getInstance(currTest.keyAlgo, p);
+ SecretKey key = kg.generateKey();
+ Cipher c1 = Cipher.getInstance(currTest.transformation, p);
+ Cipher c2 = Cipher.getInstance(currTest.transformation,
+ "SunJCE");
+
+ byte[] plainTxt = new byte[currTest.dataSize];
+ random.nextBytes(plainTxt);
+ System.out.println("Testing inLen = " + plainTxt.length);
+
+ c2.init(Cipher.ENCRYPT_MODE, key);
+ AlgorithmParameters params = c2.getParameters();
+ byte[] answer = c2.doFinal(plainTxt);
+ System.out.println("Encryption tests: START");
+ test(c1, Cipher.ENCRYPT_MODE, key, params, firstBlkSize,
+ plainTxt, answer);
+ System.out.println("Encryption tests: DONE");
+ c2.init(Cipher.DECRYPT_MODE, key, params);
+ byte[] answer2 = c2.doFinal(answer);
+ System.out.println("Decryption tests: START");
+ test(c1, Cipher.DECRYPT_MODE, key, params, firstBlkSize,
+ answer, answer2);
+ System.out.println("Decryption tests: DONE");
+ } catch (NoSuchAlgorithmException nsae) {
+ System.out.println("Skipping unsupported algorithm: " +
+ nsae);
+ }
+ }
+ } catch (Exception ex) {
+ // print out debug info when exception is encountered
+ if (debugBuf != null) {
+ System.out.println(debugBuf.toString());
+ debugBuf = new StringBuffer();
+ }
+ throw ex;
+ }
+ }
+
+ private static void test(Cipher cipher, int mode, SecretKey key,
+ AlgorithmParameters params, int firstBlkSize,
+ byte[] in, byte[] answer) throws Exception {
+ // test setup
+ long startTime, endTime;
+ cipher.init(mode, key, params);
+ int outLen = cipher.getOutputSize(in.length);
+ //debugOut("Estimated output size = " + outLen + "\n");
+
+ // test data preparation
+ ByteBuffer inBuf = ByteBuffer.allocate(in.length);
+ inBuf.put(in);
+ inBuf.position(0);
+ ByteBuffer inDirectBuf = ByteBuffer.allocateDirect(in.length);
+ inDirectBuf.put(in);
+ inDirectBuf.position(0);
+ ByteBuffer outBuf = ByteBuffer.allocate(outLen);
+ ByteBuffer outDirectBuf = ByteBuffer.allocateDirect(outLen);
+
+ // test#1: byte[] in + byte[] out
+ //debugOut("Test#1:\n");
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ startTime = System.nanoTime();
+ byte[] temp = cipher.update(in, 0, firstBlkSize);
+ if (temp != null && temp.length > 0) {
+ baos.write(temp, 0, temp.length);
+ }
+ temp = cipher.doFinal(in, firstBlkSize, in.length - firstBlkSize);
+ if (temp != null && temp.length > 0) {
+ baos.write(temp, 0, temp.length);
+ }
+ byte[] testOut1 = baos.toByteArray();
+ endTime = System.nanoTime();
+ perfOut("stream InBuf + stream OutBuf: " +
+ (endTime - startTime));
+ match(testOut1, answer);
+
+ // test#2: Non-direct Buffer in + non-direct Buffer out
+ //debugOut("Test#2:\n");
+ //debugOut("inputBuf: " + inBuf + "\n");
+ //debugOut("outputBuf: " + outBuf + "\n");
+
+ startTime = System.nanoTime();
+ cipher.update(inBuf, outBuf);
+ cipher.doFinal(inBuf, outBuf);
+ endTime = System.nanoTime();
+ perfOut("non-direct InBuf + non-direct OutBuf: " +
+ (endTime - startTime));
+ match(outBuf, answer);
+
+ // test#3: Direct Buffer in + direc Buffer out
+ //debugOut("Test#3:\n");
+ //debugOut("(pre) inputBuf: " + inDirectBuf + "\n");
+ //debugOut("(pre) outputBuf: " + outDirectBuf + "\n");
+
+ startTime = System.nanoTime();
+ cipher.update(inDirectBuf, outDirectBuf);
+ cipher.doFinal(inDirectBuf, outDirectBuf);
+ endTime = System.nanoTime();
+ perfOut("direct InBuf + direct OutBuf: " +
+ (endTime - startTime));
+
+ //debugOut("(post) inputBuf: " + inDirectBuf + "\n");
+ //debugOut("(post) outputBuf: " + outDirectBuf + "\n");
+ match(outDirectBuf, answer);
+
+ // test#4: Direct Buffer in + non-direct Buffer out
+ //debugOut("Test#4:\n");
+ inDirectBuf.position(0);
+ outBuf.position(0);
+ //debugOut("inputBuf: " + inDirectBuf + "\n");
+ //debugOut("outputBuf: " + outBuf + "\n");
+
+ startTime = System.nanoTime();
+ cipher.update(inDirectBuf, outBuf);
+ cipher.doFinal(inDirectBuf, outBuf);
+ endTime = System.nanoTime();
+ perfOut("direct InBuf + non-direct OutBuf: " +
+ (endTime - startTime));
+ match(outBuf, answer);
+
+ // test#5: Non-direct Buffer in + direct Buffer out
+ //debugOut("Test#5:\n");
+ inBuf.position(0);
+ outDirectBuf.position(0);
+
+ //debugOut("(pre) inputBuf: " + inBuf + "\n");
+ //debugOut("(pre) outputBuf: " + outDirectBuf + "\n");
+
+ startTime = System.nanoTime();
+ cipher.update(inBuf, outDirectBuf);
+ cipher.doFinal(inBuf, outDirectBuf);
+ endTime = System.nanoTime();
+ perfOut("non-direct InBuf + direct OutBuf: " +
+ (endTime - startTime));
+
+ //debugOut("(post) inputBuf: " + inBuf + "\n");
+ //debugOut("(post) outputBuf: " + outDirectBuf + "\n");
+ match(outDirectBuf, answer);
+
+ debugBuf = null;
+ }
+
+ private static void perfOut(String msg) {
+ if (debugBuf != null) {
+ debugBuf.append("PERF>" + msg);
+ }
+ }
+
+ private static void debugOut(String msg) {
+ if (debugBuf != null) {
+ debugBuf.append(msg);
+ }
+ }
+
+ private static void match(byte[] b1, byte[] b2) throws Exception {
+ if (b1.length != b2.length) {
+ debugOut("got len : " + b1.length + "\n");
+ debugOut("expect len: " + b2.length + "\n");
+ throw new Exception("mismatch - different length! got: " + b1.length + ", expect: " + b2.length + "\n");
+ } else {
+ for (int i = 0; i < b1.length; i++) {
+ if (b1[i] != b2[i]) {
+ debugOut("got : " + toString(b1) + "\n");
+ debugOut("expect: " + toString(b2) + "\n");
+ throw new Exception("mismatch");
+ }
+ }
+ }
+ }
+
+ private static void match(ByteBuffer bb, byte[] answer) throws Exception {
+ byte[] bbTemp = new byte[bb.position()];
+ bb.position(0);
+ bb.get(bbTemp, 0, bbTemp.length);
+ match(bbTemp, answer);
+ }
+
+ public static void main(String[] args) throws Exception {
+ main(new TestSymmCiphers());
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java Mon Apr 07 14:19:23 2008 -0700
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+import java.io.*;
+import java.util.*;
+import java.lang.reflect.*;
+
+import java.security.*;
+import java.security.cert.*;
+import java.security.spec.*;
+import java.security.interfaces.*;
+import java.math.BigInteger;
+
+import javax.crypto.*;
+import javax.crypto.spec.*;
+
+public class SecretKeysBasic extends PKCS11Test {
+
+ private static final char SEP = File.separatorChar;
+ private static char[] tokenPwd;
+ private static final char[] nssPwd =
+ new char[]{'t', 'e', 's', 't', '1', '2'};
+ private static final char[] solarisPwd =
+ new char[]{'p', 'i', 'n'};
+ private static SecretKey sk1;
+ private static SecretKey sk2;
+ private static SecretKey softkey;
+ private static KeyStore ks;
+ private static final String KS_TYPE = "PKCS11";
+ private static Provider provider;
+
+ public static void main(String[] args) throws Exception {
+ main(new SecretKeysBasic());
+ }
+
+ public void main(Provider p) throws Exception {
+ this.provider = p;
+
+ // create secret key
+ byte[] keyVal = new byte[16];
+ (new SecureRandom()).nextBytes(keyVal);
+ // NSS will throw CKR_HOST_MEMORY if calling C_DecryptInit w/
+ // (keyVal[0] == 0)
+ if (keyVal[0] == 0) {
+ keyVal[0] = 1;
+ }
+ softkey = new SecretKeySpec(keyVal, "AES");
+ dumpKey("softkey", softkey);
+
+ KeyGenerator kg = KeyGenerator.getInstance("DESede", provider);
+ sk1 = kg.generateKey();
+ dumpKey("skey1", sk1);
+ sk2 = kg.generateKey();
+ dumpKey("skey2", sk2);
+
+ String token = System.getProperty("TOKEN");
+
+ if (token == null || token.length() == 0) {
+ System.out.println("Error: missing TOKEN system property");
+ throw new Exception("token arg required");
+ }
+
+ if ("nss".equals(token)) {
+ tokenPwd = nssPwd;
+ } else if ("solaris".equals(token)) {
+ tokenPwd = solarisPwd;
+ }
+
+ int testnum = 1;
+ doTest();
+ }
+
+ private static boolean checkSecretKeyEntry(String alias,
+ SecretKey expected,
+ boolean saveBeforeCheck)
+ throws Exception {
+ if (saveBeforeCheck) {
+ ks.setKeyEntry(alias, expected, null, null);
+ }
+ SecretKey result = (SecretKey) (ks.getKey(alias, null));
+ String keyEncFormat = result.getFormat();
+ if (keyEncFormat == null) {
+ // sensitive or un-extractable keys - verify by encrypt/decrypt
+ byte[] data = new byte[64];
+ Cipher c =
+ Cipher.getInstance(result.getAlgorithm() + "/CBC/NoPadding",
+ provider);
+ c.init(Cipher.ENCRYPT_MODE, expected);
+ byte[] encOut = c.doFinal(data);
+ c.init(Cipher.DECRYPT_MODE, result, c.getParameters());
+ byte[] decOut = c.doFinal(encOut);
+ if (!Arrays.equals(data, decOut)) {
+ return false;
+ }
+ } else if (keyEncFormat.toUpperCase().equals("RAW")) {
+ if (!Arrays.equals(result.getEncoded(), expected.getEncoded())) {
+ dumpKey("\texpected:", expected);
+ dumpKey("\treturns:", result);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void dumpKey(String info, SecretKey key) {
+ System.out.println(info + "> " + key);
+ System.out.println("\tALGO=" + key.getAlgorithm());
+ if (key.getFormat() != null) {
+ System.out.println("\t[" + key.getFormat() + "] VALUE=" +
+ new BigInteger(key.getEncoded()));
+ } else {
+ System.out.println("\tVALUE=n/a");
+ }
+ }
+
+ private static void doTest() throws Exception {
+ if (ks == null) {
+ ks = KeyStore.getInstance(KS_TYPE, provider);
+ ks.load(null, tokenPwd);
+ }
+
+ System.out.println("Number of entries: " + ks.size());
+ if (ks.size() != 0) {
+ System.out.println("Deleting entries under aliases: ");
+ for (Enumeration<String> aliases = ks.aliases();
+ aliases.hasMoreElements();) {
+ String alias = aliases.nextElement();
+ System.out.println("\t" + alias);
+ ks.deleteEntry(alias);
+ }
+ }
+
+ String alias = "testSKey";
+
+ boolean testResult = checkSecretKeyEntry(alias, softkey, true);
+ if (!testResult) {
+ System.out.println("FAILURE: setKey() w/ softSecretKey failed");
+ }
+
+ if (!checkSecretKeyEntry(alias, sk1, true)) {
+ testResult = false;
+ System.out.println("FAILURE: setKey() w/ skey1 failed");
+ }
+ if (!checkSecretKeyEntry(alias, sk2, true)) {
+ testResult = false;
+ System.out.println("FAILURE: setKey() w/ skey2 failed");
+ }
+
+ ks.store(null);
+ System.out.println("Reloading keystore...");
+
+ ks.load(null, "whatever".toCharArray());
+ if (ks.size() != 1) {
+ System.out.println("FAILURE: reload#1 ks.size() != 1");
+ }
+ if (!checkSecretKeyEntry(alias, sk2, false)) {
+ testResult = false;
+ System.out.println("FAILURE: reload#1 ks entry check failed");
+ }
+
+ ks.deleteEntry(alias);
+ ks.store(null);
+
+ System.out.println("Reloading keystore...");
+ ks.load(null, "whatever".toCharArray());
+ if (ks.size() != 0) {
+ testResult = false;
+ System.out.println("FAILURE: reload#2 ks.size() != 0");
+ }
+ if (!testResult) {
+ throw new Exception("One or more test failed!");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh Mon Apr 07 14:19:23 2008 -0700
@@ -0,0 +1,164 @@
+#
+# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+# CA 95054 USA or visit www.sun.com if you need additional information or
+# have any questions.
+#
+
+# @test
+# @bug 6599979
+# @summary Ensure that re-assigning the alias works
+#
+# @run shell SecretKeysBasic.sh
+#
+# To run by hand:
+# %sh SecretKeysBasic.sh
+#
+# Note:
+# . test only runs on solaris at the moment
+
+# set a few environment variables so that the shell-script can run stand-alone
+# in the source directory
+
+# if running by hand on windows, change TESTSRC and TESTCLASSES to "."
+if [ "${TESTSRC}" = "" ] ; then
+ TESTSRC=`pwd`
+fi
+if [ "${TESTCLASSES}" = "" ] ; then
+ TESTCLASSES=`pwd`
+fi
+
+# if running by hand on windows, change this to appropriate value
+if [ "${TESTJAVA}" = "" ] ; then
+ TESTJAVA="/net/shimmer/export/valeriep/jdk7/build/solaris-sparc"
+fi
+echo TESTSRC=${TESTSRC}
+echo TESTCLASSES=${TESTCLASSES}
+echo TESTJAVA=${TESTJAVA}
+echo ""
+
+#DEBUG=sunpkcs11,pkcs11keystore
+
+echo DEBUG=${DEBUG}
+echo ""
+
+OS=`uname -s`
+case "$OS" in
+ SunOS )
+ FS="/"
+ PS=":"
+ SCCS="${FS}usr${FS}ccs${FS}bin${FS}sccs"
+ CP="${FS}bin${FS}cp -f"
+ RM="${FS}bin${FS}rm -rf"
+ MKDIR="${FS}bin${FS}mkdir -p"
+ CHMOD="${FS}bin${FS}chmod"
+ ;;
+ * )
+ echo "Unsupported System ${OS} - Test only runs on Solaris"
+ exit 0;
+ ;;
+esac
+
+TOKENS="nss solaris"
+STATUS=0
+for token in ${TOKENS}
+do
+
+if [ ${token} = "nss" ]
+then
+ # make cert/key DBs writable if token is NSS
+ ${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}cert8.db ${TESTCLASSES}
+ ${CHMOD} +w ${TESTCLASSES}${FS}cert8.db
+
+ ${CP} ${TESTSRC}${FS}..${FS}nss${FS}db${FS}key3.db ${TESTCLASSES}
+ ${CHMOD} +w ${TESTCLASSES}${FS}key3.db
+ USED_FILE_LIST="${TESTCLASSES}${FS}cert8.db ${TESTCLASSES}${FS}key3.db"
+elif [ ${token} = "solaris" ]
+then
+ OS_VERSION=`uname -r`
+ case "${OS_VERSION}" in
+ 5.1* )
+ SOFTTOKEN_DIR=${TESTCLASSES}
+ export SOFTTOKEN_DIR
+ ;;
+ * )
+ echo "Unsupported Version ${OS_VERSION} - Test only runs on Solaris"
+ exit 0;
+ ;;
+ esac
+
+ # copy keystore into write-able location
+ if [ -d ${TESTCLASSES}${FS}pkcs11_softtoken ]
+ then
+ echo "Removing old pkcs11_keystore, creating new pkcs11_keystore"
+
+ echo ${RM} ${TESTCLASSES}${FS}pkcs11_softtoken
+ ${RM} ${TESTCLASSES}${FS}pkcs11_softtoken
+ fi
+ echo ${MKDIR} ${TESTCLASSES}${FS}pkcs11_softtoken${FS}private
+ ${MKDIR} ${TESTCLASSES}${FS}pkcs11_softtoken${FS}private
+
+ echo ${MKDIR} ${TESTCLASSES}${FS}pkcs11_softtoken${FS}public
+ ${MKDIR} ${TESTCLASSES}${FS}pkcs11_softtoken${FS}public
+
+ echo ${CP} ${TESTSRC}${FS}BasicData${FS}pkcs11_softtoken${FS}objstore_info \
+ ${TESTCLASSES}${FS}pkcs11_softtoken
+ ${CP} ${TESTSRC}${FS}BasicData${FS}pkcs11_softtoken${FS}objstore_info \
+ ${TESTCLASSES}${FS}pkcs11_softtoken
+
+ echo ${CHMOD} +w ${TESTCLASSES}${FS}pkcs11_softtoken${FS}objstore_info
+ ${CHMOD} 600 ${TESTCLASSES}${FS}pkcs11_softtoken${FS}objstore_info
+ USED_FILE_LIST="${TESTCLASSES}${FS}pkcs11_softtoken"
+fi
+
+cd ${TESTCLASSES}
+${TESTJAVA}${FS}bin${FS}javac \
+ -classpath ${TESTCLASSES} \
+ -d ${TESTCLASSES} \
+ ${TESTSRC}${FS}SecretKeysBasic.java
+
+# run test
+cd ${TESTSRC}
+${TESTJAVA}${FS}bin${FS}java \
+ -DDIR=${TESTSRC}${FS}BasicData${FS} \
+ -classpath ${TESTCLASSES}${PS}${TESTSRC}${FS}loader.jar \
+ -DCUSTOM_DB_DIR=${TESTCLASSES} \
+ -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-${token}.txt \
+ -DNO_DEFAULT=true \
+ -DNO_DEIMOS=true \
+ -DTOKEN=${token} \
+ -Djava.security.debug=${DEBUG} \
+ SecretKeysBasic
+
+# -DCUSTOM_P11_CONFIG=${TESTSRC}${FS}BasicData${FS}p11-${token}.txt \
+
+# save error status
+if [ $? != 0 ]
+then
+ echo "Test against " ${token} " Failed!"
+ STATUS=1
+fi
+
+# clean up
+${RM} ${USED_FILE_LIST}
+
+done
+
+# return
+exit ${STATUS}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/CriticalSubjectAltName.java Mon Apr 07 14:19:23 2008 -0700
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2001-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/*
+ * @test
+ * @bug 6668231
+ * @summary Presence of a critical subjectAltName causes JSSE's SunX509 to
+ * fail trusted checks
+ * @author Xuelei Fan
+ *
+ * This test depends on binary keystore, crisubn.jks and trusted.jks. Because
+ * JAVA keytool cannot generate X509 certificate with SubjectAltName extension,
+ * the certificates are generated with openssl toolkits and then imported into
+ * JAVA keystore.
+ *
+ * The crisubn.jks holds a private key entry and the corresponding X509
+ * certificate issued with an empty Subject field, and a critical
+ * SubjectAltName extension.
+ *
+ * The trusted.jks holds the trusted certificate.
+ */
+import java.io.*;
+import java.net.*;
+import javax.net.ssl.*;
+import java.security.cert.Certificate;
+
+public class CriticalSubjectAltName implements HostnameVerifier {
+ /*
+ * =============================================================
+ * Set the various variables needed for the tests, then
+ * specify what tests to run on each side.
+ */
+
+ /*
+ * Should we run the client or server in a separate thread?
+ * Both sides can throw exceptions, but do you have a preference
+ * as to which side should be the main thread.
+ */
+ static boolean separateServerThread = true;
+
+ /*
+ * Where do we find the keystores?
+ */
+ static String pathToStores = "./";
+ static String keyStoreFile = "crisubn.jks";
+ static String trustStoreFile = "trusted.jks";
+ static String passwd = "passphrase";
+
+ /*
+ * Is the server ready to serve?
+ */
+ volatile static boolean serverReady = false;
+
+ /*
+ * Turn on SSL debugging?
+ */
+ static boolean debug = false;
+
+ /*
+ * If the client or server is doing some kind of object creation
+ * that the other side depends on, and that thread prematurely
+ * exits, you may experience a hang. The test harness will
+ * terminate all hung threads after its timeout has expired,
+ * currently 3 minutes by default, but you might try to be
+ * smart about it....
+ */
+
+ /*
+ * Define the server side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doServerSide() throws Exception {
+ SSLServerSocketFactory sslssf =
+ (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
+ SSLServerSocket sslServerSocket =
+ (SSLServerSocket) sslssf.createServerSocket(serverPort);
+ serverPort = sslServerSocket.getLocalPort();
+
+ /*
+ * Signal Client, we're ready for his connect.
+ */
+ serverReady = true;
+
+ SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
+ OutputStream sslOS = sslSocket.getOutputStream();
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sslOS));
+ bw.write("HTTP/1.1 200 OK\r\n\r\n\r\n");
+ bw.flush();
+ Thread.sleep(5000);
+ sslSocket.close();
+ }
+
+ /*
+ * Define the client side of the test.
+ *
+ * If the server prematurely exits, serverReady will be set to true
+ * to avoid infinite hangs.
+ */
+ void doClientSide() throws Exception {
+
+ /*
+ * Wait for server to get started.
+ */
+ while (!serverReady) {
+ Thread.sleep(50);
+ }
+
+ URL url = new URL("https://localhost:"+serverPort+"/index.html");
+ HttpsURLConnection urlc = (HttpsURLConnection)url.openConnection();
+ urlc.setHostnameVerifier(this);
+ urlc.getInputStream();
+
+ if (urlc.getResponseCode() == -1) {
+ throw new RuntimeException("getResponseCode() returns -1");
+ }
+ }
+
+ /*
+ * =============================================================
+ * The remainder is just support stuff
+ */
+
+ // use any free port by default
+ volatile int serverPort = 0;
+
+ volatile Exception serverException = null;
+ volatile Exception clientException = null;
+
+ public static void main(String[] args) throws Exception {
+ String keyFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + keyStoreFile;
+ String trustFilename =
+ System.getProperty("test.src", "./") + "/" + pathToStores +
+ "/" + trustStoreFile;
+
+ System.setProperty("javax.net.ssl.keyStore", keyFilename);
+ System.setProperty("javax.net.ssl.keyStorePassword", passwd);
+ System.setProperty("javax.net.ssl.trustStore", trustFilename);
+ System.setProperty("javax.net.ssl.trustStorePassword", passwd);
+
+ if (debug)
+ System.setProperty("javax.net.debug", "all");
+
+ /*
+ * Start the tests.
+ */
+ new CriticalSubjectAltName();
+ }
+
+ Thread clientThread = null;
+ Thread serverThread = null;
+
+ /*
+ * Primary constructor, used to drive remainder of the test.
+ *
+ * Fork off the other side, then do your work.
+ */
+ CriticalSubjectAltName() throws Exception {
+ if (separateServerThread) {
+ startServer(true);
+ startClient(false);
+ } else {
+ startClient(true);
+ startServer(false);
+ }
+
+ /*
+ * Wait for other side to close down.
+ */
+ if (separateServerThread) {
+ serverThread.join();
+ } else {
+ clientThread.join();
+ }
+
+ /*
+ * When we get here, the test is pretty much over.
+ *
+ * If the main thread excepted, that propagates back
+ * immediately. If the other thread threw an exception, we
+ * should report back.
+ */
+ if (serverException != null)
+ throw serverException;
+ if (clientException != null)
+ throw clientException;
+ }
+
+ void startServer(boolean newThread) throws Exception {
+ if (newThread) {
+ serverThread = new Thread() {
+ public void run() {
+ try {
+ doServerSide();
+ } catch (Exception e) {
+ /*
+ * Our server thread just died.
+ *
+ * Release the client, if not active already...
+ */
+ System.err.println("Server died...");
+ serverReady = true;
+ serverException = e;
+ }
+ }
+ };
+ serverThread.start();
+ } else {
+ doServerSide();
+ }
+ }
+
+ void startClient(boolean newThread) throws Exception {
+ if (newThread) {
+ clientThread = new Thread() {
+ public void run() {
+ try {
+ doClientSide();
+ } catch (Exception e) {
+ /*
+ * Our client thread just died.
+ */
+ System.err.println("Client died...");
+ clientException = e;
+ }
+ }
+ };
+ clientThread.start();
+ } else {
+ doClientSide();
+ }
+ }
+
+ // Simple test method to blindly agree that hostname and certname match
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+
+}
Binary file jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/crisubn.jks has changed
Binary file jdk/test/sun/security/ssl/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnection/trusted.jks has changed