mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 03:24:38 +02:00
Merge
This commit is contained in:
commit
bbe29fa484
23 changed files with 1943 additions and 562 deletions
|
@ -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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -87,8 +87,7 @@
|
||||||
# sign Alias for sign-jar
|
# sign Alias for sign-jar
|
||||||
# sign-jar Builds/signs sunjce_provider.jar (no install)
|
# sign-jar Builds/signs sunjce_provider.jar (no install)
|
||||||
#
|
#
|
||||||
# obfus Builds/obfuscates/signs/installs
|
# obfus Builds/obfuscates/signs sunjce_provider.jar
|
||||||
# sunjce_provider.jar
|
|
||||||
#
|
#
|
||||||
# release Builds all targets in preparation
|
# release Builds all targets in preparation
|
||||||
# for workspace integration.
|
# for workspace integration.
|
||||||
|
@ -101,8 +100,25 @@
|
||||||
BUILDDIR = ../../../..
|
BUILDDIR = ../../../..
|
||||||
PACKAGE = com.sun.crypto.provider
|
PACKAGE = com.sun.crypto.provider
|
||||||
PRODUCT = sun
|
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)/common/Defs.gmk
|
||||||
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Location for the newly built classfiles.
|
# Location for the newly built classfiles.
|
||||||
|
@ -147,6 +163,8 @@ endif # OPENJDK
|
||||||
#
|
#
|
||||||
UNSIGNED_DIR = $(TEMPDIR)/unsigned
|
UNSIGNED_DIR = $(TEMPDIR)/unsigned
|
||||||
|
|
||||||
|
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
||||||
|
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# Build the unsigned sunjce_provider.jar file.
|
# Build the unsigned sunjce_provider.jar file.
|
||||||
|
@ -184,44 +202,66 @@ ifndef OPENJDK
|
||||||
# Sign the provider jar file. Not needed for OpenJDK.
|
# Sign the provider jar file. Not needed for OpenJDK.
|
||||||
#
|
#
|
||||||
|
|
||||||
SIGNED_DIR = $(TEMPDIR)/signed
|
SIGNED_DIR = $(JCE_BUILD_DIR)/signed
|
||||||
|
|
||||||
sign: sign-jar
|
sign: sign-jar
|
||||||
|
|
||||||
sign-jar: $(SIGNED_DIR)/sunjce_provider.jar
|
sign-jar: $(SIGNED_DIR)/sunjce_provider.jar
|
||||||
|
|
||||||
|
ifndef ALT_JCE_BUILD_DIR
|
||||||
$(SIGNED_DIR)/sunjce_provider.jar: $(UNSIGNED_DIR)/sunjce_provider.jar
|
$(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.
|
# 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
|
CLOSED_DIR = $(BUILDDIR)/closed/com/sun/crypto/provider
|
||||||
|
|
||||||
obfus: $(OBFUS_DIR)/sunjce_provider.jar
|
obfus: $(OBFUS_DIR)/sunjce_provider.jar
|
||||||
$(release-warning)
|
$(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)
|
$(presign)
|
||||||
$(preobfus)
|
$(preobfus)
|
||||||
@$(ECHO) ">>>Obfuscating Sun JCE Provider..."
|
|
||||||
$(prep-target)
|
$(prep-target)
|
||||||
$(CD) $(OBFUS_DIR); \
|
$(CD) $(OBFUS_DIR); \
|
||||||
$(OBFUSCATOR) -fv \
|
$(OBFUSCATOR) -fv sunjce.dox
|
||||||
$(CURRENT_DIRECTORY)/$(CLOSED_DIR)/obfus/sunjce.dox
|
|
||||||
@$(CD) $(OBFUS_DIR); $(java-vm-cleanup)
|
@$(CD) $(OBFUS_DIR); $(java-vm-cleanup)
|
||||||
$(BOOT_JAR_CMD) cmf $(JCE_MANIFEST_FILE) $@ \
|
$(BOOT_JAR_CMD) cmf $(JCE_MANIFEST_FILE) $@ \
|
||||||
-C $(OBFUS_DIR)/build com \
|
-C $(OBFUS_DIR)/build com \
|
||||||
$(JAR_JFLAGS)
|
$(JAR_JFLAGS)
|
||||||
$(sign-target)
|
$(sign-target)
|
||||||
$(MKDIR) -p $(dir $(JAR_DESTFILE))
|
|
||||||
$(RM) $(JAR_DESTFILE)
|
|
||||||
$(CP) $@ $(JAR_DESTFILE)
|
|
||||||
@$(java-vm-cleanup)
|
@$(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
|
# The current obfuscator has a limitation in that it currently only
|
||||||
# supports up to v49 class file format. Force v49 classfiles in our
|
# supports up to v49 class file format. Force v49 classfiles in our
|
||||||
|
@ -235,9 +275,9 @@ TARGET_CLASS_VERSION = 5
|
||||||
#
|
#
|
||||||
|
|
||||||
release: $(OBFUS_DIR)/sunjce_provider.jar
|
release: $(OBFUS_DIR)/sunjce_provider.jar
|
||||||
$(RM) $(RELEASE_DIR)/sunjce_provider.jar
|
$(RM) $(JCE_BUILD_DIR)/release/sunjce_provider.jar
|
||||||
$(MKDIR) -p $(RELEASE_DIR)
|
$(MKDIR) -p $(JCE_BUILD_DIR)/release
|
||||||
$(CP) $(OBFUS_DIR)/sunjce_provider.jar $(RELEASE_DIR)
|
$(CP) $(OBFUS_DIR)/sunjce_provider.jar $(JCE_BUILD_DIR)/release
|
||||||
$(release-warning)
|
$(release-warning)
|
||||||
|
|
||||||
endif # OPENJDK
|
endif # OPENJDK
|
||||||
|
@ -275,7 +315,7 @@ endif
|
||||||
#
|
#
|
||||||
|
|
||||||
clobber clean::
|
clobber clean::
|
||||||
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR)
|
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
|
||||||
|
|
||||||
.PHONY: build-jar jar install-jar
|
.PHONY: build-jar jar install-jar
|
||||||
ifndef OPENJDK
|
ifndef OPENJDK
|
||||||
|
|
|
@ -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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -449,11 +449,20 @@ endif
|
||||||
# Check for spaces and null value
|
# Check for spaces and null value
|
||||||
OUTPUTDIR:=$(call AltCheckSpaces,OUTPUTDIR)
|
OUTPUTDIR:=$(call AltCheckSpaces,OUTPUTDIR)
|
||||||
OUTPUTDIR:=$(call AltCheckValue,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 the output directory and make sure it exists and is writable
|
||||||
_create_outputdir:=$(shell $(MKDIR) -p "$(OUTPUTDIR)" > $(DEV_NULL) 2>&1)
|
_create_outputdir:=$(shell $(MKDIR) -p "$(OUTPUTDIR)" > $(DEV_NULL) 2>&1)
|
||||||
ifeq ($(call WriteDirExists,$(OUTPUTDIR),/dev/null),/dev/null)
|
ifeq ($(call WriteDirExists,$(OUTPUTDIR),/dev/null),/dev/null)
|
||||||
_outputdir_error:=$(error "ERROR: OUTPUTDIR '$(OUTPUTDIR)' not created or not writable")
|
_outputdir_error:=$(error "ERROR: OUTPUTDIR '$(OUTPUTDIR)' not created or not writable")
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# Define absolute path if needed and check for spaces and null value
|
# Define absolute path if needed and check for spaces and null value
|
||||||
ifndef ABS_OUTPUTDIR
|
ifndef ABS_OUTPUTDIR
|
||||||
ABS_OUTPUTDIR:=$(call FullPath,$(OUTPUTDIR))
|
ABS_OUTPUTDIR:=$(call FullPath,$(OUTPUTDIR))
|
||||||
|
|
|
@ -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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -31,7 +31,7 @@ include $(BUILDDIR)/common/Release.gmk
|
||||||
JCE_MANIFEST_FILE = $(TEMPDIR)/manifest.mf
|
JCE_MANIFEST_FILE = $(TEMPDIR)/manifest.mf
|
||||||
$(JCE_MANIFEST_FILE): $(MAINMANIFEST)
|
$(JCE_MANIFEST_FILE): $(MAINMANIFEST)
|
||||||
$(prep-target)
|
$(prep-target)
|
||||||
( $(SED) "s/@@RELEASE@@/$(RELEASE)/" $(MAINMANIFEST); \
|
( $(SED) "s/@@RELEASE@@/$(RELEASE)/" $<; \
|
||||||
$(ECHO) "Extension-Name: javax.crypto"; \
|
$(ECHO) "Extension-Name: javax.crypto"; \
|
||||||
$(ECHO) "Implementation-Vendor-Id: com.sun"; ) > $@
|
$(ECHO) "Implementation-Vendor-Id: com.sun"; ) > $@
|
||||||
|
|
||||||
|
@ -75,6 +75,7 @@ endef
|
||||||
define sign-target
|
define sign-target
|
||||||
$(BOOT_JARSIGNER_CMD) -keystore $(SIGNING_KEYSTORE) \
|
$(BOOT_JARSIGNER_CMD) -keystore $(SIGNING_KEYSTORE) \
|
||||||
$@ $(SIGNING_ALIAS) < $(SIGNING_PASSPHRASE)
|
$@ $(SIGNING_ALIAS) < $(SIGNING_PASSPHRASE)
|
||||||
|
@$(java-vm-cleanup)
|
||||||
@$(ECHO) "\nJar codesigning finished."
|
@$(ECHO) "\nJar codesigning finished."
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
@ -88,13 +89,15 @@ define release-warning
|
||||||
endef
|
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
|
define sign-file
|
||||||
$(presign)
|
$(presign)
|
||||||
$(install-file)
|
$(prep-target)
|
||||||
|
$(CP) $1 $@
|
||||||
$(sign-target)
|
$(sign-target)
|
||||||
@$(java-vm-cleanup)
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# 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-jar Builds/signs jce.jar file (no install)
|
||||||
# sign-policy Builds/signs policy files (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
|
# release Builds all targets in preparation
|
||||||
# for workspace integration.
|
# for workspace integration.
|
||||||
|
@ -110,8 +110,24 @@ BUILDDIR = ../..
|
||||||
PACKAGE = javax.crypto
|
PACKAGE = javax.crypto
|
||||||
PRODUCT = sun
|
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)/common/Defs.gmk
|
||||||
include Defs-jce.gmk
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Location for the newly built classfiles.
|
# Location for the newly built classfiles.
|
||||||
|
@ -158,6 +174,8 @@ endif # OPENJDK
|
||||||
#
|
#
|
||||||
UNSIGNED_DIR = $(TEMPDIR)/unsigned
|
UNSIGNED_DIR = $(TEMPDIR)/unsigned
|
||||||
|
|
||||||
|
include Defs-jce.gmk
|
||||||
|
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# Build the unsigned jce.jar file. Signing/obfuscation comes later.
|
# Build the unsigned jce.jar file. Signing/obfuscation comes later.
|
||||||
|
@ -299,7 +317,7 @@ ifndef OPENJDK
|
||||||
# Sign the various jar files. Not needed for OpenJDK.
|
# 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_BUILDDIR = $(SIGNED_DIR)/policy
|
||||||
|
|
||||||
SIGNED_POLICY_FILES = \
|
SIGNED_POLICY_FILES = \
|
||||||
|
@ -312,61 +330,87 @@ sign-jar: $(SIGNED_DIR)/jce.jar
|
||||||
|
|
||||||
sign-policy: $(SIGNED_POLICY_FILES)
|
sign-policy: $(SIGNED_POLICY_FILES)
|
||||||
|
|
||||||
|
ifndef ALT_JCE_BUILD_DIR
|
||||||
$(SIGNED_DIR)/jce.jar: $(UNSIGNED_DIR)/jce.jar
|
$(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: \
|
$(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar: \
|
||||||
$(UNSIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar
|
$(UNSIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar
|
||||||
$(sign-file)
|
$(call sign-file, $<)
|
||||||
|
|
||||||
$(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar: \
|
$(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar: \
|
||||||
$(UNSIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar
|
$(UNSIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar
|
||||||
$(sign-file)
|
$(call sign-file, $<)
|
||||||
|
|
||||||
$(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar: \
|
$(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar: \
|
||||||
$(UNSIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar
|
$(UNSIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar
|
||||||
$(sign-file)
|
$(call sign-file, $<)
|
||||||
|
|
||||||
$(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar: \
|
$(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar: \
|
||||||
$(UNSIGNED_POLICY_BUILDDIR)/limited/local_policy.jar
|
$(UNSIGNED_POLICY_BUILDDIR)/limited/local_policy.jar
|
||||||
$(sign-file)
|
$(call sign-file, $<)
|
||||||
|
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# Obfuscate/sign/install the JDK build. Not needed for OpenJDK.
|
# 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
|
CLOSED_DIR = $(BUILDDIR)/closed/javax/crypto
|
||||||
|
|
||||||
obfus: $(OBFUS_DIR)/jce.jar
|
obfus: $(OBFUS_DIR)/jce.jar
|
||||||
$(release-warning)
|
$(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)
|
$(presign)
|
||||||
$(preobfus)
|
$(preobfus)
|
||||||
@$(ECHO) ">>>Obfuscating JCE framework..."
|
|
||||||
$(prep-target)
|
$(prep-target)
|
||||||
$(CD) $(OBFUS_DIR); \
|
$(CD) $(OBFUS_DIR); \
|
||||||
$(OBFUSCATOR) -fv \
|
$(OBFUSCATOR) -fv framework.dox
|
||||||
$(CURRENT_DIRECTORY)/$(CLOSED_DIR)/obfus/framework.dox
|
|
||||||
@$(CD) $(OBFUS_DIR); $(java-vm-cleanup)
|
@$(CD) $(OBFUS_DIR); $(java-vm-cleanup)
|
||||||
|
@#
|
||||||
@# The sun.security.internal classes are currently not obfuscated
|
@# The sun.security.internal classes are currently not obfuscated
|
||||||
@# due to an obfus problem. Manually copy them to the build directory
|
@# due to an obfus problem. Manually copy them to the build directory
|
||||||
@# so that they are included in the jce.jar file.
|
@# so that they are included in the jce.jar file.
|
||||||
|
@#
|
||||||
$(CP) -r $(CLASSDESTDIR)/sun $(OBFUS_DIR)/build
|
$(CP) -r $(CLASSDESTDIR)/sun $(OBFUS_DIR)/build
|
||||||
$(RM) $(UNSIGNED_DIR)/jce.jar
|
|
||||||
$(BOOT_JAR_CMD) cmf $(JCE_MANIFEST_FILE) $@ \
|
$(BOOT_JAR_CMD) cmf $(JCE_MANIFEST_FILE) $@ \
|
||||||
-C $(OBFUS_DIR)/build javax \
|
-C $(OBFUS_DIR)/build javax \
|
||||||
-C $(OBFUS_DIR)/build sun \
|
-C $(OBFUS_DIR)/build sun \
|
||||||
$(JAR_JFLAGS)
|
$(JAR_JFLAGS)
|
||||||
$(sign-target)
|
$(sign-target)
|
||||||
$(MKDIR) -p $(dir $(JAR_DESTFILE))
|
|
||||||
$(RM) $(JAR_DESTFILE)
|
|
||||||
$(CP) $@ $(JAR_DESTFILE)
|
|
||||||
@$(java-vm-cleanup)
|
@$(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
|
# The current obfuscator has a limitation in that it currently only
|
||||||
# supports up to v49 class file format. Force v49 classfiles in our
|
# supports up to v49 class file format. Force v49 classfiles in our
|
||||||
|
@ -380,26 +424,27 @@ TARGET_CLASS_VERSION = 5
|
||||||
# unlimited policy file distribution, etc.
|
# 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 \
|
$(RM) -r \
|
||||||
$(RELEASE_DIR)/UnlimitedJCEPolicy \
|
$(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy \
|
||||||
$(RELEASE_DIR)/jce.jar \
|
$(JCE_BUILD_DIR)/release/jce.jar \
|
||||||
$(RELEASE_DIR)/US_export_policy.jar \
|
$(JCE_BUILD_DIR)/release/US_export_policy.jar \
|
||||||
$(RELEASE_DIR)/local_policy.jar \
|
$(JCE_BUILD_DIR)/release/local_policy.jar \
|
||||||
$(RELEASE_DIR)/UnlimitedJCEPolicy.zip
|
$(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy.zip
|
||||||
$(MKDIR) -p $(RELEASE_DIR)/UnlimitedJCEPolicy
|
$(MKDIR) -p $(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy
|
||||||
$(CP) $(OBFUS_DIR)/jce.jar $(RELEASE_DIR)
|
$(CP) $(OBFUS_DIR)/jce.jar $(JCE_BUILD_DIR)/release
|
||||||
$(CP) -r \
|
$(CP) \
|
||||||
$(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar \
|
$(SIGNED_POLICY_BUILDDIR)/limited/US_export_policy.jar \
|
||||||
$(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar \
|
$(SIGNED_POLICY_BUILDDIR)/limited/local_policy.jar \
|
||||||
$(RELEASE_DIR)
|
$(JCE_BUILD_DIR)/release
|
||||||
$(CP) \
|
$(CP) \
|
||||||
$(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar \
|
$(SIGNED_POLICY_BUILDDIR)/unlimited/US_export_policy.jar \
|
||||||
$(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar \
|
$(SIGNED_POLICY_BUILDDIR)/unlimited/local_policy.jar \
|
||||||
$(RELEASE_DIR)/UnlimitedJCEPolicy
|
$(CLOSED_DIR)/doc/COPYRIGHT.html \
|
||||||
$(CP) $(CLOSED_DIR)/doc/COPYRIGHT.html \
|
$(CLOSED_DIR)/doc/README.txt \
|
||||||
$(CLOSED_DIR)/doc/README.txt $(RELEASE_DIR)/UnlimitedJCEPolicy
|
$(JCE_BUILD_DIR)/release/UnlimitedJCEPolicy
|
||||||
cd $(RELEASE_DIR) ; \
|
cd $(JCE_BUILD_DIR)/release ; \
|
||||||
$(ZIPEXE) -qr UnlimitedJCEPolicy.zip UnlimitedJCEPolicy
|
$(ZIPEXE) -qr UnlimitedJCEPolicy.zip UnlimitedJCEPolicy
|
||||||
$(release-warning)
|
$(release-warning)
|
||||||
|
|
||||||
|
@ -478,7 +523,8 @@ endif
|
||||||
|
|
||||||
clobber clean::
|
clobber clean::
|
||||||
$(RM) -r $(JAR_DESTFILE) $(POLICY_DESTDIR)/US_export_policy.jar \
|
$(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 \
|
.PHONY: build-jar jar build-policy unlimited limited install-jar \
|
||||||
install-limited install-unlimited
|
install-limited install-unlimited
|
||||||
|
|
|
@ -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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -92,8 +92,25 @@ BUILDDIR = ../../..
|
||||||
PACKAGE = sun.security.mscapi
|
PACKAGE = sun.security.mscapi
|
||||||
LIBRARY = sunmscapi
|
LIBRARY = sunmscapi
|
||||||
PRODUCT = sun
|
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)/common/Defs.gmk
|
||||||
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
|
||||||
|
|
||||||
CPLUSPLUSLIBRARY=true
|
CPLUSPLUSLIBRARY=true
|
||||||
|
|
||||||
|
@ -163,6 +180,8 @@ all: build-jar install-prebuilt
|
||||||
$(build-warning)
|
$(build-warning)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
||||||
|
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# Build the unsigned sunmscapi.jar file.
|
# Build the unsigned sunmscapi.jar file.
|
||||||
|
@ -200,14 +219,26 @@ ifndef OPENJDK
|
||||||
# Sign the provider jar file. Not needed for OpenJDK.
|
# Sign the provider jar file. Not needed for OpenJDK.
|
||||||
#
|
#
|
||||||
|
|
||||||
SIGNED_DIR = $(TEMPDIR)/signed
|
SIGNED_DIR = $(JCE_BUILD_DIR)/signed
|
||||||
|
|
||||||
sign: sign-jar
|
sign: sign-jar
|
||||||
|
|
||||||
sign-jar: $(SIGNED_DIR)/sunmscapi.jar
|
sign-jar: $(SIGNED_DIR)/sunmscapi.jar
|
||||||
|
|
||||||
|
ifndef ALT_JCE_BUILD_DIR
|
||||||
$(SIGNED_DIR)/sunmscapi.jar: $(UNSIGNED_DIR)/sunmscapi.jar
|
$(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 @@ $(SIGNED_DIR)/sunmscapi.jar: $(UNSIGNED_DIR)/sunmscapi.jar
|
||||||
#
|
#
|
||||||
|
|
||||||
release: $(SIGNED_DIR)/sunmscapi.jar
|
release: $(SIGNED_DIR)/sunmscapi.jar
|
||||||
$(RM) $(RELEASE_DIR)/sunmscapi.jar
|
$(RM) $(JCE_BUILD_DIR)/release/sunmscapi.jar
|
||||||
$(MKDIR) -p $(RELEASE_DIR)
|
$(MKDIR) -p $(JCE_BUILD_DIR)/release
|
||||||
$(CP) $(SIGNED_DIR)/sunmscapi.jar $(RELEASE_DIR)
|
$(CP) $(SIGNED_DIR)/sunmscapi.jar $(JCE_BUILD_DIR)/release
|
||||||
$(release-warning)
|
$(release-warning)
|
||||||
|
|
||||||
endif # OPENJDK
|
endif # OPENJDK
|
||||||
|
@ -255,7 +286,7 @@ endif
|
||||||
#
|
#
|
||||||
|
|
||||||
clobber clean::
|
clobber clean::
|
||||||
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR)
|
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
|
||||||
|
|
||||||
.PHONY: build-jar jar install-jar
|
.PHONY: build-jar jar install-jar
|
||||||
ifndef OPENJDK
|
ifndef OPENJDK
|
||||||
|
|
|
@ -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.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -92,8 +92,25 @@ BUILDDIR = ../../..
|
||||||
PACKAGE = sun.security.pkcs11
|
PACKAGE = sun.security.pkcs11
|
||||||
LIBRARY = j2pkcs11
|
LIBRARY = j2pkcs11
|
||||||
PRODUCT = sun
|
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)/common/Defs.gmk
|
||||||
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# C and Java Files
|
# C and Java Files
|
||||||
|
@ -163,6 +180,8 @@ all: build-jar install-prebuilt
|
||||||
$(build-warning)
|
$(build-warning)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
include $(BUILDDIR)/javax/crypto/Defs-jce.gmk
|
||||||
|
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# Build the unsigned sunpkcs11.jar file.
|
# Build the unsigned sunpkcs11.jar file.
|
||||||
|
@ -200,14 +219,26 @@ ifndef OPENJDK
|
||||||
# Sign the provider jar file. Not needed for OpenJDK.
|
# Sign the provider jar file. Not needed for OpenJDK.
|
||||||
#
|
#
|
||||||
|
|
||||||
SIGNED_DIR = $(TEMPDIR)/signed
|
SIGNED_DIR = $(JCE_BUILD_DIR)/signed
|
||||||
|
|
||||||
sign: sign-jar
|
sign: sign-jar
|
||||||
|
|
||||||
sign-jar: $(SIGNED_DIR)/sunpkcs11.jar
|
sign-jar: $(SIGNED_DIR)/sunpkcs11.jar
|
||||||
|
|
||||||
|
ifndef ALT_JCE_BUILD_DIR
|
||||||
$(SIGNED_DIR)/sunpkcs11.jar: $(UNSIGNED_DIR)/sunpkcs11.jar
|
$(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 @@ $(SIGNED_DIR)/sunpkcs11.jar: $(UNSIGNED_DIR)/sunpkcs11.jar
|
||||||
#
|
#
|
||||||
|
|
||||||
release: $(SIGNED_DIR)/sunpkcs11.jar
|
release: $(SIGNED_DIR)/sunpkcs11.jar
|
||||||
$(RM) $(RELEASE_DIR)/sunpkcs11.jar
|
$(RM) $(JCE_BUILD_DIR)/release/sunpkcs11.jar
|
||||||
$(MKDIR) -p $(RELEASE_DIR)
|
$(MKDIR) -p $(JCE_BUILD_DIR)/release
|
||||||
$(CP) $(SIGNED_DIR)/sunpkcs11.jar $(RELEASE_DIR)
|
$(CP) $(SIGNED_DIR)/sunpkcs11.jar $(JCE_BUILD_DIR)/release
|
||||||
$(release-warning)
|
$(release-warning)
|
||||||
|
|
||||||
endif # OPENJDK
|
endif # OPENJDK
|
||||||
|
@ -255,7 +286,7 @@ endif
|
||||||
#
|
#
|
||||||
|
|
||||||
clobber clean::
|
clobber clean::
|
||||||
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR)
|
$(RM) -r $(JAR_DESTFILE) $(TEMPDIR) $(JCE_BUILD_DIR)
|
||||||
|
|
||||||
.PHONY: build-jar jar install-jar
|
.PHONY: build-jar jar install-jar
|
||||||
ifndef OPENJDK
|
ifndef OPENJDK
|
||||||
|
|
|
@ -91,9 +91,10 @@ public class NegotiatorImpl extends Negotiator {
|
||||||
GSSManagerImpl manager = new GSSManagerImpl(
|
GSSManagerImpl manager = new GSSManagerImpl(
|
||||||
GSSUtil.CALLER_HTTP_NEGOTIATE);
|
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,
|
context = manager.createContext(serverName,
|
||||||
oid,
|
oid,
|
||||||
null,
|
null,
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||||
* have any questions.
|
* have any questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package sun.security.pkcs11;
|
package sun.security.pkcs11;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import java.security.*;
|
import java.security.*;
|
||||||
import java.security.spec.*;
|
import java.security.spec.*;
|
||||||
|
@ -34,7 +34,6 @@ import javax.crypto.*;
|
||||||
import javax.crypto.spec.*;
|
import javax.crypto.spec.*;
|
||||||
|
|
||||||
import sun.nio.ch.DirectBuffer;
|
import sun.nio.ch.DirectBuffer;
|
||||||
|
|
||||||
import sun.security.pkcs11.wrapper.*;
|
import sun.security.pkcs11.wrapper.*;
|
||||||
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
|
|
||||||
|
@ -43,8 +42,8 @@ import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
|
||||||
* DES, DESede, AES, ARCFOUR, and Blowfish.
|
* DES, DESede, AES, ARCFOUR, and Blowfish.
|
||||||
*
|
*
|
||||||
* This class is designed to support ECB and CBC with NoPadding and
|
* This class is designed to support ECB and CBC with NoPadding and
|
||||||
* PKCS5Padding for both. However, currently only CBC/NoPadding (and
|
* PKCS5Padding for both. It will use its own padding impl if the
|
||||||
* ECB/NoPadding for stream ciphers) is functional.
|
* native mechanism does not support padding.
|
||||||
*
|
*
|
||||||
* Note that PKCS#11 current only supports ECB and CBC. There are no
|
* 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.
|
* provisions for other modes such as CFB, OFB, PCBC, or CTR mode.
|
||||||
|
@ -66,6 +65,55 @@ final class P11Cipher extends CipherSpi {
|
||||||
// padding constant for PKCS5Padding
|
// padding constant for PKCS5Padding
|
||||||
private final static int PAD_PKCS5 = 6;
|
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
|
// token instance
|
||||||
private final Token token;
|
private final Token token;
|
||||||
|
|
||||||
|
@ -99,65 +147,93 @@ final class P11Cipher extends CipherSpi {
|
||||||
// padding type, on of PAD_* above (PAD_NONE for stream ciphers)
|
// padding type, on of PAD_* above (PAD_NONE for stream ciphers)
|
||||||
private int paddingType;
|
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
|
// original IV, if in MODE_CBC
|
||||||
private byte[] iv;
|
private byte[] iv;
|
||||||
|
|
||||||
// total number of bytes processed
|
// number of bytes buffered internally by the native mechanism and padBuffer
|
||||||
private int bytesProcessed;
|
// if we do the padding
|
||||||
|
private int bytesBuffered;
|
||||||
|
|
||||||
P11Cipher(Token token, String algorithm, long mechanism)
|
P11Cipher(Token token, String algorithm, long mechanism)
|
||||||
throws PKCS11Exception {
|
throws PKCS11Exception, NoSuchAlgorithmException {
|
||||||
super();
|
super();
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.algorithm = algorithm;
|
this.algorithm = algorithm;
|
||||||
this.mechanism = mechanism;
|
this.mechanism = mechanism;
|
||||||
keyAlgorithm = algorithm.split("/")[0];
|
|
||||||
|
String algoParts[] = algorithm.split("/");
|
||||||
|
keyAlgorithm = algoParts[0];
|
||||||
|
|
||||||
if (keyAlgorithm.equals("AES")) {
|
if (keyAlgorithm.equals("AES")) {
|
||||||
blockSize = 16;
|
blockSize = 16;
|
||||||
blockMode = MODE_CBC;
|
} else if (keyAlgorithm.equals("RC4") ||
|
||||||
// XXX change default to PKCS5Padding
|
keyAlgorithm.equals("ARCFOUR")) {
|
||||||
paddingType = PAD_NONE;
|
|
||||||
} else if (keyAlgorithm.equals("RC4") || keyAlgorithm.equals("ARCFOUR")) {
|
|
||||||
blockSize = 0;
|
blockSize = 0;
|
||||||
blockMode = MODE_ECB;
|
|
||||||
paddingType = PAD_NONE;
|
|
||||||
} else { // DES, DESede, Blowfish
|
} else { // DES, DESede, Blowfish
|
||||||
blockSize = 8;
|
blockSize = 8;
|
||||||
blockMode = MODE_CBC;
|
}
|
||||||
// XXX change default to PKCS5Padding
|
this.blockMode =
|
||||||
paddingType = PAD_NONE;
|
(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();
|
session = token.getOpSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
|
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();
|
mode = mode.toUpperCase();
|
||||||
|
int result;
|
||||||
if (mode.equals("ECB")) {
|
if (mode.equals("ECB")) {
|
||||||
this.blockMode = MODE_ECB;
|
result = MODE_ECB;
|
||||||
} else if (mode.equals("CBC")) {
|
} else if (mode.equals("CBC")) {
|
||||||
if (blockSize == 0) {
|
if (blockSize == 0) {
|
||||||
throw new NoSuchAlgorithmException
|
throw new NoSuchAlgorithmException
|
||||||
("CBC mode not supported with stream ciphers");
|
("CBC mode not supported with stream ciphers");
|
||||||
}
|
}
|
||||||
this.blockMode = MODE_CBC;
|
result = MODE_CBC;
|
||||||
} else {
|
} else {
|
||||||
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
throw new NoSuchAlgorithmException("Unsupported mode " + mode);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected void engineSetPadding(String padding)
|
protected void engineSetPadding(String padding)
|
||||||
throws NoSuchPaddingException {
|
throws NoSuchPaddingException {
|
||||||
if (padding.equalsIgnoreCase("NoPadding")) {
|
paddingObj = null;
|
||||||
|
padBuffer = null;
|
||||||
|
padding = padding.toUpperCase();
|
||||||
|
if (padding.equals("NOPADDING")) {
|
||||||
paddingType = PAD_NONE;
|
paddingType = PAD_NONE;
|
||||||
} else if (padding.equalsIgnoreCase("PKCS5Padding")) {
|
} else if (padding.equals("PKCS5PADDING")) {
|
||||||
if (blockSize == 0) {
|
|
||||||
throw new NoSuchPaddingException
|
|
||||||
("PKCS#5 padding not supported with stream ciphers");
|
|
||||||
}
|
|
||||||
paddingType = PAD_PKCS5;
|
paddingType = PAD_PKCS5;
|
||||||
// XXX PKCS#5 not yet implemented
|
if (mechanism != CKM_DES_CBC_PAD && mechanism != CKM_DES3_CBC_PAD &&
|
||||||
throw new NoSuchPaddingException("pkcs5");
|
mechanism != CKM_AES_CBC_PAD) {
|
||||||
|
// no native padding support; use our own padding impl
|
||||||
|
paddingObj = new PKCS5Padding(blockSize);
|
||||||
|
padBuffer = new byte[blockSize];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new NoSuchPaddingException("Unsupported padding " + padding);
|
throw new NoSuchPaddingException("Unsupported padding " + padding);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +251,7 @@ final class P11Cipher extends CipherSpi {
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected byte[] engineGetIV() {
|
protected byte[] engineGetIV() {
|
||||||
return (iv == null) ? null : (byte[])iv.clone();
|
return (iv == null) ? null : (byte[]) iv.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
|
@ -185,8 +261,9 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||||
try {
|
try {
|
||||||
AlgorithmParameters params = AlgorithmParameters.getInstance
|
AlgorithmParameters params =
|
||||||
(keyAlgorithm, P11Util.getSunJceProvider());
|
AlgorithmParameters.getInstance(keyAlgorithm,
|
||||||
|
P11Util.getSunJceProvider());
|
||||||
params.init(ivSpec);
|
params.init(ivSpec);
|
||||||
return params;
|
return params;
|
||||||
} catch (GeneralSecurityException e) {
|
} catch (GeneralSecurityException e) {
|
||||||
|
@ -210,38 +287,38 @@ final class P11Cipher extends CipherSpi {
|
||||||
protected void engineInit(int opmode, Key key,
|
protected void engineInit(int opmode, Key key,
|
||||||
AlgorithmParameterSpec params, SecureRandom random)
|
AlgorithmParameterSpec params, SecureRandom random)
|
||||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
byte[] iv;
|
byte[] ivValue;
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
if (params instanceof IvParameterSpec == false) {
|
if (params instanceof IvParameterSpec == false) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("Only IvParameterSpec supported");
|
("Only IvParameterSpec supported");
|
||||||
}
|
}
|
||||||
IvParameterSpec ivSpec = (IvParameterSpec)params;
|
IvParameterSpec ivSpec = (IvParameterSpec) params;
|
||||||
iv = ivSpec.getIV();
|
ivValue = ivSpec.getIV();
|
||||||
} else {
|
} else {
|
||||||
iv = null;
|
ivValue = null;
|
||||||
}
|
}
|
||||||
implInit(opmode, key, iv, random);
|
implInit(opmode, key, ivValue, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
protected void engineInit(int opmode, Key key, AlgorithmParameters params,
|
||||||
SecureRandom random)
|
SecureRandom random)
|
||||||
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
throws InvalidKeyException, InvalidAlgorithmParameterException {
|
||||||
byte[] iv;
|
byte[] ivValue;
|
||||||
if (params != null) {
|
if (params != null) {
|
||||||
try {
|
try {
|
||||||
IvParameterSpec ivSpec = (IvParameterSpec)
|
IvParameterSpec ivSpec = (IvParameterSpec)
|
||||||
params.getParameterSpec(IvParameterSpec.class);
|
params.getParameterSpec(IvParameterSpec.class);
|
||||||
iv = ivSpec.getIV();
|
ivValue = ivSpec.getIV();
|
||||||
} catch (InvalidParameterSpecException e) {
|
} catch (InvalidParameterSpecException e) {
|
||||||
throw new InvalidAlgorithmParameterException
|
throw new InvalidAlgorithmParameterException
|
||||||
("Could not decode IV", e);
|
("Could not decode IV", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
iv = null;
|
ivValue = null;
|
||||||
}
|
}
|
||||||
implInit(opmode, key, iv, random);
|
implInit(opmode, key, ivValue, random);
|
||||||
}
|
}
|
||||||
|
|
||||||
// actual init() implementation
|
// actual init() implementation
|
||||||
|
@ -331,63 +408,43 @@ final class P11Cipher extends CipherSpi {
|
||||||
session = token.getOpSession();
|
session = token.getOpSession();
|
||||||
}
|
}
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
token.p11.C_EncryptInit
|
token.p11.C_EncryptInit(session.id(),
|
||||||
(session.id(), new CK_MECHANISM(mechanism, iv), p11Key.keyID);
|
new CK_MECHANISM(mechanism, iv), p11Key.keyID);
|
||||||
} else {
|
} else {
|
||||||
token.p11.C_DecryptInit
|
token.p11.C_DecryptInit(session.id(),
|
||||||
(session.id(), new CK_MECHANISM(mechanism, iv), p11Key.keyID);
|
new CK_MECHANISM(mechanism, iv), p11Key.keyID);
|
||||||
}
|
}
|
||||||
bytesProcessed = 0;
|
bytesBuffered = 0;
|
||||||
|
padBufferLen = 0;
|
||||||
initialized = true;
|
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?
|
// if update(inLen) is called, how big does the output buffer have to be?
|
||||||
private int updateLength(int inLen) {
|
private int updateLength(int inLen) {
|
||||||
if (inLen <= 0) {
|
if (inLen <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (blockSize == 0) {
|
|
||||||
return inLen;
|
int result = inLen + bytesBuffered;
|
||||||
} else {
|
if (blockSize != 0) {
|
||||||
// bytes that need to be buffered now
|
// minus the number of bytes in the last incomplete block.
|
||||||
int buffered = bytesBuffered(bytesProcessed);
|
result -= (result & (blockSize - 1));
|
||||||
// bytes that need to be buffered after this update
|
|
||||||
int newBuffered = bytesBuffered(bytesProcessed + inLen);
|
|
||||||
return inLen + buffered - newBuffered;
|
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if doFinal(inLen) is called, how big does the output buffer have to be?
|
// if doFinal(inLen) is called, how big does the output buffer have to be?
|
||||||
private int doFinalLength(int inLen) {
|
private int doFinalLength(int inLen) {
|
||||||
if (paddingType == PAD_NONE) {
|
|
||||||
return updateLength(inLen);
|
|
||||||
}
|
|
||||||
if (inLen < 0) {
|
if (inLen < 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
int buffered = bytesBuffered(bytesProcessed);
|
|
||||||
int newProcessed = bytesProcessed + inLen;
|
int result = inLen + bytesBuffered;
|
||||||
int paddedProcessed = (newProcessed + blockSize) & ~(blockSize - 1);
|
if (blockSize != 0 && encrypt && paddingType != PAD_NONE) {
|
||||||
return paddedProcessed - bytesProcessed + buffered;
|
// add the number of bytes to make the last block complete.
|
||||||
|
result += (blockSize - (result & (blockSize - 1)));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
|
@ -397,6 +454,7 @@ final class P11Cipher extends CipherSpi {
|
||||||
int n = engineUpdate(in, inOfs, inLen, out, 0);
|
int n = engineUpdate(in, inOfs, inLen, out, 0);
|
||||||
return P11Util.convert(out, 0, n);
|
return P11Util.convert(out, 0, n);
|
||||||
} catch (ShortBufferException e) {
|
} catch (ShortBufferException e) {
|
||||||
|
// convert since the output length is calculated by updateLength()
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -409,6 +467,7 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
|
@Override
|
||||||
protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
protected int engineUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
||||||
throws ShortBufferException {
|
throws ShortBufferException {
|
||||||
return implUpdate(inBuffer, outBuffer);
|
return implUpdate(inBuffer, outBuffer);
|
||||||
|
@ -422,14 +481,15 @@ final class P11Cipher extends CipherSpi {
|
||||||
int n = engineDoFinal(in, inOfs, inLen, out, 0);
|
int n = engineDoFinal(in, inOfs, inLen, out, 0);
|
||||||
return P11Util.convert(out, 0, n);
|
return P11Util.convert(out, 0, n);
|
||||||
} catch (ShortBufferException e) {
|
} catch (ShortBufferException e) {
|
||||||
|
// convert since the output length is calculated by doFinalLength()
|
||||||
throw new ProviderException(e);
|
throw new ProviderException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
|
protected int engineDoFinal(byte[] in, int inOfs, int inLen, byte[] out,
|
||||||
int outOfs) throws ShortBufferException, IllegalBlockSizeException {
|
int outOfs) throws ShortBufferException, IllegalBlockSizeException,
|
||||||
// BadPaddingException {
|
BadPaddingException {
|
||||||
int n = 0;
|
int n = 0;
|
||||||
if ((inLen != 0) && (in != null)) {
|
if ((inLen != 0) && (in != null)) {
|
||||||
n = engineUpdate(in, inOfs, inLen, out, outOfs);
|
n = engineUpdate(in, inOfs, inLen, out, outOfs);
|
||||||
|
@ -440,8 +500,10 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
|
@Override
|
||||||
protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
protected int engineDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer)
|
||||||
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
int n = engineUpdate(inBuffer, outBuffer);
|
int n = engineUpdate(inBuffer, outBuffer);
|
||||||
n += implDoFinal(outBuffer);
|
n += implDoFinal(outBuffer);
|
||||||
return n;
|
return n;
|
||||||
|
@ -454,18 +516,55 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
int k;
|
int k = 0;
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
k = token.p11.C_EncryptUpdate
|
k = token.p11.C_EncryptUpdate(session.id(), 0, in, inOfs, inLen,
|
||||||
(session.id(), 0, in, inOfs, inLen, 0, out, outOfs, outLen);
|
0, out, outOfs, outLen);
|
||||||
} else {
|
} else {
|
||||||
k = token.p11.C_DecryptUpdate
|
int newPadBufferLen = 0;
|
||||||
(session.id(), 0, in, inOfs, inLen, 0, out, outOfs, outLen);
|
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;
|
||||||
}
|
}
|
||||||
bytesProcessed += inLen;
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytesBuffered += (inLen - k);
|
||||||
return k;
|
return k;
|
||||||
} catch (PKCS11Exception e) {
|
} 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);
|
throw new ProviderException("update() failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -481,56 +580,94 @@ final class P11Cipher extends CipherSpi {
|
||||||
if (outLen < updateLength(inLen)) {
|
if (outLen < updateLength(inLen)) {
|
||||||
throw new ShortBufferException();
|
throw new ShortBufferException();
|
||||||
}
|
}
|
||||||
boolean inPosChanged = false;
|
int origPos = inBuffer.position();
|
||||||
try {
|
try {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
|
|
||||||
long inAddr = 0;
|
long inAddr = 0;
|
||||||
int inOfs = inBuffer.position();
|
int inOfs = 0;
|
||||||
byte[] inArray = null;
|
byte[] inArray = null;
|
||||||
|
|
||||||
if (inBuffer instanceof DirectBuffer) {
|
if (inBuffer instanceof DirectBuffer) {
|
||||||
inAddr = ((DirectBuffer)inBuffer).address();
|
inAddr = ((DirectBuffer) inBuffer).address();
|
||||||
} else {
|
inOfs = origPos;
|
||||||
if (inBuffer.hasArray()) {
|
} else if (inBuffer.hasArray()) {
|
||||||
inArray = inBuffer.array();
|
inArray = inBuffer.array();
|
||||||
inOfs += inBuffer.arrayOffset();
|
inOfs = (origPos + inBuffer.arrayOffset());
|
||||||
} else {
|
|
||||||
inArray = new byte[inLen];
|
|
||||||
inBuffer.get(inArray);
|
|
||||||
inOfs = 0;
|
|
||||||
inPosChanged = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long outAddr = 0;
|
long outAddr = 0;
|
||||||
int outOfs = outBuffer.position();
|
int outOfs = 0;
|
||||||
byte[] outArray = null;
|
byte[] outArray = null;
|
||||||
if (outBuffer instanceof DirectBuffer) {
|
if (outBuffer instanceof DirectBuffer) {
|
||||||
outAddr = ((DirectBuffer)outBuffer).address();
|
outAddr = ((DirectBuffer) outBuffer).address();
|
||||||
|
outOfs = outBuffer.position();
|
||||||
} else {
|
} else {
|
||||||
if (outBuffer.hasArray()) {
|
if (outBuffer.hasArray()) {
|
||||||
outArray = outBuffer.array();
|
outArray = outBuffer.array();
|
||||||
outOfs += outBuffer.arrayOffset();
|
outOfs = (outBuffer.position() + outBuffer.arrayOffset());
|
||||||
} else {
|
} else {
|
||||||
outArray = new byte[outLen];
|
outArray = new byte[outLen];
|
||||||
outOfs = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int k;
|
int k = 0;
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
k = token.p11.C_EncryptUpdate
|
if (inAddr == 0 && inArray == null) {
|
||||||
(session.id(), inAddr, inArray, inOfs, inLen,
|
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);
|
outAddr, outArray, outOfs, outLen);
|
||||||
} else {
|
} else {
|
||||||
k = token.p11.C_DecryptUpdate
|
int newPadBufferLen = 0;
|
||||||
(session.id(), inAddr, inArray, inOfs, inLen,
|
if (paddingObj != null) {
|
||||||
outAddr, outArray, outOfs, outLen);
|
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;
|
||||||
}
|
}
|
||||||
bytesProcessed += inLen;
|
}
|
||||||
if (!inPosChanged) {
|
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);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytesBuffered += (inLen - k);
|
||||||
if (!(outBuffer instanceof DirectBuffer) &&
|
if (!(outBuffer instanceof DirectBuffer) &&
|
||||||
!outBuffer.hasArray()) {
|
!outBuffer.hasArray()) {
|
||||||
outBuffer.put(outArray, outOfs, k);
|
outBuffer.put(outArray, outOfs, k);
|
||||||
|
@ -539,43 +676,71 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
return k;
|
return k;
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
// Un-read the bytes back to input buffer
|
// Reset input buffer to its original position for
|
||||||
if (inPosChanged) {
|
inBuffer.position(origPos);
|
||||||
inBuffer.position(inBuffer.position() - inLen);
|
if (e.getErrorCode() == CKR_BUFFER_TOO_SMALL) {
|
||||||
|
throw (ShortBufferException)
|
||||||
|
(new ShortBufferException().initCause(e));
|
||||||
}
|
}
|
||||||
// XXX throw correct exception
|
|
||||||
throw new ProviderException("update() failed", e);
|
throw new ProviderException("update() failed", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int implDoFinal(byte[] out, int outOfs, int outLen)
|
private int implDoFinal(byte[] out, int outOfs, int outLen)
|
||||||
throws ShortBufferException, IllegalBlockSizeException {
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
if (outLen < doFinalLength(0)) {
|
BadPaddingException {
|
||||||
|
int requiredOutLen = doFinalLength(0);
|
||||||
|
if (outLen < requiredOutLen) {
|
||||||
throw new ShortBufferException();
|
throw new ShortBufferException();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
|
int k = 0;
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
return token.p11.C_EncryptFinal
|
if (paddingObj != null) {
|
||||||
(session.id(), 0, out, outOfs, outLen);
|
int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
|
||||||
} else {
|
requiredOutLen - bytesBuffered);
|
||||||
return token.p11.C_DecryptFinal
|
k = token.p11.C_EncryptUpdate(session.id(),
|
||||||
(session.id(), 0, out, outOfs, outLen);
|
0, padBuffer, 0, actualPadLen,
|
||||||
|
0, out, outOfs, outLen);
|
||||||
}
|
}
|
||||||
|
k += token.p11.C_EncryptFinal(session.id(),
|
||||||
|
0, out, (outOfs + k), (outLen - k));
|
||||||
|
} else {
|
||||||
|
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) {
|
} catch (PKCS11Exception e) {
|
||||||
handleException(e);
|
handleException(e);
|
||||||
throw new ProviderException("doFinal() failed", e);
|
throw new ProviderException("doFinal() failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
initialized = false;
|
initialized = false;
|
||||||
bytesProcessed = 0;
|
bytesBuffered = 0;
|
||||||
|
padBufferLen = 0;
|
||||||
session = token.releaseSession(session);
|
session = token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int implDoFinal(ByteBuffer outBuffer)
|
private int implDoFinal(ByteBuffer outBuffer)
|
||||||
throws ShortBufferException, IllegalBlockSizeException {
|
throws ShortBufferException, IllegalBlockSizeException,
|
||||||
|
BadPaddingException {
|
||||||
int outLen = outBuffer.remaining();
|
int outLen = outBuffer.remaining();
|
||||||
if (outLen < doFinalLength(0)) {
|
int requiredOutLen = doFinalLength(0);
|
||||||
|
if (outLen < requiredOutLen) {
|
||||||
throw new ShortBufferException();
|
throw new ShortBufferException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -583,30 +748,54 @@ final class P11Cipher extends CipherSpi {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
|
|
||||||
long outAddr = 0;
|
long outAddr = 0;
|
||||||
int outOfs = outBuffer.position();
|
|
||||||
byte[] outArray = null;
|
byte[] outArray = null;
|
||||||
|
int outOfs = 0;
|
||||||
if (outBuffer instanceof DirectBuffer) {
|
if (outBuffer instanceof DirectBuffer) {
|
||||||
outAddr = ((DirectBuffer)outBuffer).address();
|
outAddr = ((DirectBuffer) outBuffer).address();
|
||||||
|
outOfs = outBuffer.position();
|
||||||
} else {
|
} else {
|
||||||
if (outBuffer.hasArray()) {
|
if (outBuffer.hasArray()) {
|
||||||
outArray = outBuffer.array();
|
outArray = outBuffer.array();
|
||||||
outOfs += outBuffer.arrayOffset();
|
outOfs = outBuffer.position() + outBuffer.arrayOffset();
|
||||||
} else {
|
} else {
|
||||||
outArray = new byte[outLen];
|
outArray = new byte[outLen];
|
||||||
outOfs = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int k;
|
int k = 0;
|
||||||
|
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
k = token.p11.C_EncryptFinal
|
if (paddingObj != null) {
|
||||||
(session.id(), outAddr, outArray, outOfs, outLen);
|
int actualPadLen = paddingObj.setPaddingBytes(padBuffer,
|
||||||
} else {
|
requiredOutLen - bytesBuffered);
|
||||||
k = token.p11.C_DecryptFinal
|
k = token.p11.C_EncryptUpdate(session.id(),
|
||||||
(session.id(), outAddr, outArray, outOfs, outLen);
|
0, padBuffer, 0, actualPadLen,
|
||||||
|
outAddr, outArray, outOfs, outLen);
|
||||||
}
|
}
|
||||||
if (!(outBuffer instanceof DirectBuffer) &&
|
k += token.p11.C_EncryptFinal(session.id(),
|
||||||
!outBuffer.hasArray()) {
|
outAddr, outArray, (outOfs + k), (outLen - k));
|
||||||
|
} else {
|
||||||
|
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 ((!encrypt && paddingObj != null) ||
|
||||||
|
(!(outBuffer instanceof DirectBuffer) &&
|
||||||
|
!outBuffer.hasArray())) {
|
||||||
outBuffer.put(outArray, outOfs, k);
|
outBuffer.put(outArray, outOfs, k);
|
||||||
} else {
|
} else {
|
||||||
outBuffer.position(outBuffer.position() + k);
|
outBuffer.position(outBuffer.position() + k);
|
||||||
|
@ -617,20 +806,22 @@ final class P11Cipher extends CipherSpi {
|
||||||
throw new ProviderException("doFinal() failed", e);
|
throw new ProviderException("doFinal() failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
initialized = false;
|
initialized = false;
|
||||||
bytesProcessed = 0;
|
bytesBuffered = 0;
|
||||||
session = token.releaseSession(session);
|
session = token.releaseSession(session);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleException(PKCS11Exception e)
|
private void handleException(PKCS11Exception e)
|
||||||
throws IllegalBlockSizeException {
|
throws ShortBufferException, IllegalBlockSizeException {
|
||||||
long errorCode = e.getErrorCode();
|
long errorCode = e.getErrorCode();
|
||||||
// XXX better check
|
if (errorCode == CKR_BUFFER_TOO_SMALL) {
|
||||||
if (errorCode == CKR_DATA_LEN_RANGE) {
|
throw (ShortBufferException)
|
||||||
throw (IllegalBlockSizeException)new
|
(new ShortBufferException().initCause(e));
|
||||||
IllegalBlockSizeException(e.toString()).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
|
// see JCE spec
|
||||||
|
@ -649,12 +840,14 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
|
@Override
|
||||||
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
protected int engineGetKeySize(Key key) throws InvalidKeyException {
|
||||||
int n = P11SecretKeyFactory.convertKey
|
int n = P11SecretKeyFactory.convertKey
|
||||||
(token, key, keyAlgorithm).keyLength();
|
(token, key, keyAlgorithm).keyLength();
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
try {
|
try {
|
||||||
if ((session != null) && token.isValid()) {
|
if ((session != null) && token.isValid()) {
|
||||||
|
@ -666,4 +859,15 @@ final class P11Cipher extends CipherSpi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -65,10 +65,86 @@ final class P11KeyGenerator extends KeyGeneratorSpi {
|
||||||
// are supported.
|
// are supported.
|
||||||
private boolean supportBothKeySizes;
|
private boolean supportBothKeySizes;
|
||||||
|
|
||||||
// min and max key sizes (in bits) for variable-key-length
|
/**
|
||||||
// algorithms, e.g. RC4 and Blowfish
|
* Utility method for checking if the specified key size is valid
|
||||||
private int minKeySize;
|
* and within the supported range. Return the significant key size
|
||||||
private int maxKeySize;
|
* 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)
|
P11KeyGenerator(Token token, String algorithm, long mechanism)
|
||||||
throws PKCS11Exception {
|
throws PKCS11Exception {
|
||||||
|
@ -85,72 +161,44 @@ final class P11KeyGenerator extends KeyGeneratorSpi {
|
||||||
supportBothKeySizes =
|
supportBothKeySizes =
|
||||||
(token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
|
(token.provider.config.isEnabled(CKM_DES2_KEY_GEN) &&
|
||||||
(token.getMechanismInfo(CKM_DES2_KEY_GEN) != null));
|
(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();
|
setDefaultKeySize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// set default keysize and also initialize keyType
|
// set default keysize and also initialize keyType
|
||||||
private void setDefaultKeySize() {
|
private void setDefaultKeySize() {
|
||||||
// whether to check default key size against the min and max value
|
|
||||||
boolean validateKeySize = false;
|
|
||||||
switch ((int)mechanism) {
|
switch ((int)mechanism) {
|
||||||
case (int)CKM_DES_KEY_GEN:
|
case (int)CKM_DES_KEY_GEN:
|
||||||
keySize = 64;
|
keySize = 64;
|
||||||
significantKeySize = 56;
|
|
||||||
keyType = CKK_DES;
|
keyType = CKK_DES;
|
||||||
break;
|
break;
|
||||||
case (int)CKM_DES2_KEY_GEN:
|
case (int)CKM_DES2_KEY_GEN:
|
||||||
keySize = 128;
|
keySize = 128;
|
||||||
significantKeySize = 112;
|
|
||||||
keyType = CKK_DES2;
|
keyType = CKK_DES2;
|
||||||
break;
|
break;
|
||||||
case (int)CKM_DES3_KEY_GEN:
|
case (int)CKM_DES3_KEY_GEN:
|
||||||
keySize = 192;
|
keySize = 192;
|
||||||
significantKeySize = 168;
|
|
||||||
keyType = CKK_DES3;
|
keyType = CKK_DES3;
|
||||||
break;
|
break;
|
||||||
case (int)CKM_AES_KEY_GEN:
|
case (int)CKM_AES_KEY_GEN:
|
||||||
keyType = CKK_AES;
|
|
||||||
keySize = 128;
|
keySize = 128;
|
||||||
significantKeySize = 128;
|
keyType = CKK_AES;
|
||||||
break;
|
break;
|
||||||
case (int)CKM_RC4_KEY_GEN:
|
case (int)CKM_RC4_KEY_GEN:
|
||||||
keyType = CKK_RC4;
|
|
||||||
keySize = 128;
|
keySize = 128;
|
||||||
validateKeySize = true;
|
keyType = CKK_RC4;
|
||||||
break;
|
break;
|
||||||
case (int)CKM_BLOWFISH_KEY_GEN:
|
case (int)CKM_BLOWFISH_KEY_GEN:
|
||||||
keyType = CKK_BLOWFISH;
|
|
||||||
keySize = 128;
|
keySize = 128;
|
||||||
validateKeySize = true;
|
keyType = CKK_BLOWFISH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ProviderException("Unknown mechanism " + mechanism);
|
throw new ProviderException("Unknown mechanism " + mechanism);
|
||||||
}
|
}
|
||||||
if (validateKeySize &&
|
try {
|
||||||
((keySize > maxKeySize) || (keySize < minKeySize))) {
|
significantKeySize = checkKeySize(mechanism, keySize, token);
|
||||||
throw new ProviderException("Unsupported key size");
|
} catch (InvalidAlgorithmParameterException iape) {
|
||||||
|
throw new ProviderException("Unsupported default key size", iape);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,57 +218,32 @@ final class P11KeyGenerator extends KeyGeneratorSpi {
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected void engineInit(int keySize, SecureRandom random) {
|
protected void engineInit(int keySize, SecureRandom random) {
|
||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
switch ((int)mechanism) {
|
int newSignificantKeySize;
|
||||||
case (int)CKM_DES_KEY_GEN:
|
try {
|
||||||
if ((keySize != this.keySize) &&
|
newSignificantKeySize = checkKeySize(mechanism, keySize, token);
|
||||||
(keySize != this.significantKeySize)) {
|
} catch (InvalidAlgorithmParameterException iape) {
|
||||||
throw new InvalidParameterException
|
throw (InvalidParameterException)
|
||||||
("DES key length must be 56 bits");
|
(new InvalidParameterException().initCause(iape));
|
||||||
}
|
|
||||||
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");
|
|
||||||
}
|
}
|
||||||
|
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 (mechanism != newMechanism) {
|
||||||
if (supportBothKeySizes) {
|
if (supportBothKeySizes) {
|
||||||
mechanism = newMechanism;
|
mechanism = newMechanism;
|
||||||
setDefaultKeySize();
|
// Adjust keyType to reflect the mechanism change
|
||||||
|
keyType = (mechanism == CKM_DES2_KEY_GEN ?
|
||||||
|
CKK_DES2 : CKK_DES3);
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidParameterException
|
throw new InvalidParameterException
|
||||||
("Only " + significantKeySize +
|
("Only " + significantKeySize +
|
||||||
"-bit DESede key length is supported");
|
"-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;
|
this.keySize = keySize;
|
||||||
significantKeySize = keySize;
|
this.significantKeySize = newSignificantKeySize;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -156,10 +156,10 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
// CKA_CLASS - entry type
|
// CKA_CLASS - entry type
|
||||||
private CK_ATTRIBUTE type = null;
|
private CK_ATTRIBUTE type = null;
|
||||||
|
|
||||||
// CKA_LABEL of cert
|
// CKA_LABEL of cert and secret key
|
||||||
private String label = null;
|
private String label = null;
|
||||||
|
|
||||||
// CKA_ID - of private key/cert
|
// CKA_ID of the private key/cert pair
|
||||||
private byte[] id = null;
|
private byte[] id = null;
|
||||||
|
|
||||||
// CKA_TRUSTED - true if cert is trusted
|
// CKA_TRUSTED - true if cert is trusted
|
||||||
|
@ -871,10 +871,8 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
|
if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
|
||||||
token.provider.login(null, handler);
|
token.provider.login(null, handler);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// token supports protected authentication path
|
// token supports protected authentication path
|
||||||
// (external pin-pad, for example)
|
// (external pin-pad, for example)
|
||||||
|
|
||||||
if (handler != null &&
|
if (handler != null &&
|
||||||
!token.config.getKeyStoreCompatibilityMode()) {
|
!token.config.getKeyStoreCompatibilityMode()) {
|
||||||
throw new LoginException("can not specify password if token " +
|
throw new LoginException("can not specify password if token " +
|
||||||
|
@ -1130,19 +1128,14 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
SecretKey skey = ske.getSecretKey();
|
SecretKey skey = ske.getSecretKey();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// first see if the key already exists.
|
// first check if the key already exists
|
||||||
// if so, update the CKA_LABEL
|
AliasInfo aliasInfo = aliasMap.get(alias);
|
||||||
if (!updateSkey(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);
|
engineDeleteEntry(alias);
|
||||||
storeSkey(alias, ske);
|
|
||||||
}
|
}
|
||||||
|
storeSkey(alias, ske);
|
||||||
|
|
||||||
} catch (PKCS11Exception pe) {
|
} catch (PKCS11Exception pe) {
|
||||||
throw new KeyStoreException(pe);
|
throw new KeyStoreException(pe);
|
||||||
}
|
}
|
||||||
|
@ -1396,41 +1389,6 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
* XXX On ibutton, when you C_SetAttribute(CKA_ID) for a private key
|
||||||
|
@ -1532,30 +1490,6 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
private void updateP11Pkey(String alias, CK_ATTRIBUTE attribute, P11Key key)
|
||||||
throws PKCS11Exception {
|
throws PKCS11Exception {
|
||||||
|
|
||||||
|
@ -1689,48 +1623,26 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
throws PKCS11Exception, KeyStoreException {
|
throws PKCS11Exception, KeyStoreException {
|
||||||
|
|
||||||
SecretKey skey = ske.getSecretKey();
|
SecretKey skey = ske.getSecretKey();
|
||||||
long keyType = CKK_GENERIC_SECRET;
|
// No need to specify CKA_CLASS, CKA_KEY_TYPE, CKA_VALUE since
|
||||||
|
// they are handled in P11SecretKeyFactory.createKey() method.
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
|
||||||
ATTR_SKEY_TOKEN_TRUE,
|
ATTR_SKEY_TOKEN_TRUE,
|
||||||
ATTR_CLASS_SKEY,
|
|
||||||
ATTR_PRIVATE_TRUE,
|
ATTR_PRIVATE_TRUE,
|
||||||
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
|
||||||
new CK_ATTRIBUTE(CKA_LABEL, alias),
|
new CK_ATTRIBUTE(CKA_LABEL, alias),
|
||||||
new CK_ATTRIBUTE(CKA_VALUE, skey.getEncoded()) };
|
};
|
||||||
attrs = token.getAttributes
|
|
||||||
(TemplateManager.O_IMPORT, CKO_SECRET_KEY, keyType, attrs);
|
|
||||||
|
|
||||||
// create the new entry
|
|
||||||
Session session = null;
|
|
||||||
try {
|
try {
|
||||||
session = token.getOpSession();
|
P11SecretKeyFactory.convertKey(token, skey, null, attrs);
|
||||||
token.p11.C_CreateObject(session.id(), attrs);
|
} catch (InvalidKeyException ike) {
|
||||||
|
// re-throw KeyStoreException to match javadoc
|
||||||
|
throw new KeyStoreException("Cannot convert to PKCS11 keys", ike);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update global alias map
|
||||||
|
aliasMap.put(alias, new AliasInfo(alias));
|
||||||
|
|
||||||
if (debug != null) {
|
if (debug != null) {
|
||||||
debug.println("storeSkey created token secret key for [" +
|
debug.println("storeSkey created token secret key for [" +
|
||||||
alias +
|
alias + "]");
|
||||||
"]");
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
token.releaseSession(session);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2492,7 +2404,8 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
// if there are duplicates (either between secret keys,
|
// if there are duplicates (either between secret keys,
|
||||||
// or between a secret key and another object),
|
// or between a secret key and another object),
|
||||||
// throw an exception
|
// throw an exception
|
||||||
HashSet<String> sKeySet = new HashSet<String>();
|
HashMap<String, AliasInfo> sKeyMap =
|
||||||
|
new HashMap<String, AliasInfo>();
|
||||||
|
|
||||||
attrs = new CK_ATTRIBUTE[] {
|
attrs = new CK_ATTRIBUTE[] {
|
||||||
ATTR_SKEY_TOKEN_TRUE,
|
ATTR_SKEY_TOKEN_TRUE,
|
||||||
|
@ -2507,8 +2420,8 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
|
|
||||||
// there is a CKA_LABEL
|
// there is a CKA_LABEL
|
||||||
String cka_label = new String(attrs[0].getCharArray());
|
String cka_label = new String(attrs[0].getCharArray());
|
||||||
if (!sKeySet.contains(cka_label)) {
|
if (sKeyMap.get(cka_label) == null) {
|
||||||
sKeySet.add(cka_label);
|
sKeyMap.put(cka_label, new AliasInfo(cka_label));
|
||||||
} else {
|
} else {
|
||||||
throw new KeyStoreException("invalid KeyStore state: " +
|
throw new KeyStoreException("invalid KeyStore state: " +
|
||||||
"found multiple secret keys sharing same " +
|
"found multiple secret keys sharing same " +
|
||||||
|
@ -2523,7 +2436,7 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
ArrayList<AliasInfo> matchedCerts =
|
ArrayList<AliasInfo> matchedCerts =
|
||||||
mapPrivateKeys(pkeyIDs, certMap);
|
mapPrivateKeys(pkeyIDs, certMap);
|
||||||
boolean sharedLabel = mapCerts(matchedCerts, certMap);
|
boolean sharedLabel = mapCerts(matchedCerts, certMap);
|
||||||
mapSecretKeys(sKeySet);
|
mapSecretKeys(sKeyMap);
|
||||||
|
|
||||||
return sharedLabel;
|
return sharedLabel;
|
||||||
|
|
||||||
|
@ -2547,7 +2460,7 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
HashMap<String, HashSet<AliasInfo>> certMap)
|
HashMap<String, HashSet<AliasInfo>> certMap)
|
||||||
throws PKCS11Exception, CertificateException {
|
throws PKCS11Exception, CertificateException {
|
||||||
|
|
||||||
// global alias map
|
// reset global alias map
|
||||||
aliasMap = new HashMap<String, AliasInfo>();
|
aliasMap = new HashMap<String, AliasInfo>();
|
||||||
|
|
||||||
// list of matched certs that we will return
|
// list of matched certs that we will return
|
||||||
|
@ -2722,18 +2635,17 @@ final class P11KeyStore extends KeyStoreSpi {
|
||||||
* If the secret key shares a CKA_LABEL with another entry,
|
* If the secret key shares a CKA_LABEL with another entry,
|
||||||
* throw an exception
|
* throw an exception
|
||||||
*/
|
*/
|
||||||
private void mapSecretKeys(HashSet<String> sKeySet)
|
private void mapSecretKeys(HashMap<String, AliasInfo> sKeyMap)
|
||||||
throws KeyStoreException {
|
throws KeyStoreException {
|
||||||
for (String label : sKeySet) {
|
for (String label : sKeyMap.keySet()) {
|
||||||
if (!aliasMap.containsKey(label)) {
|
if (aliasMap.containsKey(label)) {
|
||||||
aliasMap.put(label, new AliasInfo(label));
|
|
||||||
} else {
|
|
||||||
throw new KeyStoreException("invalid KeyStore state: " +
|
throw new KeyStoreException("invalid KeyStore state: " +
|
||||||
"found secret key sharing CKA_LABEL [" +
|
"found secret key sharing CKA_LABEL [" +
|
||||||
label +
|
label +
|
||||||
"] with another token object");
|
"] with another token object");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
aliasMap.putAll(sKeyMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dumpTokenMap() {
|
private void dumpTokenMap() {
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -98,7 +98,6 @@ final class P11RSACipher extends CipherSpi {
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.algorithm = "RSA";
|
this.algorithm = "RSA";
|
||||||
this.mechanism = mechanism;
|
this.mechanism = mechanism;
|
||||||
session = token.getOpSession();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// modes do not make sense for RSA, but allow ECB
|
// modes do not make sense for RSA, but allow ECB
|
||||||
|
@ -184,7 +183,8 @@ final class P11RSACipher extends CipherSpi {
|
||||||
throw new InvalidKeyException
|
throw new InvalidKeyException
|
||||||
("Wrap has to be used with public keys");
|
("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;
|
return;
|
||||||
} else if (opmode == Cipher.UNWRAP_MODE) {
|
} else if (opmode == Cipher.UNWRAP_MODE) {
|
||||||
if (p11Key.isPrivate() == false) {
|
if (p11Key.isPrivate() == false) {
|
||||||
|
@ -383,7 +383,8 @@ final class P11RSACipher extends CipherSpi {
|
||||||
return implDoFinal(out, outOfs, out.length - outOfs);
|
return implDoFinal(out, outOfs, out.length - outOfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] doFinal() throws BadPaddingException, IllegalBlockSizeException {
|
private byte[] doFinal() throws BadPaddingException,
|
||||||
|
IllegalBlockSizeException {
|
||||||
byte[] t = new byte[2048];
|
byte[] t = new byte[2048];
|
||||||
int n = implDoFinal(t, 0, t.length);
|
int n = implDoFinal(t, 0, t.length);
|
||||||
byte[] out = new byte[n];
|
byte[] out = new byte[n];
|
||||||
|
@ -394,20 +395,37 @@ final class P11RSACipher extends CipherSpi {
|
||||||
// see JCE spec
|
// see JCE spec
|
||||||
protected byte[] engineWrap(Key key) throws InvalidKeyException,
|
protected byte[] engineWrap(Key key) throws InvalidKeyException,
|
||||||
IllegalBlockSizeException {
|
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();
|
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;
|
Session s = null;
|
||||||
try {
|
try {
|
||||||
s = token.getOpSession();
|
s = token.getOpSession();
|
||||||
byte[] b = token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
|
return token.p11.C_WrapKey(s.id(), new CK_MECHANISM(mechanism),
|
||||||
p11Key.keyID, secretKey.keyID);
|
p11Key.keyID, sKey.keyID);
|
||||||
return b;
|
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new InvalidKeyException("wrap() failed", e);
|
throw new InvalidKeyException("wrap() failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -431,11 +449,13 @@ final class P11RSACipher extends CipherSpi {
|
||||||
};
|
};
|
||||||
attributes = token.getAttributes
|
attributes = token.getAttributes
|
||||||
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
||||||
long keyID = token.p11.C_UnwrapKey(s.id(), new CK_MECHANISM(mechanism),
|
long keyID = token.p11.C_UnwrapKey(s.id(),
|
||||||
p11Key.keyID, wrappedKey, attributes);
|
new CK_MECHANISM(mechanism), p11Key.keyID, wrappedKey,
|
||||||
return P11Key.secretKey(session, keyID, algorithm, 48 << 3, attributes);
|
attributes);
|
||||||
|
return P11Key.secretKey(session, keyID, algorithm, 48 << 3,
|
||||||
|
attributes);
|
||||||
} catch (PKCS11Exception e) {
|
} catch (PKCS11Exception e) {
|
||||||
throw new InvalidKeyException("wrap() failed", e);
|
throw new InvalidKeyException("unwrap() failed", e);
|
||||||
} finally {
|
} finally {
|
||||||
token.releaseSession(s);
|
token.releaseSession(s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -104,9 +104,20 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an arbitrary key of algorithm into a P11Key of provider.
|
* 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 {
|
throws InvalidKeyException {
|
||||||
token.ensureValid();
|
token.ensureValid();
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
|
@ -115,25 +126,41 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
if (key instanceof SecretKey == false) {
|
if (key instanceof SecretKey == false) {
|
||||||
throw new InvalidKeyException("Key must be a SecretKey");
|
throw new InvalidKeyException("Key must be a SecretKey");
|
||||||
}
|
}
|
||||||
long algorithmType;
|
long algoType;
|
||||||
if (algorithm == null) {
|
if (algo == null) {
|
||||||
algorithm = key.getAlgorithm();
|
algo = key.getAlgorithm();
|
||||||
algorithmType = getKeyType(algorithm);
|
algoType = getKeyType(algo);
|
||||||
} else {
|
} else {
|
||||||
algorithmType = getKeyType(algorithm);
|
algoType = getKeyType(algo);
|
||||||
long keyAlgorithmType = getKeyType(key.getAlgorithm());
|
long keyAlgorithmType = getKeyType(key.getAlgorithm());
|
||||||
if (algorithmType != keyAlgorithmType) {
|
if (algoType != keyAlgorithmType) {
|
||||||
if ((algorithmType == PCKK_HMAC) || (algorithmType == PCKK_SSLMAC)) {
|
if ((algoType == PCKK_HMAC) || (algoType == PCKK_SSLMAC)) {
|
||||||
// ignore key algorithm for MACs
|
// ignore key algorithm for MACs
|
||||||
} else {
|
} else {
|
||||||
throw new InvalidKeyException
|
throw new InvalidKeyException
|
||||||
("Key algorithm must be " + algorithm);
|
("Key algorithm must be " + algo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (key instanceof P11Key) {
|
if (key instanceof P11Key) {
|
||||||
P11Key p11Key = (P11Key)key;
|
P11Key p11Key = (P11Key)key;
|
||||||
if (p11Key.token == token) {
|
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;
|
return p11Key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,11 +168,11 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
if (p11Key != null) {
|
if (p11Key != null) {
|
||||||
return p11Key;
|
return p11Key;
|
||||||
}
|
}
|
||||||
if ("RAW".equals(key.getFormat()) == false) {
|
if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
|
||||||
throw new InvalidKeyException("Encoded format must be RAW");
|
throw new InvalidKeyException("Encoded format must be RAW");
|
||||||
}
|
}
|
||||||
byte[] encoded = key.getEncoded();
|
byte[] encoded = key.getEncoded();
|
||||||
p11Key = createKey(token, encoded, algorithm, algorithmType);
|
p11Key = createKey(token, encoded, algo, algoType, extraAttrs);
|
||||||
token.secretCache.put(key, p11Key);
|
token.secretCache.put(key, p11Key);
|
||||||
return p11Key;
|
return p11Key;
|
||||||
}
|
}
|
||||||
|
@ -159,59 +186,47 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static P11Key createKey(Token token, byte[] encoded,
|
private static P11Key createKey(Token token, byte[] encoded,
|
||||||
String algorithm, long keyType) throws InvalidKeyException {
|
String algorithm, long keyType, CK_ATTRIBUTE[] extraAttrs)
|
||||||
int n = encoded.length;
|
throws InvalidKeyException {
|
||||||
int keyLength;
|
int n = encoded.length << 3;
|
||||||
|
int keyLength = n;
|
||||||
|
try {
|
||||||
switch ((int)keyType) {
|
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:
|
case (int)CKK_DES:
|
||||||
if (n != 8) {
|
keyLength =
|
||||||
throw new InvalidKeyException
|
P11KeyGenerator.checkKeySize(CKM_DES_KEY_GEN, n, token);
|
||||||
("DES key length must be 8 bytes");
|
|
||||||
}
|
|
||||||
keyLength = 56;
|
|
||||||
fixDESParity(encoded, 0);
|
fixDESParity(encoded, 0);
|
||||||
break;
|
break;
|
||||||
case (int)CKK_DES3:
|
case (int)CKK_DES3:
|
||||||
if (n == 16) {
|
keyLength =
|
||||||
keyType = CKK_DES2;
|
P11KeyGenerator.checkKeySize(CKM_DES3_KEY_GEN, n, token);
|
||||||
} else if (n == 24) {
|
|
||||||
keyType = CKK_DES3;
|
|
||||||
fixDESParity(encoded, 16);
|
|
||||||
} else {
|
|
||||||
throw new InvalidKeyException
|
|
||||||
("DESede key length must be 16 or 24 bytes");
|
|
||||||
}
|
|
||||||
fixDESParity(encoded, 0);
|
fixDESParity(encoded, 0);
|
||||||
fixDESParity(encoded, 8);
|
fixDESParity(encoded, 8);
|
||||||
keyLength = n * 7;
|
if (keyLength == 112) {
|
||||||
|
keyType = CKK_DES2;
|
||||||
|
} else {
|
||||||
|
keyType = CKK_DES3;
|
||||||
|
fixDESParity(encoded, 16);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case (int)CKK_AES:
|
case (int)CKK_AES:
|
||||||
if ((n != 16) && (n != 24) && (n != 32)) {
|
keyLength =
|
||||||
throw new InvalidKeyException
|
P11KeyGenerator.checkKeySize(CKM_AES_KEY_GEN, n, token);
|
||||||
("AES key length must be 16, 24, or 32 bytes");
|
break;
|
||||||
}
|
case (int)CKK_RC4:
|
||||||
keyLength = n << 3;
|
keyLength =
|
||||||
|
P11KeyGenerator.checkKeySize(CKM_RC4_KEY_GEN, n, token);
|
||||||
break;
|
break;
|
||||||
case (int)CKK_BLOWFISH:
|
case (int)CKK_BLOWFISH:
|
||||||
if ((n < 5) || (n > 56)) {
|
keyLength =
|
||||||
throw new InvalidKeyException
|
P11KeyGenerator.checkKeySize(CKM_BLOWFISH_KEY_GEN, n,
|
||||||
("Blowfish key length must be between 5 and 56 bytes");
|
token);
|
||||||
}
|
|
||||||
keyLength = n << 3;
|
|
||||||
break;
|
break;
|
||||||
case (int)CKK_GENERIC_SECRET:
|
case (int)CKK_GENERIC_SECRET:
|
||||||
case (int)PCKK_TLSPREMASTER:
|
case (int)PCKK_TLSPREMASTER:
|
||||||
case (int)PCKK_TLSRSAPREMASTER:
|
case (int)PCKK_TLSRSAPREMASTER:
|
||||||
case (int)PCKK_TLSMASTER:
|
case (int)PCKK_TLSMASTER:
|
||||||
keyType = CKK_GENERIC_SECRET;
|
keyType = CKK_GENERIC_SECRET;
|
||||||
keyLength = n << 3;
|
|
||||||
break;
|
break;
|
||||||
case (int)PCKK_SSLMAC:
|
case (int)PCKK_SSLMAC:
|
||||||
case (int)PCKK_HMAC:
|
case (int)PCKK_HMAC:
|
||||||
|
@ -220,18 +235,30 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
("MAC keys must not be empty");
|
("MAC keys must not be empty");
|
||||||
}
|
}
|
||||||
keyType = CKK_GENERIC_SECRET;
|
keyType = CKK_GENERIC_SECRET;
|
||||||
keyLength = n << 3;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new InvalidKeyException("Unknown algorithm " + algorithm);
|
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;
|
Session session = null;
|
||||||
try {
|
try {
|
||||||
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
|
CK_ATTRIBUTE[] attributes;
|
||||||
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
|
if (extraAttrs != null) {
|
||||||
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
|
attributes = new CK_ATTRIBUTE[3 + extraAttrs.length];
|
||||||
new CK_ATTRIBUTE(CKA_VALUE, encoded),
|
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
|
attributes = token.getAttributes
|
||||||
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
|
||||||
session = token.getObjSession();
|
session = token.getObjSession();
|
||||||
|
@ -280,7 +307,7 @@ final class P11SecretKeyFactory extends SecretKeyFactorySpi {
|
||||||
private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException {
|
private byte[] getKeyBytes(SecretKey key) throws InvalidKeySpecException {
|
||||||
try {
|
try {
|
||||||
key = engineTranslateKey(key);
|
key = engineTranslateKey(key);
|
||||||
if ("RAW".equals(key.getFormat()) == false) {
|
if ("RAW".equalsIgnoreCase(key.getFormat()) == false) {
|
||||||
throw new InvalidKeySpecException
|
throw new InvalidKeySpecException
|
||||||
("Could not obtain key bytes");
|
("Could not obtain key bytes");
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -601,14 +601,26 @@ public final class SunPKCS11 extends AuthProvider {
|
||||||
// XXX attributes for Ciphers (supported modes, padding)
|
// XXX attributes for Ciphers (supported modes, padding)
|
||||||
d(CIP, "ARCFOUR", P11Cipher, s("RC4"),
|
d(CIP, "ARCFOUR", P11Cipher, s("RC4"),
|
||||||
m(CKM_RC4));
|
m(CKM_RC4));
|
||||||
// XXX only CBC/NoPadding for block ciphers
|
|
||||||
d(CIP, "DES/CBC/NoPadding", P11Cipher,
|
d(CIP, "DES/CBC/NoPadding", P11Cipher,
|
||||||
m(CKM_DES_CBC));
|
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,
|
d(CIP, "DESede/CBC/NoPadding", P11Cipher,
|
||||||
m(CKM_DES3_CBC));
|
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,
|
d(CIP, "AES/CBC/NoPadding", P11Cipher,
|
||||||
m(CKM_AES_CBC));
|
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));
|
m(CKM_BLOWFISH_CBC));
|
||||||
|
|
||||||
// XXX RSA_X_509, RSA_OAEP not yet supported
|
// XXX RSA_X_509, RSA_OAEP not yet supported
|
||||||
|
|
|
@ -87,6 +87,9 @@ class EndEntityChecker {
|
||||||
// the Microsoft Server-Gated-Cryptography EKU extension OID
|
// 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";
|
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 =
|
private final static String NSCT_SSL_CLIENT =
|
||||||
NetscapeCertTypeExtension.SSL_CLIENT;
|
NetscapeCertTypeExtension.SSL_CLIENT;
|
||||||
|
|
||||||
|
@ -171,6 +174,13 @@ class EndEntityChecker {
|
||||||
throws CertificateException {
|
throws CertificateException {
|
||||||
// basic constraints irrelevant in EE certs
|
// basic constraints irrelevant in EE certs
|
||||||
exts.remove(SimpleValidator.OID_BASIC_CONSTRAINTS);
|
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()) {
|
if (!exts.isEmpty()) {
|
||||||
throw new CertificateException("Certificate contains unsupported "
|
throw new CertificateException("Certificate contains unsupported "
|
||||||
+ "critical extensions: " + exts);
|
+ "critical extensions: " + exts);
|
||||||
|
|
|
@ -123,7 +123,10 @@ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_connect
|
||||||
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr);
|
C_GetFunctionList = (CK_C_GetFunctionList) dlsym(hModule, getFunctionListStr);
|
||||||
(*env)->ReleaseStringUTFChars(env, jGetFunctionList, 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);
|
throwIOException(env, systemErrorMessage);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -46,9 +46,7 @@ public class TestGetInstance {
|
||||||
|
|
||||||
Cipher c;
|
Cipher c;
|
||||||
|
|
||||||
c = Cipher.getInstance("des");
|
c = Cipher.getInstance("PBEWithMD5AndTripleDES");
|
||||||
same(p, c.getProvider());
|
|
||||||
c = Cipher.getInstance("des/cbc/pkcs5padding");
|
|
||||||
same(p, c.getProvider());
|
same(p, c.getProvider());
|
||||||
|
|
||||||
c = Cipher.getInstance("des", "SunJCE");
|
c = Cipher.getInstance("des", "SunJCE");
|
||||||
|
|
109
jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
Normal file
109
jdk/test/sun/security/pkcs11/Cipher/TestRSACipherWrap.java
Normal file
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
282
jdk/test/sun/security/pkcs11/Cipher/TestSymmCiphers.java
Normal file
282
jdk/test/sun/security/pkcs11/Cipher/TestSymmCiphers.java
Normal file
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
194
jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java
Normal file
194
jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.java
Normal file
|
@ -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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
164
jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh
Normal file
164
jdk/test/sun/security/pkcs11/KeyStore/SecretKeysBasic.sh
Normal file
|
@ -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}
|
|
@ -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 not shown.
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue